diff --git a/controllers/admin/config.go b/controllers/admin/config.go index b28e0d5ab..29aac58e0 100644 --- a/controllers/admin/config.go +++ b/controllers/admin/config.go @@ -435,6 +435,23 @@ func SetSocialHandles(w http.ResponseWriter, r *http.Request) { controllers.WriteSimpleResponse(w, true, "social handles updated") } +// SetChatDisabled will disable chat functionality. +func SetChatDisabled(w http.ResponseWriter, r *http.Request) { + if !requirePOST(w, r) { + return + } + + configValue, success := getValueFromRequest(w, r) + if !success { + controllers.WriteSimpleResponse(w, false, "unable to update chat disabled") + return + } + + data.SetChatDisabled(configValue.Value.(bool)) + + controllers.WriteSimpleResponse(w, true, "chat disabled status updated") +} + func requirePOST(w http.ResponseWriter, r *http.Request) bool { if r.Method != controllers.POST { controllers.WriteSimpleResponse(w, false, r.Method+" not supported") diff --git a/controllers/admin/serverConfig.go b/controllers/admin/serverConfig.go index 97ce35f9a..fb721dd0c 100644 --- a/controllers/admin/serverConfig.go +++ b/controllers/admin/serverConfig.go @@ -43,6 +43,7 @@ func GetServerConfig(w http.ResponseWriter, r *http.Request) { StreamKey: data.GetStreamKey(), WebServerPort: config.WebServerPort, RTMPServerPort: data.GetRTMPPortNumber(), + ChatDisabled: data.GetChatDisabled(), VideoSettings: videoSettings{ VideoQualityVariants: videoQualityVariants, LatencyLevel: data.GetStreamLatencyLevel().Level, @@ -71,6 +72,7 @@ type serverConfigAdminResponse struct { VideoSettings videoSettings `json:"videoSettings"` LatencyLevel int `json:"latencyLevel"` YP yp `json:"yp"` + ChatDisabled bool `json:"chatDisabled"` } type videoSettings struct { diff --git a/controllers/config.go b/controllers/config.go index cffb8d16d..a5016baf0 100644 --- a/controllers/config.go +++ b/controllers/config.go @@ -21,6 +21,7 @@ type webConfigResponse struct { ExtraPageContent string `json:"extraPageContent"` StreamTitle string `json:"streamTitle,omitempty"` // What's going on with the current stream SocialHandles []models.SocialHandle `json:"socialHandles"` + ChatDisabled bool `json:"chatDisabled"` } // GetWebConfig gets the status of the server. @@ -48,6 +49,7 @@ func GetWebConfig(w http.ResponseWriter, r *http.Request) { ExtraPageContent: pageContent, StreamTitle: data.GetStreamTitle(), SocialHandles: socialHandles, + ChatDisabled: data.GetChatDisabled(), } if err := json.NewEncoder(w).Encode(configuration); err != nil { diff --git a/core/chat/server.go b/core/chat/server.go index 3c2add7b0..9ce5c5ee8 100644 --- a/core/chat/server.go +++ b/core/chat/server.go @@ -135,6 +135,10 @@ func (s *server) Listen() { case c := <-s.delCh: s.removeClient(c) case msg := <-s.sendAllCh: + if data.GetChatDisabled() { + break + } + if !msg.Empty() { // set defaults before sending msg to anywhere msg.SetDefaults() diff --git a/core/data/config.go b/core/data/config.go index 31ed87c6f..6a629a58c 100644 --- a/core/data/config.go +++ b/core/data/config.go @@ -33,6 +33,7 @@ const s3StorageEnabledKey = "s3_storage_enabled" const s3StorageConfigKey = "s3_storage_config" const videoLatencyLevel = "video_latency_level" const videoStreamOutputVariantsKey = "video_stream_output_variants" +const chatDisabledKey = "chat_disabled" // GetExtraPageBodyContent will return the user-supplied body content. func GetExtraPageBodyContent() string { @@ -408,6 +409,21 @@ func SetStreamOutputVariants(variants []models.StreamOutputVariant) error { return _datastore.Save(configEntry) } +// SetChatDisabled will disable chat if set to true. +func SetChatDisabled(disabled bool) error { + return _datastore.SetBool(chatDisabledKey, disabled) +} + +// GetChatDisabled will return if chat is disabled. +func GetChatDisabled() bool { + disabled, err := _datastore.GetBool(chatDisabledKey) + if err == nil { + return disabled + } + + return false +} + // VerifySettings will perform a sanity check for specific settings values. func VerifySettings() error { if GetStreamKey() == "" { diff --git a/router/router.go b/router/router.go index 6fa042404..adc3c1f7c 100644 --- a/router/router.go +++ b/router/router.go @@ -109,6 +109,9 @@ func Start() error { // Server summary http.HandleFunc("/api/admin/config/serversummary", middleware.RequireAdminAuth(admin.SetServerSummary)) + // Disable chat + http.HandleFunc("/api/admin/config/chat/disable", middleware.RequireAdminAuth(admin.SetChatDisabled)) + // Return all webhooks http.HandleFunc("/api/admin/webhooks", middleware.RequireAdminAuth(admin.GetWebhooks)) diff --git a/webroot/js/app.js b/webroot/js/app.js index 581898029..7d65875d4 100644 --- a/webroot/js/app.js +++ b/webroot/js/app.js @@ -8,7 +8,11 @@ import UsernameForm from './components/chat/username.js'; import VideoPoster from './components/video-poster.js'; import Chat from './components/chat/chat.js'; import Websocket from './utils/websocket.js'; -import { parseSecondsToDurationString, hasTouchScreen, getOrientation } from './utils/helpers.js'; +import { + parseSecondsToDurationString, + hasTouchScreen, + getOrientation, +} from './utils/helpers.js'; import { addNewlines, @@ -50,6 +54,7 @@ export default class App extends Component { websocket: new Websocket(), displayChat: chatStorage === null ? true : chatStorage, chatInputEnabled: false, // chat input box state + chatDisabled: false, username: getLocalStorage(KEY_USERNAME) || generateUsername(), touchKeyboardActive: false, @@ -195,12 +200,7 @@ export default class App extends Component { if (!status) { return; } - const { - viewerCount, - online, - lastConnectTime, - streamTitle, - } = status; + const { viewerCount, online, lastConnectTime, streamTitle } = status; this.lastDisconnectTime = status.lastDisconnectTime; @@ -265,7 +265,9 @@ export default class App extends Component { } if (this.windowBlurred) { - document.title = ` 🔴 ${this.state.configData && this.state.configData.name}`; + document.title = ` 🔴 ${ + this.state.configData && this.state.configData.name + }`; } } @@ -289,7 +291,9 @@ export default class App extends Component { }); if (this.windowBlurred) { - document.title = ` 🟢 ${this.state.configData && this.state.configData.name}`; + document.title = ` 🟢 ${ + this.state.configData && this.state.configData.name + }`; } } @@ -302,7 +306,6 @@ export default class App extends Component { this.setState({ streamStatusMessage: `${MESSAGE_ONLINE} ${streamDurationString}`, }); - } handleUsernameChange(newName) { @@ -370,7 +373,7 @@ export default class App extends Component { handleSpaceBarPressed(e) { e.preventDefault(); - if(this.state.isPlaying) { + if (this.state.isPlaying) { this.setState({ isPlaying: false, }); @@ -384,7 +387,11 @@ export default class App extends Component { } handleKeyPressed(e) { - if (e.code === 'Space' && e.target === document.body && this.state.streamOnline) { + if ( + e.code === 'Space' && + e.target === document.body && + this.state.streamOnline + ) { this.handleSpaceBarPressed(e); } } @@ -408,7 +415,6 @@ export default class App extends Component { windowWidth, } = state; - const { version: appVersion, logo = TEMP_IMAGE, @@ -417,45 +423,52 @@ export default class App extends Component { tags = [], name, extraPageContent, + chatDisabled, } = configData; const bgUserLogo = { backgroundImage: `url(${logo})` }; - const tagList = (tags !== null && tags.length > 0) - ? tags.map( - (tag, index) => html` -