init commit
This commit is contained in:
621
libs/phantombot/web/ytplayer/js/index.js
Normal file
621
libs/phantombot/web/ytplayer/js/index.js
Normal file
@@ -0,0 +1,621 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author ScaniaTV
|
||||
*/
|
||||
|
||||
/*
|
||||
* Main player functions and listeners.
|
||||
*
|
||||
* Every global functions should be added under the "player" object.
|
||||
* The iframe API from YouTube can be accessed from "player.API".
|
||||
* Basic information about the current song can be access with "player.temp.song", "player.temp.title", and "player.temp.requester".
|
||||
* For more functions under the "player" object, take a look at the socket.js script.
|
||||
* You can also generate modals with jQuery, see util/helpers.js for more information.
|
||||
*/
|
||||
$(function() {
|
||||
var cluster = null,
|
||||
timer = null;
|
||||
|
||||
/*
|
||||
* @function Loads the player page.
|
||||
*
|
||||
* @param {boolean} hasPlaylistData - If a playlist is loaded.
|
||||
*/
|
||||
const openPlayer = hasPlaylistData => {
|
||||
$('.loader').fadeOut(6e2, () => {
|
||||
$(this).remove();
|
||||
});
|
||||
// Show the page.
|
||||
$('#main').fadeIn(5e2);
|
||||
|
||||
if (!hasPlaylistData && player.hasAPIKey() && !player.secondConnection) {
|
||||
toastr.error('Failed to load a playlist with songs.');
|
||||
|
||||
// Create a fake progress slider.
|
||||
player.progressSlider = $('#progress-slider').slider({
|
||||
'value': 0,
|
||||
'min': 0,
|
||||
'step': 0.1,
|
||||
'tooltip': 'hide',
|
||||
'selection': 'none'
|
||||
});
|
||||
|
||||
// Error the to user.
|
||||
helpers.getErrorModal('Playlist Error', 'Failed to load a playlist with songs, please load a playlist.', () => {
|
||||
player.dbQuery('get_playlists', 'yt_playlists_registry', (results) => {
|
||||
// Get the keys.
|
||||
results = Object.keys(results);
|
||||
const playlists = [];
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
if (results[i].indexOf('ytPlaylist_') !== -1) {
|
||||
playlists.push(results[i].substr(results[i].indexOf('_') + 1, results[i].length));
|
||||
}
|
||||
}
|
||||
|
||||
helpers.getPlaylistModal('Load Playlist', 'Playlist Name', 'Load', 'Playlist', playlists, () => {
|
||||
let playlist = $('#playlist-load').find(':selected').text();
|
||||
|
||||
if (playlist === 'Select a playlist') {
|
||||
toastr.error('Please select a valid playlist.');
|
||||
} else {
|
||||
if (playlist.length > 0) {
|
||||
player.loadPlaylist(playlist);
|
||||
toastr.success('Loading playlist: ' + playlist);
|
||||
|
||||
if (player.firstLoad === true) {
|
||||
player.ready();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).modal('toggle');
|
||||
});
|
||||
}).modal('toggle');
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Global function that is called once the socket is connected and that the YouTube iframe is loaded.
|
||||
*/
|
||||
window.onYouTubeIframeAPIReady = () => {
|
||||
// Set a timer in case no songs load to send a error.
|
||||
timer = setTimeout(openPlayer, 5e3, false);
|
||||
|
||||
// Set a var for the slider.
|
||||
player.canSlide = true;
|
||||
// Set a var for the first load.
|
||||
player.firstLoad = true;
|
||||
|
||||
// Check if the player is disabled right away.
|
||||
player.dbQuery('get_module_status', 'modules', (data) => {
|
||||
if (data['./systems/youtubePlayer.js'] == 'false') {
|
||||
helpers.getErrorModal('Module Disabled', 'The YouTube player module is disabled, please go and enable it.', () => {
|
||||
window.location.reload();
|
||||
}).modal('toggle');
|
||||
|
||||
openPlayer(true);
|
||||
clearTimeout(timer);
|
||||
}
|
||||
});
|
||||
|
||||
// Add a listener to load the main playlist.
|
||||
player.addListener('playlist', (e) => {
|
||||
let table = [],
|
||||
playlist = e.playlist;
|
||||
|
||||
// Set the playlist name.
|
||||
$('#playlist-name').html('(' + e.playlistname + ')');
|
||||
|
||||
// Table header.
|
||||
table.push(($('<tr>').append($('<th/>', {
|
||||
'style': 'width: 5%;',
|
||||
'html': '#'
|
||||
})).append($('<th/>', {
|
||||
'style': 'width: 70%;',
|
||||
'html': 'Song'
|
||||
})).append($('<th/>', {
|
||||
'style': 'width: 15%;',
|
||||
'html': 'Duration'
|
||||
})).append($('<th/>', {
|
||||
'style': 'width: 10%; text-align: right; padding-right: 16px;',
|
||||
'html': 'Actions'
|
||||
}))).html());
|
||||
|
||||
for (let i = 0; i < playlist.length; i++) {
|
||||
let row = $('<tr/>');
|
||||
|
||||
// Add position.
|
||||
row.append($('<td/>', {
|
||||
'text': i,
|
||||
'style': 'width: 5%;'
|
||||
}));
|
||||
|
||||
// Add song name.
|
||||
row.append($('<td/>', {
|
||||
'text': playlist[i].title,
|
||||
'style': 'width: 70%;'
|
||||
}));
|
||||
|
||||
// Add duration.
|
||||
row.append($('<td/>', {
|
||||
'text': playlist[i].duration,
|
||||
'style': 'width: 15%;'
|
||||
}));
|
||||
|
||||
// Add buttons.
|
||||
row.append($('<td/>', {
|
||||
'html': $('<div/>', {
|
||||
'class': 'btn-group btn-group-justified header-button'
|
||||
}).append($('<button/>', {
|
||||
'type': 'button',
|
||||
'class': 'btn btn-secondary btn-sm',
|
||||
'data-toggle': 'tooltip',
|
||||
'title': 'Play song',
|
||||
'data-song': playlist[i].song,
|
||||
'data-song-play': 'on',
|
||||
'html': $('<i/>', {
|
||||
'class': 'fas fa-play'
|
||||
})
|
||||
})).append($('<button/>', {
|
||||
'type': 'button',
|
||||
'class': 'btn btn-secondary btn-sm',
|
||||
'data-toggle': 'tooltip',
|
||||
'title': 'Delete song',
|
||||
'data-song': playlist[i].song,
|
||||
'data-song-remove': 'on',
|
||||
'html': $('<i/>', {
|
||||
'class': 'fas fa-trash'
|
||||
})
|
||||
})),
|
||||
'style': 'width: 10%;'
|
||||
}));
|
||||
|
||||
// Append the row.
|
||||
table.push(row[0].outerHTML);
|
||||
}
|
||||
|
||||
// Render the data.
|
||||
if (cluster !== null) {
|
||||
cluster.update(table);
|
||||
} else {
|
||||
cluster = new Clusterize({
|
||||
rows: table,
|
||||
scrollId: 'playlist-table-id',
|
||||
contentId: 'playlist-content',
|
||||
callbacks: {
|
||||
clusterChanged: () => {
|
||||
// Remove old events and register new ones.
|
||||
$('[data-song-play="on"]').off().on('click', (e) => {
|
||||
// Play the song.
|
||||
player.updateSong($(e.currentTarget).data('song'));
|
||||
// Hide the tooltip.
|
||||
$(e.currentTarget).tooltip('hide');
|
||||
});
|
||||
|
||||
// Remove old events and register new ones.
|
||||
$('[data-song-remove="on"]').off().on('click', (e) => {
|
||||
// Delete the song.
|
||||
player.removeSongFromPlaylist($(e.currentTarget).data('song'));
|
||||
// Hide the tooltip.
|
||||
$(e.currentTarget).tooltip('hide');
|
||||
// Remove the row.
|
||||
$(e.currentTarget.closest('tr')).remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Add a listener for the songrequest queue.
|
||||
player.addListener('songlist', (e) => {
|
||||
let table = $('#queue-table-content'),
|
||||
songlist = e.songlist;
|
||||
|
||||
// Remove the current data from the table.
|
||||
table.find('tr:gt(0)').remove();
|
||||
|
||||
for (let i = 0; i < songlist.length; i++) {
|
||||
let row = $('<tr/>');
|
||||
|
||||
// Add position.
|
||||
row.append($('<td/>', {
|
||||
'text': i
|
||||
}));
|
||||
|
||||
// Add song name.
|
||||
row.append($('<td/>', {
|
||||
'text': songlist[i].title
|
||||
}));
|
||||
|
||||
// Add duration.
|
||||
row.append($('<td/>', {
|
||||
'text': songlist[i].duration
|
||||
}));
|
||||
|
||||
// Add requester.
|
||||
row.append($('<td/>', {
|
||||
'text': songlist[i].requester
|
||||
}));
|
||||
|
||||
// Add buttons.
|
||||
row.append($('<td/>', {
|
||||
'html': $('<div/>', {
|
||||
'class': 'btn-group btn-group-justified header-button'
|
||||
}).append($('<button/>', {
|
||||
'type': 'button',
|
||||
'class': 'btn btn-secondary btn-sm',
|
||||
'data-toggle': 'tooltip',
|
||||
'data-song': songlist[i].song,
|
||||
'title': 'Play song',
|
||||
'html': $('<i/>', {
|
||||
'class': 'fas fa-play'
|
||||
}),
|
||||
'click': (e) => {
|
||||
// Jump to the song.
|
||||
player.updateSong($(e.currentTarget).data('song'));
|
||||
// The song once jumped to it.
|
||||
player.removeSongFromRequest($(e.currentTarget).data('song'));
|
||||
// Hide the tooltip, or could stay opened.
|
||||
$(e.currentTarget).tooltip('hide');
|
||||
}
|
||||
})).append($('<button/>', {
|
||||
'type': 'button',
|
||||
'class': 'btn btn-secondary btn-sm',
|
||||
'data-toggle': 'tooltip',
|
||||
'title': 'Delete song',
|
||||
'data-song': songlist[i].song,
|
||||
'html': $('<i/>', {
|
||||
'class': 'fas fa-trash'
|
||||
}),
|
||||
'click': (e) => {
|
||||
// Delete song.
|
||||
player.removeSongFromRequest($(e.currentTarget).data('song'));
|
||||
// Hide the tooltip, or could stay opened.
|
||||
$(e.currentTarget).tooltip('hide');
|
||||
}
|
||||
}))
|
||||
}));
|
||||
|
||||
// Append the row.
|
||||
table.append(row);
|
||||
}
|
||||
});
|
||||
|
||||
// Add a listener for the volume.
|
||||
player.addListener('setvolume', (e) => {
|
||||
player.API.setVolume(e.setvolume);
|
||||
|
||||
// Update the value under the slider.
|
||||
$('#volume-slider-value').html(e.setvolume + '%');
|
||||
|
||||
// Update the icon.
|
||||
$('#mute-button-icon').attr('class', (e.setvolume === 0 ? 'fas fa-volume-off' : (e.setvolume > 50 ? 'fas fa-volume-up' : 'fas fa-volume-down')));
|
||||
|
||||
// Always destroy the old slider.
|
||||
if (player.volumeSlider !== undefined) {
|
||||
player.volumeSlider.slider('destroy');
|
||||
}
|
||||
|
||||
// Add the volume slider event.
|
||||
player.volumeSlider = $('#volume-slider').slider({
|
||||
'value': e.setvolume,
|
||||
'min': 0,
|
||||
'max': 100,
|
||||
'step': 1,
|
||||
'tooltip': 'hide'
|
||||
}).on('slide', (e) => {
|
||||
// Make sure the player wasn't muted.
|
||||
if (player.API.isMuted()) {
|
||||
player.API.unMute();
|
||||
}
|
||||
// Update the player volume
|
||||
player.API.setVolume(e.value);
|
||||
// Update the value under the slider.
|
||||
$('#volume-slider-value').html(e.value + '%');
|
||||
// Update the icon.
|
||||
$('#mute-button-icon').attr('class', (e.value === 0 ? 'fas fa-volume-off' : (e.value > 50 ? 'fas fa-volume-up' : 'fas fa-volume-down')));
|
||||
}).on('slideStop', (e) => {
|
||||
// Update the player volume
|
||||
player.API.setVolume(e.value);
|
||||
// Send the volume update event to the bot once done updating.
|
||||
player.updateVolume(e.value);
|
||||
// Update the value under the slider.
|
||||
$('#volume-slider-value').html(e.value + '%');
|
||||
// Update the icon.
|
||||
$('#mute-button-icon').attr('class', (e.value === 0 ? 'fas fa-volume-off' : (e.value > 50 ? 'fas fa-volume-up' : 'fas fa-volume-down')));
|
||||
});
|
||||
});
|
||||
|
||||
// Add a listener for the play event.
|
||||
player.addListener('play', (e) => {
|
||||
// If this is the first load, start the player paused.
|
||||
if (player.firstLoad === true) {
|
||||
// Queue the first video
|
||||
player.API.cueVideoById(e.play, 0, 'medium');
|
||||
// Mark as not first load.
|
||||
player.firstLoad = false;
|
||||
// Clear timer
|
||||
clearTimeout(timer);
|
||||
// Remove loader.
|
||||
openPlayer(true);
|
||||
// Alert the user.
|
||||
toastr.info('Song queued: ' + (e.title.length > 30 ? e.title.substring(0, 30) + '...' : e.title));
|
||||
} else {
|
||||
player.API.loadVideoById(e.play, 0, 'medium');
|
||||
toastr.success('Now playing: ' + (e.title.length > 30 ? e.title.substring(0, 30) + '...' : e.title));
|
||||
}
|
||||
|
||||
// Update the value under the slider.
|
||||
$('#progress-slider-value').html(e.duration);
|
||||
|
||||
// Always destroy the old slider.
|
||||
if (player.progressSlider !== undefined) {
|
||||
player.progressSlider.slider('destroy');
|
||||
}
|
||||
|
||||
// Add progress slider event.
|
||||
player.progressSlider = $('#progress-slider').slider({
|
||||
'value': 0,
|
||||
'min': 0,
|
||||
'step': 0.1,
|
||||
'tooltip': 'hide',
|
||||
'selection': 'none'
|
||||
}).on('slide', (e) => {
|
||||
player.API.seekTo(e.value, true);
|
||||
}).on('slideStart', () => {
|
||||
player.canSlide = false;
|
||||
}).on('slideStop', () => {
|
||||
player.canSlide = true;
|
||||
});
|
||||
|
||||
// Update title information.
|
||||
$('#video-title').html(e.title);
|
||||
$('#video-url').html('<a href="https://youtu.be/' + e.play + '" target="_blank">https://youtu.be/' + e.play + '</a>');
|
||||
$('#user-requester').html(e.requester);
|
||||
|
||||
// Request the songlist to remove played songs.
|
||||
player.requestRequestList('songlist');
|
||||
|
||||
// Save this info for other use.
|
||||
player.temp = {
|
||||
song: e.play,
|
||||
title: e.title,
|
||||
user: e.requester
|
||||
};
|
||||
});
|
||||
|
||||
// Pause listener.
|
||||
player.addListener('pause', () => {
|
||||
if (player.API.getPlayerState() === 2) {
|
||||
player.API.playVideo();
|
||||
} else {
|
||||
player.API.pauseVideo();
|
||||
}
|
||||
});
|
||||
|
||||
// Load the player.
|
||||
player.API = new YT.Player('player-frame', {
|
||||
events: {
|
||||
'onReady': () => {
|
||||
// Request the playlist.
|
||||
player.requestPlaylist('playlist');
|
||||
|
||||
// Request the songlist.
|
||||
player.requestRequestList('songlist');
|
||||
|
||||
// Send the ready event.
|
||||
player.ready();
|
||||
|
||||
// Interval that updates the progess slider.
|
||||
setInterval(() => {
|
||||
if (player.progressSlider !== undefined && player.API.getPlayerState() === 1 && player.canSlide) {
|
||||
player.progressSlider.slider('setAttribute', 'max', player.API.getDuration());
|
||||
player.progressSlider.slider('setValue', player.API.getCurrentTime());
|
||||
}
|
||||
}, 5e2);
|
||||
},
|
||||
'onStateChange': (e) => {
|
||||
// Make sure the button shows pause.
|
||||
if (e.data === 1) {
|
||||
$('#play-pause-button').attr('class', 'fas fa-pause');
|
||||
} else if (e.data === 2) {
|
||||
$('#play-pause-button').attr('class', 'fas fa-play');
|
||||
}
|
||||
|
||||
player.updateState(e.data);
|
||||
},
|
||||
'onError': (e) => {
|
||||
player.sendError(e.data);
|
||||
}
|
||||
},
|
||||
playerVars: {
|
||||
iv_load_policy: 3,
|
||||
controls: 0,
|
||||
showinfo: 0,
|
||||
showsearch: 0,
|
||||
autoplay: 1,
|
||||
rel: 0
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
// Buttons and events.
|
||||
$(function() {
|
||||
// Delete current song from playlist button.
|
||||
$('#del-cur-playlist-button').on('click', () => {
|
||||
player.deleteFromPlaylist();
|
||||
toastr.success('Deleted from playlist: ' + (player.temp.title.length > 30 ? player.temp.title.substring(0, 30) + '...' : player.temp.title));
|
||||
});
|
||||
|
||||
// Fav button to steal a song.
|
||||
$('#fav-button').on('click', () => {
|
||||
player.addSongToPlaylist();
|
||||
toastr.success('Added to playlist: ' + (player.temp.title.length > 30 ? player.temp.title.substring(0, 30) + '...' : player.temp.title));
|
||||
});
|
||||
|
||||
// Skip song button.
|
||||
$('#skip-button').on('click', () => {
|
||||
// Mark the state as paused.
|
||||
player.updateState(2);
|
||||
// Skip the song.
|
||||
player.skipSong();
|
||||
});
|
||||
|
||||
// Mute button.
|
||||
$('#mute-button').on('click', () => {
|
||||
if (player.API.isMuted()) {
|
||||
player.API.unMute();
|
||||
$('#mute-button-icon').attr('class', (player.API.getVolume() === 0 ? 'fas fa-volume-off' : (player.API.getVolume() > 50 ? 'fas fa-volume-up' : 'fas fa-volume-down')));
|
||||
} else {
|
||||
player.API.mute();
|
||||
$('#mute-button-icon').attr('class', 'fas fa-volume-off');
|
||||
}
|
||||
});
|
||||
|
||||
// Pause button.
|
||||
$('#pause-button').on('click', () => {
|
||||
if (player.API.getPlayerState() === 2 || player.API.getPlayerState() === 5) {
|
||||
player.API.playVideo();
|
||||
$('#play-pause-button').attr('class', 'fas fa-pause');
|
||||
} else {
|
||||
player.API.pauseVideo();
|
||||
$('#play-pause-button').attr('class', 'fas fa-play');
|
||||
}
|
||||
});
|
||||
|
||||
// Add song to queue button.
|
||||
$('#queue-add-song-button').on('click', () => {
|
||||
helpers.getSongModal('Add Song to Queue', 'Song Name or YouTube Url', 'Add', 'https://youtu.be/dQw4w9WgXcQ', () => {
|
||||
let song = $('#song-url').val();
|
||||
|
||||
if (song.length > 0) {
|
||||
player.requestSong(song);
|
||||
}
|
||||
}).modal('toggle');
|
||||
});
|
||||
|
||||
// Add song to playlist button.
|
||||
$('#playlist-add-song-button').on('click', () => {
|
||||
helpers.getSongModal('Add Song to Playlist', 'Song Name or YouTube Url', 'Add', 'https://youtu.be/dQw4w9WgXcQ', () => {
|
||||
let song = $('#song-url').val();
|
||||
|
||||
if (song.length > 0) {
|
||||
player.addSongToPlaylist(song);
|
||||
}
|
||||
}).modal('toggle');
|
||||
});
|
||||
|
||||
// Load playlist button.
|
||||
$('#load-playlist-button').on('click', () => {
|
||||
player.dbQuery('get_playlists', 'yt_playlists_registry', (results) => {
|
||||
// Get the keys.
|
||||
results = Object.keys(results);
|
||||
const playlists = [];
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
if (results[i].indexOf('ytPlaylist_') !== -1) {
|
||||
playlists.push(results[i].substr(results[i].indexOf('_') + 1, results[i].length));
|
||||
}
|
||||
}
|
||||
|
||||
helpers.getPlaylistModal('Load Playlist', 'Playlist Name', 'Load', 'Playlist', playlists, () => {
|
||||
let playlist = $('#playlist-load').find(':selected').text();
|
||||
|
||||
if (playlist === 'Select a playlist') {
|
||||
toastr.error('Please select a valid playlist.');
|
||||
} else {
|
||||
if (playlist.length > 0) {
|
||||
player.loadPlaylist(playlist);
|
||||
toastr.success('Loading playlist: ' + playlist);
|
||||
}
|
||||
}
|
||||
}).modal('toggle');
|
||||
});
|
||||
});
|
||||
|
||||
// Settings button.
|
||||
$('#settings-button').on('click', () => {
|
||||
helpers.getSettingsModal(() => {
|
||||
// Save the new size.
|
||||
localStorage.setItem('phantombot_ytplayer_size', $('#player-size-btn').text().toLowerCase());
|
||||
// Set the new size.
|
||||
helpers.setPlayerSize();
|
||||
|
||||
// Update DJ name.
|
||||
let djName = $('#dj-name').val();
|
||||
if (djName.length > 0) {
|
||||
player.dbUpdate('dj_name_up', 'ytSettings', 'playlistDJname', String(djName));
|
||||
}
|
||||
|
||||
// Update user max songs.
|
||||
let maxSongs = $('#max-song-user').val();
|
||||
if (parseInt(maxSongs) > 0) {
|
||||
player.dbUpdate('max_song_up', 'ytSettings', 'songRequestsMaxParallel', String(maxSongs));
|
||||
}
|
||||
|
||||
// Update max song length.
|
||||
let maxSongLen = $('#max-song-length').val();
|
||||
if (parseInt(maxSongLen) > 0) {
|
||||
player.dbUpdate('max_song_len_up', 'ytSettings', 'songRequestsMaxSecondsforVideo', String(maxSongLen));
|
||||
}
|
||||
|
||||
//Update the votecount.
|
||||
let voteCount = $('#vote-count').val();
|
||||
if (parseInt(voteCount) > 0) {
|
||||
player.dbUpdate('vote_count', 'ytSettings', 'voteCount', String(voteCount));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Playlist shuffle button.
|
||||
$('#playlist-shuffle-button').on('click', () => {
|
||||
player.shufflePlaylist();
|
||||
});
|
||||
|
||||
// Enable global tooltips.
|
||||
$('body').tooltip({
|
||||
selector: '[data-toggle="tooltip"]',
|
||||
container: 'body',
|
||||
trigger: 'hover',
|
||||
delay: {
|
||||
show: 350,
|
||||
hide: 50
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Load other player settings.
|
||||
$(function() {
|
||||
// Toastr options.
|
||||
toastr.options.progressBar = true;
|
||||
toastr.options.preventDuplicates = true;
|
||||
|
||||
// Set the player size.
|
||||
helpers.setPlayerSize();
|
||||
if (helpers.urlIsIP()) {
|
||||
toaster.warning('You may be accessing the YouTube player by using an IP Address in the URL.<br/><br/>'
|
||||
+ 'YouTube\'s embed API really hates this and may refuse to work.<br/><br/>You should switch to using a '
|
||||
+ 'Hostname, Domain, or Sub-Domain to avoid issues.', 'Potential Conflict Detected',
|
||||
{
|
||||
timeOut: 60000,
|
||||
extendedTimeOut: 120000,
|
||||
closeButton: true
|
||||
});
|
||||
}
|
||||
});
|
||||
11
libs/phantombot/web/ytplayer/js/playerConfig.js
Normal file
11
libs/phantombot/web/ytplayer/js/playerConfig.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// Configuration for YTPlayer
|
||||
// Automatically Generated by PhantomBot at Startup
|
||||
// Do NOT Modify! Overwritten when PhantomBot is restarted!
|
||||
var playerPort = 25000;
|
||||
var channelName = "zino1337";
|
||||
var auth="5TeJqWPU4j5avTqmdwgvsPPhqd8yY1";
|
||||
var http="https://";
|
||||
function getPlayerPort() { return playerPort; }
|
||||
function getChannelName() { return channelName; }
|
||||
function getAuth() { return auth; }
|
||||
function getProtocol() { return http; }
|
||||
282
libs/phantombot/web/ytplayer/js/util/helpers.js
Normal file
282
libs/phantombot/web/ytplayer/js/util/helpers.js
Normal file
@@ -0,0 +1,282 @@
|
||||
// Script that has helper functions.
|
||||
$(function() {
|
||||
var helpers = {};
|
||||
|
||||
/*
|
||||
* @function Generates a basic modal, you have to append your own body with jQuery.
|
||||
*
|
||||
* @param {String} id
|
||||
* @param {String} title
|
||||
* @param {String} btn
|
||||
* @param {Object} body
|
||||
* @param {Function} onClose
|
||||
* @return {Object}
|
||||
*/
|
||||
helpers.getModal = (id, title, btn, body, onClose) => {
|
||||
return $('<div/>', {
|
||||
'class': 'modal fade',
|
||||
'id': id
|
||||
}).append($('<div/>', {
|
||||
'class': 'modal-dialog'
|
||||
}).append($('<div/>', {
|
||||
'class': 'modal-content'
|
||||
}).append($('<div/>', {
|
||||
'class': 'modal-header',
|
||||
}).append($('<h5/>', {
|
||||
'class': 'modal-title',
|
||||
'text': title
|
||||
})).append($('<button/>', {
|
||||
'type': 'button',
|
||||
'class': 'close',
|
||||
'data-dismiss': 'modal',
|
||||
'html': '×'
|
||||
}))).append($('<div/>', {
|
||||
'class': 'modal-body',
|
||||
'html': body
|
||||
})).append($('<div/>', {
|
||||
'class': 'modal-footer',
|
||||
}).append($('<button/>', {
|
||||
'class': 'btn btn-primary',
|
||||
'type': 'button',
|
||||
'text': btn,
|
||||
'data-dismiss': 'modal',
|
||||
'click': onClose
|
||||
}))))).on('hidden.bs.modal', () => {
|
||||
$('#' + id).remove();
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function Generates a simple add song modal.
|
||||
*
|
||||
* @param {String} title
|
||||
* @param {String} label
|
||||
* @param {String} btn
|
||||
* @param {String} placeholder
|
||||
* @param {Function} onClose
|
||||
* @return {Object}
|
||||
*/
|
||||
helpers.getSongModal = (title, label, btn, placeholder, onClose) => {
|
||||
return helpers.getModal('song-modal', title, btn, $('<div/>', {
|
||||
'class': 'form-group'
|
||||
}).append($('<label/>', {
|
||||
'text': label
|
||||
})).append($('<input/>', {
|
||||
'class': 'form-control',
|
||||
'type': 'text',
|
||||
'placeholder': placeholder,
|
||||
'id': 'song-url',
|
||||
'focus': () => {
|
||||
$('#song-url').attr('placeholder', '');
|
||||
},
|
||||
'blur': () => {
|
||||
$('#song-url').attr('placeholder', placeholder);
|
||||
}
|
||||
})), onClose);
|
||||
};
|
||||
|
||||
/*
|
||||
* @function Generates a load playlist modal
|
||||
*
|
||||
* @param {String} title
|
||||
* @param {String} label
|
||||
* @param {String} btn
|
||||
* @param {String} placeholder
|
||||
* @param {Array} playlists
|
||||
* @param {Function} onClose
|
||||
* @return {Object}
|
||||
*/
|
||||
helpers.getPlaylistModal = (title, label, btn, placeholder, playlists, onClose) => {
|
||||
return helpers.getModal('playlist-load-modal', title, btn, $('<div/>', {
|
||||
'class': 'form-group'
|
||||
}).append($('<label/>', {
|
||||
'text': label
|
||||
})).append($('<select/>', {
|
||||
'class': 'form-control',
|
||||
'id': 'playlist-load',
|
||||
'text': 'Select a playlist',
|
||||
'style': 'width: 100%; cursor: pointer;',
|
||||
'data-toggle': 'dropdown'
|
||||
}).append($('<option/>', {
|
||||
'html': 'Select a playlist',
|
||||
'selected': 'true',
|
||||
'disabled': 'true',
|
||||
'hidden': 'true'
|
||||
})).append(playlists.map(function(playlist) {
|
||||
return $('<option/>', {
|
||||
'html': playlist
|
||||
});
|
||||
})).append($('<option/>', {
|
||||
'html': 'Select a playlist',
|
||||
'disabled': 'true',
|
||||
'hidden': 'true'
|
||||
}))), onClose);
|
||||
};
|
||||
|
||||
/*
|
||||
* @function Generates a load playlist modal
|
||||
*
|
||||
* @param {String} title
|
||||
* @param {String} body
|
||||
* @param {Function} onClose
|
||||
* @return {Object}
|
||||
*/
|
||||
helpers.getErrorModal = (title, body, onClose) => {
|
||||
return helpers.getModal('err-modal', title, 'Ok', $('<div/>', {
|
||||
'class': 'form-group'
|
||||
}).append($('<p/>', {
|
||||
'text': body
|
||||
})), onClose);
|
||||
};
|
||||
|
||||
/*
|
||||
* @function Generates the settings modal
|
||||
*
|
||||
* @param {Function} onClose
|
||||
*/
|
||||
helpers.getSettingsModal = (onClose) => {
|
||||
player.dbQuery('yt_settings', 'ytSettings', (e) => {
|
||||
helpers.getModal('settings-modal', 'YouTube Player and Request Settings', 'Save', $('<form/>').append($('<div/>', {
|
||||
'class': 'form-group'
|
||||
}).append($('<label/>', {
|
||||
'text': 'Player Size'
|
||||
})).append($('<div/>', {
|
||||
'class': 'dropdown'
|
||||
}).append($('<button/>', {
|
||||
'class': 'btn btn-secondary dropdown-toggle',
|
||||
'type': 'button',
|
||||
'data-toggle': 'dropdown',
|
||||
'text': helpers.getPlayerSize(),
|
||||
'id': 'player-size-btn'
|
||||
})).append($('<div/>', {
|
||||
'class': 'dropdown-menu',
|
||||
'aria-labelledby': 'player-size-btn'
|
||||
}).append($('<a/>', {
|
||||
'class': 'dropdown-item',
|
||||
'href': '#',
|
||||
'text': 'Default',
|
||||
'click': () => {
|
||||
$('#player-size-btn').text('Default');
|
||||
}
|
||||
})).append($('<a/>', {
|
||||
'class': 'dropdown-item',
|
||||
'href': '#',
|
||||
'text': 'Half',
|
||||
'click': () => {
|
||||
$('#player-size-btn').text('Half');
|
||||
}
|
||||
})).append($('<a/>', {
|
||||
'class': 'dropdown-item',
|
||||
'href': '#',
|
||||
'text': 'Small',
|
||||
'click': () => {
|
||||
$('#player-size-btn').text('Small');
|
||||
}
|
||||
})).append($('<a/>', {
|
||||
'class': 'dropdown-item',
|
||||
'href': '#',
|
||||
'text': 'Tiny',
|
||||
'click': () => {
|
||||
$('#player-size-btn').text('Tiny');
|
||||
}
|
||||
})).append($('<a/>', {
|
||||
'class': 'dropdown-item',
|
||||
'href': '#',
|
||||
'text': 'Hidden',
|
||||
'click': () => {
|
||||
$('#player-size-btn').text('Hidden');
|
||||
}
|
||||
}))))).append($('<div/>', {
|
||||
'class': 'form-group'
|
||||
}).append($('<label/>', {
|
||||
'text': 'Player DJ Name'
|
||||
})).append($('<input/>', {
|
||||
'type': 'text',
|
||||
'data-toggle': 'tooltip',
|
||||
'title': 'Name of the default playlist user.',
|
||||
'class': 'form-control',
|
||||
'id': 'dj-name',
|
||||
'value': e.playlistDJname
|
||||
}))).append($('<div/>', {
|
||||
'class': 'form-group',
|
||||
}).append($('<label/>', {
|
||||
'text': 'Maximum Songs'
|
||||
})).append($('<input/>', {
|
||||
'type': 'number',
|
||||
'data-toggle': 'tooltip',
|
||||
'title': 'How many songs one user can have in the queue.',
|
||||
'class': 'form-control',
|
||||
'id': 'max-song-user',
|
||||
'value': e.songRequestsMaxParallel
|
||||
}))).append($('<div/>', {
|
||||
'class': 'form-group'
|
||||
}).append($('<label/>', {
|
||||
'text': 'Maximum Song Duration'
|
||||
})).append($('<input/>', {
|
||||
'type': 'number',
|
||||
'data-toggle': 'tooltip',
|
||||
'id': 'max-song-length',
|
||||
'title': 'How long in seconds a song can be.',
|
||||
'class': 'form-control',
|
||||
'value': e.songRequestsMaxSecondsforVideo
|
||||
}))).append($('<div/>', {
|
||||
'class': 'form-group'
|
||||
}).append($('<label/>', {
|
||||
'text': 'Vote Count'
|
||||
})).append($('<input/>', {
|
||||
'type': 'number',
|
||||
'data-toggle': 'tooltip',
|
||||
'id': 'vote-count',
|
||||
'title': 'How many votes it takes to Skip.',
|
||||
'class': 'form-control',
|
||||
'value': e.voteCount
|
||||
}))),onClose).modal('toggle');
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function Gets the player size.
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
helpers.getPlayerSize = () => {
|
||||
let size = localStorage.getItem('phantombot_ytplayer_size');
|
||||
|
||||
return (size === null ? 'Default' : size[0].toUpperCase() + size.substr(1));
|
||||
};
|
||||
|
||||
/*
|
||||
* @function Sets the new player size.
|
||||
*/
|
||||
helpers.setPlayerSize = () => {
|
||||
switch (localStorage.getItem('phantombot_ytplayer_size')) {
|
||||
case 'half':
|
||||
$('#left-section').attr('class', 'col-md-6').removeClass('off');
|
||||
$('#right-section').attr('class', 'col-md-6');
|
||||
break;
|
||||
case 'small':
|
||||
$('#left-section').attr('class', 'col-md-5').removeClass('off');
|
||||
$('#right-section').attr('class', 'col-md-7');
|
||||
break;
|
||||
case 'tiny':
|
||||
$('#left-section').attr('class', 'col-md-4').removeClass('off');
|
||||
$('#right-section').attr('class', 'col-md-8');
|
||||
break;
|
||||
case 'hidden':
|
||||
$('#left-section').addClass('off');
|
||||
$('#right-section').attr('class', 'col-md-12');
|
||||
break;
|
||||
default:
|
||||
$('#left-section').attr('class', 'col-md-7').removeClass('off');
|
||||
$('#right-section').attr('class', 'col-md-5');
|
||||
}
|
||||
};
|
||||
|
||||
helpers.urlIsIP = () => {
|
||||
var rx=/^(?!0)(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|$)){4}$/;
|
||||
return rx.test(window.location.hostname);
|
||||
}
|
||||
|
||||
// Export object.
|
||||
window.helpers = helpers;
|
||||
});
|
||||
419
libs/phantombot/web/ytplayer/js/util/socket.js
Normal file
419
libs/phantombot/web/ytplayer/js/util/socket.js
Normal file
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2020 phantombot.github.io/PhantomBot
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author ScaniaTV
|
||||
*/
|
||||
|
||||
$(function() {
|
||||
var socket = new WebSocket((getProtocol() === 'https://' || window.location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host + '/ws/ytplayer'),
|
||||
listeners = [],
|
||||
player = {},
|
||||
hasAPIKey = true,
|
||||
secondConnection = false;
|
||||
|
||||
/*
|
||||
* @function sends data to the socket, this should only be used in this script.
|
||||
*
|
||||
* @param {Object} data
|
||||
*/
|
||||
var sendToSocket = (data) => {
|
||||
// Do not send any requests or any other data to the Core for processing if there is no key.
|
||||
if (!hasAPIKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
socket.send(JSON.stringify(data));
|
||||
} catch (ex) {
|
||||
console.error('Failed to send message to socket: ' + ex.message);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* @function to determine is a second connection was detected.
|
||||
*/
|
||||
player.secondConnection = () => {
|
||||
return secondConnection;
|
||||
}
|
||||
|
||||
/*
|
||||
* @function to determine if an API key exists.
|
||||
*/
|
||||
player.hasAPIKey = () => {
|
||||
return hasAPIKey;
|
||||
}
|
||||
|
||||
/*
|
||||
* @function gets the playlist.
|
||||
*
|
||||
* @param {String} callback_id
|
||||
*/
|
||||
player.requestPlaylist = (callback_id) => {
|
||||
// Request the data.
|
||||
sendToSocket({
|
||||
query: 'playlist'
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function gets the request list.
|
||||
*
|
||||
* @param {String} callback_id
|
||||
*/
|
||||
player.requestRequestList = (callback_id) => {
|
||||
// Request the data.
|
||||
sendToSocket({
|
||||
query: 'songlist'
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function deletes a song from the current playlist.
|
||||
*/
|
||||
player.deleteFromPlaylist = () => {
|
||||
sendToSocket({
|
||||
command: 'deletecurrent'
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function "steals" a song and adds it to the default playlist.
|
||||
*
|
||||
* @param {String} song_id
|
||||
* @param {String} requester
|
||||
*/
|
||||
player.addSongToPlaylist = (song_id, requester) => {
|
||||
// Update the data.
|
||||
sendToSocket({
|
||||
command: 'stealsong',
|
||||
youTubeID: (song_id === undefined ? '' : song_id),
|
||||
requester: (requester === undefined ? '' : requester)
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function adds a song to the queue.
|
||||
*
|
||||
* @param {String} song_id
|
||||
*/
|
||||
player.requestSong = (song_id) => {
|
||||
// Add song to queue.
|
||||
sendToSocket({
|
||||
command: 'songrequest',
|
||||
search: song_id
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function removes a song from the default playlist.
|
||||
*
|
||||
* @param {String} song_id
|
||||
* @param {String} requester
|
||||
*/
|
||||
player.removeSongFromPlaylist = (song_id) => {
|
||||
// Update the data.
|
||||
sendToSocket({
|
||||
deletepl: song_id
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function removes a song from the queue.
|
||||
*
|
||||
* @param {String} song_id
|
||||
* @param {String} requester
|
||||
*/
|
||||
player.removeSongFromRequest = (song_id) => {
|
||||
// Update the data.
|
||||
sendToSocket({
|
||||
deletesr: song_id
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function shuffles the playlist.
|
||||
*/
|
||||
player.shufflePlaylist = () => {
|
||||
// Update the data.
|
||||
sendToSocket({
|
||||
command: 'togglerandom'
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function loads a new playlist
|
||||
*
|
||||
* @param {String} playlist
|
||||
*/
|
||||
player.loadPlaylist = (playlist) => {
|
||||
// Update the data.
|
||||
sendToSocket({
|
||||
command: 'loadpl',
|
||||
playlist: playlist
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function skips the current song.
|
||||
*/
|
||||
player.skipSong = () => {
|
||||
sendToSocket({
|
||||
command: 'skipsong'
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function updates the player status.
|
||||
*
|
||||
* @param {Number} status
|
||||
*/
|
||||
player.updateState = (status) => {
|
||||
sendToSocket({
|
||||
status: {
|
||||
state: status
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function updates the current song.
|
||||
*
|
||||
* @param {String} id
|
||||
*/
|
||||
player.updateSong = (id) => {
|
||||
sendToSocket({
|
||||
status: {
|
||||
currentid: id
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function puts the player in ready mode.
|
||||
*/
|
||||
player.ready = () => {
|
||||
sendToSocket({
|
||||
status: {
|
||||
ready: true
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function sends error code from YouTube Player
|
||||
*
|
||||
* @param {Number} status
|
||||
*/
|
||||
player.sendError = (status) => {
|
||||
sendToSocket({
|
||||
status: {
|
||||
errorcode: status
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function updates the player volume.+
|
||||
*
|
||||
* @param {Number} volume
|
||||
*/
|
||||
player.updateVolume = (volume) => {
|
||||
sendToSocket({
|
||||
status: {
|
||||
volume: volume
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function puts the player in ready-pause mode.
|
||||
*/
|
||||
player.readyPause = () => {
|
||||
sendToSocket({
|
||||
status: {
|
||||
readypause: true
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function Gets all keys and values from a table
|
||||
*
|
||||
* @param {String} callback_id
|
||||
* @param {String} table
|
||||
* @param {Function} callback
|
||||
*/
|
||||
player.dbQuery = (callback_id, table, callback) => {
|
||||
listeners[callback_id] = callback;
|
||||
|
||||
sendToSocket({
|
||||
dbquery: true,
|
||||
query_id: callback_id,
|
||||
table: table
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function Updates a key and value in the database
|
||||
*
|
||||
* @param {String} callback_id
|
||||
* @param {String} table
|
||||
* @param {String} key
|
||||
* @param {String} value
|
||||
* @param {Function} callback
|
||||
*/
|
||||
player.dbUpdate = (callback_id, table, key, value, callback) => {
|
||||
if (callback !== undefined) {
|
||||
listeners[callback_id] = callback;
|
||||
}
|
||||
|
||||
sendToSocket({
|
||||
dbupdate: true,
|
||||
query_id: callback_id,
|
||||
update: {
|
||||
table: table,
|
||||
key: key,
|
||||
value: value
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* @function adds a listener to the socket.
|
||||
*
|
||||
* @param {String} listener_id
|
||||
* @param {Function} listener
|
||||
*/
|
||||
player.addListener = (listener_id, listener) => {
|
||||
listeners[listener_id] = listener;
|
||||
};
|
||||
|
||||
/* Socket functions */
|
||||
|
||||
/*
|
||||
* @function is called when the socket opens.
|
||||
*/
|
||||
socket.onopen = (e) => {
|
||||
console.info('Connection established with the websocket.');
|
||||
|
||||
// Send the auth to the bot.
|
||||
sendToSocket({
|
||||
authenticate: getAuth()
|
||||
});
|
||||
|
||||
// Load the YouTube iframe.
|
||||
$('body').append($('<script/>', {
|
||||
src: 'https://www.youtube.com/iframe_api'
|
||||
}));
|
||||
};
|
||||
|
||||
/*
|
||||
* @function the socket calls when it closes
|
||||
*/
|
||||
socket.onclose = (e) => {
|
||||
console.error('Connection lost with the websocket.');
|
||||
|
||||
if (secondConnection) {
|
||||
toastr.error('PhantomBot has closed the WebSocket.', '', {timeOut: 0});
|
||||
} else {
|
||||
toastr.error('Connection with WebSocket was lost. Refresh once reestablished.', '', {timeOut: 0});
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* @function the socket calls when it gets message.
|
||||
*/
|
||||
socket.onmessage = (e) => {
|
||||
try {
|
||||
let message = JSON.parse(e.data);
|
||||
|
||||
if (message.ping !== undefined) {
|
||||
sendToSocket({
|
||||
pong: "pong"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Check this message here before doing anything else.
|
||||
if (message.secondconnection !== undefined) {
|
||||
if (message.secondconnection === true) {
|
||||
secondConnection = true;
|
||||
toastr.error('PhantomBot rejected the connection due to a player window already being open.', '',
|
||||
{timeOut: 0, extendedTimeOut: 0});
|
||||
console.error('Only one instance allowed.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check this message here before doing anything else.
|
||||
if (message.authresult !== undefined) {
|
||||
if (message.authresult === false) {
|
||||
console.error('Failed to auth with the socket.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check to ensure that there is an API key.
|
||||
if (message.ytkeycheck !== undefined) {
|
||||
if (message.ytkeycheck === false) {
|
||||
hasAPIKey = false;
|
||||
console.error("Missing YouTube API Key.");
|
||||
toastr.error('A YouTube API key has not been configured. Please review the instructions ' +
|
||||
'<a href="https://phantombot.github.io/PhantomBot/guides/#guide=content/integrations/youtubesetup">here' +
|
||||
'</a> on the PhantomBot Community Forum.', 'Missing YouTube API Key',
|
||||
{timeOut: 0, extendedTimeOut: 0});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.query_id !== undefined) {
|
||||
if (listeners[message.query_id] !== undefined) {
|
||||
listeners[message.query_id](message);
|
||||
delete listeners[message.query_id];
|
||||
}
|
||||
} else if (message.command !== undefined) {
|
||||
if (typeof message.command === 'object') {
|
||||
let keys = Object.keys(message.command);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
if (listeners[keys[i]] !== undefined) {
|
||||
listeners[keys[i]](message.command);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (listeners[message.command] !== undefined) {
|
||||
listeners[message.command](message);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let keys = Object.keys(message);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
if (listeners[keys[i]] !== undefined) {
|
||||
listeners[keys[i]](message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error('Failed to parse message from socket: ' + ex.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Make the player object global.
|
||||
window.player = player;
|
||||
});
|
||||
Reference in New Issue
Block a user