Compare commits
3 commits
a07edfc842
...
6d8135d1e3
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d8135d1e3 | |||
| a819d14861 | |||
| e3507b00f8 |
9 changed files with 166 additions and 15 deletions
|
|
@ -197,8 +197,6 @@ class connectedUser{
|
||||||
chanDB = await channelModel.findOne({name: this.channel.name});
|
chanDB = await channelModel.findOne({name: this.channel.name});
|
||||||
}
|
}
|
||||||
|
|
||||||
//If our perm map is un-initiated
|
|
||||||
//can't set this in constructor easily since it's asyncornous
|
|
||||||
//need to wait for it to complete before sending this off, but shouldnt re-do the wait for later connections
|
//need to wait for it to complete before sending this off, but shouldnt re-do the wait for later connections
|
||||||
if(this.permMap == null){
|
if(this.permMap == null){
|
||||||
//Grab perm map
|
//Grab perm map
|
||||||
|
|
@ -238,7 +236,7 @@ class connectedUser{
|
||||||
const chatBuffer = this.channel.chatBuffer.buffer;
|
const chatBuffer = this.channel.chatBuffer.buffer;
|
||||||
|
|
||||||
//Send off the metadata to our user's clients
|
//Send off the metadata to our user's clients
|
||||||
this.emit("clientMetadata", {user: userObj, flairList, queueLock, chatBuffer});
|
this.emit("clientMetadata", {user: userObj, flairList, queueLock, chatBuffer, streamType: chanDB.settings.streamType});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ class queue{
|
||||||
socket.on("move", (data) => {this.moveMedia(socket, data)});
|
socket.on("move", (data) => {this.moveMedia(socket, data)});
|
||||||
socket.on("lock", () => {this.toggleLock(socket)});
|
socket.on("lock", () => {this.toggleLock(socket)});
|
||||||
socket.on("goLive", (data) => {this.goLive(socket, data)});
|
socket.on("goLive", (data) => {this.goLive(socket, data)});
|
||||||
|
socket.on("getStreamType", (data) => {this.getStreamType(socket)});
|
||||||
|
|
||||||
//If debug mode is enabled
|
//If debug mode is enabled
|
||||||
if(config.debug){
|
if(config.debug){
|
||||||
|
|
@ -357,6 +358,18 @@ class queue{
|
||||||
throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while queue item!`, "queue");
|
throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while queue item!`, "queue");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//If the user doesn't have permission to be doing this shit
|
||||||
|
if(!((!this.locked && await chanDB.permCheck(socket.user, 'scheduleMedia')) || await chanDB.permCheck(socket.user, 'scheduleAdmin'))){
|
||||||
|
//Fuggettabouttit!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chanDB.settings.streamType == "webrtc"){
|
||||||
|
console.log("WEBRTC ENABLED, BAILING!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//If something is playing
|
//If something is playing
|
||||||
if(this.nowPlaying != null){
|
if(this.nowPlaying != null){
|
||||||
//Capture currently playing object
|
//Capture currently playing object
|
||||||
|
|
@ -403,7 +416,7 @@ class queue{
|
||||||
);
|
);
|
||||||
|
|
||||||
//Validate mode input, and default to overwrite
|
//Validate mode input, and default to overwrite
|
||||||
this.liveMode = (data.mode == "pushback") ? "pushback" : "overwrite";
|
this.liveMode = (data != null && data.mode == "pushback") ? "pushback" : "overwrite";
|
||||||
|
|
||||||
//Throw stream lock
|
//Throw stream lock
|
||||||
this.streamLock = true;
|
this.streamLock = true;
|
||||||
|
|
@ -415,6 +428,22 @@ class queue{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current channel stream type upon request
|
||||||
|
* @param {Socket} socket - Socket we received the request from
|
||||||
|
*/
|
||||||
|
async getStreamType(socket){
|
||||||
|
try{
|
||||||
|
//Get the current channel from the database
|
||||||
|
const chanDB = await channelModel.findOne({name: socket.chan});
|
||||||
|
|
||||||
|
//Send streamtype back down to user (Not perm checking for something someone can figure out by looking at a running livestream)
|
||||||
|
socket.emit("streamType", {streamType: chanDB.settings.streamType});
|
||||||
|
}catch(err){
|
||||||
|
return loggerUtils.socketExceptionHandler(socket, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async dumpQueue(socket, data){
|
async dumpQueue(socket, data){
|
||||||
//If we somehow got here while config.debug is disabled, or the user isn't allowed to preform server-side debugging
|
//If we somehow got here while config.debug is disabled, or the user isn't allowed to preform server-side debugging
|
||||||
if(!(config.debug && await permissionModel.permCheck(socket.user, "debug"))){
|
if(!(config.debug && await permissionModel.permCheck(socket.user, "debug"))){
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,11 @@ const chatSchema = require('./chatSchema');
|
||||||
//Utils
|
//Utils
|
||||||
const { exceptionHandler, errorHandler } = require('../../utils/loggerUtils');
|
const { exceptionHandler, errorHandler } = require('../../utils/loggerUtils');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Enum" for emote type property
|
||||||
|
*/
|
||||||
|
const streamMethodEnum = ["webrtc","hls"];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DB Schema for Documents containing de-hydrated representations of Canopy Stream/Chat Channels
|
* DB Schema for Documents containing de-hydrated representations of Canopy Stream/Chat Channels
|
||||||
*/
|
*/
|
||||||
|
|
@ -71,6 +76,12 @@ const channelSchema = new mongoose.Schema({
|
||||||
streamURL: {
|
streamURL: {
|
||||||
type: mongoose.SchemaTypes.String,
|
type: mongoose.SchemaTypes.String,
|
||||||
default: ''
|
default: ''
|
||||||
|
},
|
||||||
|
streamType: {
|
||||||
|
type: mongoose.SchemaTypes.String,
|
||||||
|
enum: streamMethodEnum,
|
||||||
|
default: streamMethodEnum[0]
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
permissions: {
|
permissions: {
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,6 @@ const { checkSchema, checkExact } = require('express-validator');
|
||||||
//local imports
|
//local imports
|
||||||
const accountValidator = require('./accountValidator');
|
const accountValidator = require('./accountValidator');
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
|
|
||||||
settingsMap: () => checkExact(checkSchema({
|
|
||||||
'settingsMap.hidden': {
|
|
||||||
optional: true,
|
|
||||||
isBoolean: true,
|
|
||||||
} }))
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports.name = function(field = 'name'){
|
module.exports.name = function(field = 'name'){
|
||||||
return checkSchema({
|
return checkSchema({
|
||||||
[field]: {
|
[field]: {
|
||||||
|
|
@ -89,6 +80,13 @@ module.exports.settingsMap = function(){
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
errorMessage: "Invalid Stream URL"
|
errorMessage: "Invalid Stream URL"
|
||||||
|
},
|
||||||
|
'settingsMap.streamType': {
|
||||||
|
optional: true,
|
||||||
|
errorMessage: "Invalid Stream Type",
|
||||||
|
matches: {
|
||||||
|
options: [/\b(?:webrtc|hls)\b/]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
|
||||||
<h3>Channel Preferences:</h3>
|
<h3>Channel Preferences:</h3>
|
||||||
<div class="dynamic-container">
|
<div class="dynamic-container">
|
||||||
<form action="javascript:" class="admin-list-field">
|
<form action="javascript:" class="admin-list-field">
|
||||||
<% Object.keys(channel.settings).forEach((key) => { %>
|
<% for(key of Object.keys(channel.settings)){
|
||||||
|
//Ignore keys w/ custom HTML
|
||||||
|
if(key == "streamURL" || key == "streamType"){
|
||||||
|
break;
|
||||||
|
}%>
|
||||||
<span class="admin-list-field-container">
|
<span class="admin-list-field-container">
|
||||||
<label class="admin-list-label"><%= key %>:</label>
|
<label class="admin-list-label"><%= key %>:</label>
|
||||||
<% switch(typeof channel.settings[key]){
|
<% switch(typeof channel.settings[key]){
|
||||||
|
|
@ -29,7 +33,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
|
||||||
<% break;
|
<% break;
|
||||||
} %>
|
} %>
|
||||||
</span>
|
</span>
|
||||||
<% }); %>
|
<% }; %>
|
||||||
|
<span class="admin-list-field-container">
|
||||||
|
<p>Livestream Type:</p>
|
||||||
|
<span id="channel-preference-list-stream-settings-grid">
|
||||||
|
<span>
|
||||||
|
<input type="radio" name="streamType" id="channel-preference-list-stream-type-webrtc" value="webrtc" <% if(channel.settings["streamType"] == "webrtc"){ %> checked <% }%> >
|
||||||
|
<label for="channel-preference-list-stream-type-webrtc">Peer-to-Peer (WebRTC/STUN)</label>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<input type="radio" name="streamType" id="channel-preference-list-stream-type-hls" value="hls" <% if(channel.settings["streamType"] == "hls"){ %> checked <% }%> >
|
||||||
|
<label for="channel-preference-list-stream-type-hls">Self-Hosted (HLS)</label>
|
||||||
|
</span>
|
||||||
|
<input <% if(channel.settings["streamType"] != "hls"){ %> disabled <%}%> id="channel-preference-list-stream-url" placeholder="Stream URL" value="<%= channel.settings["streamURL"] %>">
|
||||||
|
</span>
|
||||||
|
|
||||||
|
</span>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -139,6 +139,16 @@ img.admin-list-entry-item{
|
||||||
width: 8em;
|
width: 8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#channel-preference-list-stream-settings-grid{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto auto;
|
||||||
|
row-gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#channel-preference-list-stream-url {
|
||||||
|
grid-column: 2;
|
||||||
|
}
|
||||||
|
|
||||||
div.toke-command-list{
|
div.toke-command-list{
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(15em, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(15em, 1fr));
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,10 @@ class channel{
|
||||||
this.queueLock = data.locked;
|
this.queueLock = data.locked;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.socket.on("streamType", (data) => {
|
||||||
|
this.streamType = data.streamType;
|
||||||
|
});
|
||||||
|
|
||||||
this.queueBroadcastSocket.on("queue", (data) => {
|
this.queueBroadcastSocket.on("queue", (data) => {
|
||||||
this.queue = new Map(data.queue);
|
this.queue = new Map(data.queue);
|
||||||
});
|
});
|
||||||
|
|
@ -146,6 +150,9 @@ class channel{
|
||||||
|
|
||||||
//Store queue lock status
|
//Store queue lock status
|
||||||
this.queueLock = data.queueLock;
|
this.queueLock = data.queueLock;
|
||||||
|
|
||||||
|
//Store streamType
|
||||||
|
this.streamType = data.streamType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ class queuePanel extends panelObj{
|
||||||
*/
|
*/
|
||||||
this.playlistManager = new playlistManager(client, panelDocument, this);
|
this.playlistManager = new playlistManager(client, panelDocument, this);
|
||||||
|
|
||||||
|
this.streamType = "";
|
||||||
|
|
||||||
//Define non-input event listeners
|
//Define non-input event listeners
|
||||||
this.defineListeners();
|
this.defineListeners();
|
||||||
}
|
}
|
||||||
|
|
@ -65,6 +67,9 @@ class queuePanel extends panelObj{
|
||||||
//Call derived doc switch function
|
//Call derived doc switch function
|
||||||
super.docSwitch();
|
super.docSwitch();
|
||||||
|
|
||||||
|
//Request Channel Stream Type
|
||||||
|
this.client.socket.emit('getStreamType');
|
||||||
|
|
||||||
//Get queue div
|
//Get queue div
|
||||||
this.queue = this.panelDocument.querySelector('#queue');
|
this.queue = this.panelDocument.querySelector('#queue');
|
||||||
//Get queue container
|
//Get queue container
|
||||||
|
|
@ -243,6 +248,10 @@ class queuePanel extends panelObj{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleStreamType(data){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* queue control button functions */
|
/* queue control button functions */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -269,6 +278,9 @@ class queuePanel extends panelObj{
|
||||||
* @param {Event} event - Event passed down from Event Listener
|
* @param {Event} event - Event passed down from Event Listener
|
||||||
*/
|
*/
|
||||||
toggleGoLive(event){
|
toggleGoLive(event){
|
||||||
|
//Request stream type from the server Just-InCase™
|
||||||
|
client.socket.emit('getStreamType');
|
||||||
|
|
||||||
//If we're not livestreaming
|
//If we're not livestreaming
|
||||||
if(client.player.mediaHandler.type != "livehls"){
|
if(client.player.mediaHandler.type != "livehls"){
|
||||||
//If the div is hidden
|
//If the div is hidden
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ class channelSettingsPage{
|
||||||
this.banList = new banList(this.channel);
|
this.banList = new banList(this.channel);
|
||||||
this.permList = new permList(this.channel);
|
this.permList = new permList(this.channel);
|
||||||
this.prefrenceList = new prefrenceList(this.channel);
|
this.prefrenceList = new prefrenceList(this.channel);
|
||||||
|
this.livestreamPreferences = new livestreamPreferences(this.channel);
|
||||||
this.tokeCommandList = new tokeCommandList(this.channel);
|
this.tokeCommandList = new tokeCommandList(this.channel);
|
||||||
this.emoteList = new emoteList(this.channel);
|
this.emoteList = new emoteList(this.channel);
|
||||||
this.deleteBtn = new deleteBtn(this.channel);
|
this.deleteBtn = new deleteBtn(this.channel);
|
||||||
|
|
@ -364,6 +365,72 @@ class prefrenceList{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class livestreamPreferences{
|
||||||
|
constructor(channel){
|
||||||
|
this.channel = channel;
|
||||||
|
|
||||||
|
//Grab inputs
|
||||||
|
this.webRTCButton = document.querySelector("#channel-preference-list-stream-type-webrtc");
|
||||||
|
this.hlsButton = document.querySelector("#channel-preference-list-stream-type-hls");
|
||||||
|
this.streamURL = document.querySelector("#channel-preference-list-stream-url");
|
||||||
|
|
||||||
|
//Setup Input
|
||||||
|
this.setupInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
setupInput(){
|
||||||
|
//Add event listeners
|
||||||
|
this.webRTCButton.addEventListener("change", this.submitTypeUpdate.bind(this));
|
||||||
|
this.hlsButton.addEventListener("change", this.submitTypeUpdate.bind(this));
|
||||||
|
this.streamURL.addEventListener("change",this.submitURLUpdate.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
async submitURLUpdate(event){
|
||||||
|
//Grab value from event target
|
||||||
|
const value = event.target.value;
|
||||||
|
|
||||||
|
//Send setting change request to server, and store update once its received
|
||||||
|
const update = await utils.ajax.setChannelSetting(this.channel, new Map([["streamURL", value]]));
|
||||||
|
|
||||||
|
//If we we're given a good update
|
||||||
|
if(update != null && update.streamURL != null){
|
||||||
|
//Display the new streamURL in the input (I'm not making a dedicated method for a fuckin' one-liner)
|
||||||
|
this.streamURL.value = update.streamURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async submitTypeUpdate(event){
|
||||||
|
//Grab value from event target
|
||||||
|
const value = event.target.value;
|
||||||
|
|
||||||
|
//Send setting change request to server, and store update once its received
|
||||||
|
const update = await utils.ajax.setChannelSetting(this.channel, new Map([["streamType", value]]));
|
||||||
|
|
||||||
|
//Pass update to the handleUpdate method
|
||||||
|
this.handleTypeUpdate(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTypeUpdate(data){
|
||||||
|
//If the stream type is HLS
|
||||||
|
if(data.streamType == "hls"){
|
||||||
|
//Ensure the hls button is checked
|
||||||
|
this.hlsButton.checked = true;
|
||||||
|
//Ensure the stream url input is enabled
|
||||||
|
this.streamURL.disabled = false;
|
||||||
|
//Otherwise
|
||||||
|
}else{
|
||||||
|
//Ensure the stream url input is disabled
|
||||||
|
this.streamURL.disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If the stream type is webrtc
|
||||||
|
if(data.streamType == "webrtc"){
|
||||||
|
//Ensure the webrtc button is checked
|
||||||
|
this.webRTCButton.checked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class permList{
|
class permList{
|
||||||
constructor(channel){
|
constructor(channel){
|
||||||
this.channel = channel
|
this.channel = channel
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue