2021-02-19 10:05:52 +03:00
package admin
import (
"encoding/json"
"fmt"
2021-05-25 02:13:49 +03:00
"net"
2021-02-19 10:05:52 +03:00
"net/http"
2021-11-20 09:42:50 +03:00
"os"
2021-02-19 10:05:52 +03:00
"path/filepath"
"reflect"
2021-03-22 00:10:56 +03:00
"strings"
2021-02-19 10:05:52 +03:00
2022-01-13 00:53:10 +03:00
"github.com/owncast/owncast/activitypub/outbox"
2021-02-19 10:05:52 +03:00
"github.com/owncast/owncast/controllers"
2021-07-20 05:22:29 +03:00
"github.com/owncast/owncast/core/chat"
2021-02-19 10:05:52 +03:00
"github.com/owncast/owncast/core/data"
2021-07-20 05:22:29 +03:00
"github.com/owncast/owncast/core/user"
2023-03-28 21:34:00 +03:00
"github.com/owncast/owncast/core/webhooks"
2021-02-19 10:05:52 +03:00
"github.com/owncast/owncast/models"
"github.com/owncast/owncast/utils"
log "github.com/sirupsen/logrus"
2022-03-17 23:09:38 +03:00
"github.com/teris-io/shortid"
2021-02-19 10:05:52 +03:00
)
// ConfigValue is a container object that holds a value, is encoded, and saved to the database.
type ConfigValue struct {
Value interface { } ` json:"value" `
}
// SetTags will handle the web config request to set tags.
func SetTags ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValues , success := getValuesFromRequest ( w , r )
if ! success {
return
}
2021-06-29 20:21:00 +03:00
tagStrings := make ( [ ] string , 0 )
2021-02-19 10:05:52 +03:00
for _ , tag := range configValues {
2021-10-19 17:01:19 +03:00
tagStrings = append ( tagStrings , strings . TrimLeft ( tag . Value . ( string ) , "#" ) )
2021-02-19 10:05:52 +03:00
}
if err := data . SetServerMetadataTags ( tagStrings ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2022-01-13 00:53:10 +03:00
// Update Fediverse followers about this change.
if err := outbox . UpdateFollowersWithAccountUpdates ( ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2021-02-19 10:05:52 +03:00
controllers . WriteSimpleResponse ( w , true , "changed" )
}
// SetStreamTitle will handle the web config request to set the current stream title.
func SetStreamTitle ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
value := configValue . Value . ( string )
if err := data . SetStreamTitle ( value ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
if value != "" {
2021-02-23 22:24:32 +03:00
sendSystemChatAction ( fmt . Sprintf ( "Stream title changed to **%s**" , value ) , true )
2023-03-28 21:34:00 +03:00
go webhooks . SendStreamStatusEvent ( models . StreamTitleUpdated )
2021-02-19 10:05:52 +03:00
}
controllers . WriteSimpleResponse ( w , true , "changed" )
}
2021-09-12 10:18:15 +03:00
// ExternalSetStreamTitle will change the stream title on behalf of an external integration API request.
2021-07-20 05:22:29 +03:00
func ExternalSetStreamTitle ( integration user . ExternalAPIUser , w http . ResponseWriter , r * http . Request ) {
SetStreamTitle ( w , r )
}
2021-03-18 07:11:17 +03:00
2021-07-20 05:22:29 +03:00
func sendSystemChatAction ( messageText string , ephemeral bool ) {
if err := chat . SendSystemAction ( messageText , ephemeral ) ; err != nil {
2021-02-19 10:05:52 +03:00
log . Errorln ( err )
}
}
// SetServerName will handle the web config request to set the server's name.
func SetServerName ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if err := data . SetServerName ( configValue . Value . ( string ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2022-01-13 00:53:10 +03:00
// Update Fediverse followers about this change.
if err := outbox . UpdateFollowersWithAccountUpdates ( ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2021-02-19 10:05:52 +03:00
controllers . WriteSimpleResponse ( w , true , "changed" )
}
// SetServerSummary will handle the web config request to set the about/summary text.
func SetServerSummary ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if err := data . SetServerSummary ( configValue . Value . ( string ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2022-01-13 00:53:10 +03:00
// Update Fediverse followers about this change.
if err := outbox . UpdateFollowersWithAccountUpdates ( ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2021-02-19 10:05:52 +03:00
controllers . WriteSimpleResponse ( w , true , "changed" )
}
2022-08-10 08:09:43 +03:00
// SetCustomOfflineMessage will set a message to display when the server is offline.
func SetCustomOfflineMessage ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if err := data . SetCustomOfflineMessage ( strings . TrimSpace ( configValue . Value . ( string ) ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "changed" )
}
2021-03-22 00:10:56 +03:00
// SetServerWelcomeMessage will handle the web config request to set the welcome message text.
func SetServerWelcomeMessage ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if err := data . SetServerWelcomeMessage ( strings . TrimSpace ( configValue . Value . ( string ) ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "changed" )
}
2021-02-19 10:05:52 +03:00
// SetExtraPageContent will handle the web config request to set the page markdown content.
func SetExtraPageContent ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if err := data . SetExtraPageBodyContent ( configValue . Value . ( string ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "changed" )
}
2022-11-23 09:08:25 +03:00
// SetAdminPassword will handle the web config request to set the server admin password.
func SetAdminPassword ( w http . ResponseWriter , r * http . Request ) {
2021-02-19 10:05:52 +03:00
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
2022-11-23 09:08:25 +03:00
if err := data . SetAdminPassword ( configValue . Value . ( string ) ) ; err != nil {
2021-02-19 10:05:52 +03:00
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "changed" )
}
2021-03-22 02:07:10 +03:00
// SetLogo will handle a new logo image file being uploaded.
func SetLogo ( w http . ResponseWriter , r * http . Request ) {
2021-02-19 10:05:52 +03:00
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
2022-12-29 02:01:45 +03:00
value , ok := configValue . Value . ( string )
if ! ok {
controllers . WriteSimpleResponse ( w , false , "unable to find image data" )
return
}
bytes , extension , err := utils . DecodeBase64Image ( value )
2021-03-22 02:07:10 +03:00
if err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
imgPath := filepath . Join ( "data" , "logo" + extension )
2022-03-17 23:09:38 +03:00
if err := os . WriteFile ( imgPath , bytes , 0 o600 ) ; err != nil {
2021-03-22 02:07:10 +03:00
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
2021-02-19 10:05:52 +03:00
return
}
2021-03-22 02:07:10 +03:00
if err := data . SetLogoPath ( "logo" + extension ) ; err != nil {
2021-02-19 10:05:52 +03:00
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2022-03-17 23:09:38 +03:00
if err := data . SetLogoUniquenessString ( shortid . MustGenerate ( ) ) ; err != nil {
log . Error ( "Error saving logo uniqueness string: " , err )
}
2022-01-13 00:53:10 +03:00
// Update Fediverse followers about this change.
if err := outbox . UpdateFollowersWithAccountUpdates ( ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2021-02-19 10:05:52 +03:00
controllers . WriteSimpleResponse ( w , true , "changed" )
}
// SetNSFW will handle the web config request to set the NSFW flag.
func SetNSFW ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if err := data . SetNSFW ( configValue . Value . ( bool ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "changed" )
}
// SetFfmpegPath will handle the web config request to validate and set an updated copy of ffmpg.
func SetFfmpegPath ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
path := configValue . Value . ( string )
if err := utils . VerifyFFMpegPath ( path ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
if err := data . SetFfmpegPath ( configValue . Value . ( string ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "changed" )
}
// SetWebServerPort will handle the web config request to set the server's HTTP port.
func SetWebServerPort ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
2021-05-25 02:13:49 +03:00
if port , ok := configValue . Value . ( float64 ) ; ok {
if ( port < 1 ) || ( port > 65535 ) {
controllers . WriteSimpleResponse ( w , false , "Port number must be between 1 and 65535" )
return
}
if err := data . SetHTTPPortNumber ( port ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2021-09-12 10:18:15 +03:00
controllers . WriteSimpleResponse ( w , true , "HTTP port set" )
return
2021-05-25 02:13:49 +03:00
}
2021-09-12 10:18:15 +03:00
2021-05-25 02:13:49 +03:00
controllers . WriteSimpleResponse ( w , false , "Invalid type or value, port must be a number" )
}
// SetWebServerIP will handle the web config request to set the server's HTTP listen address.
func SetWebServerIP ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
2021-02-19 10:05:52 +03:00
return
}
2021-05-25 02:13:49 +03:00
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if input , ok := configValue . Value . ( string ) ; ok {
if ip := net . ParseIP ( input ) ; ip != nil {
if err := data . SetHTTPListenAddress ( ip . String ( ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2021-09-12 10:18:15 +03:00
controllers . WriteSimpleResponse ( w , true , "HTTP listen address set" )
2021-05-25 02:13:49 +03:00
return
}
2021-09-12 10:18:15 +03:00
controllers . WriteSimpleResponse ( w , false , "Invalid IP address" )
return
2021-05-25 02:13:49 +03:00
}
controllers . WriteSimpleResponse ( w , false , "Invalid type or value, IP address must be a string" )
2021-02-19 10:05:52 +03:00
}
// SetRTMPServerPort will handle the web config request to set the inbound RTMP port.
func SetRTMPServerPort ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if err := data . SetRTMPPortNumber ( configValue . Value . ( float64 ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "rtmp port set" )
}
// SetServerURL will handle the web config request to set the full server URL.
func SetServerURL ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
2022-01-21 04:07:15 +03:00
rawValue , ok := configValue . Value . ( string )
if ! ok {
2022-12-11 08:10:10 +03:00
controllers . WriteSimpleResponse ( w , false , "could not read server url" )
return
}
serverHostString := utils . GetHostnameFromURLString ( rawValue )
if serverHostString == "" {
2022-01-21 04:07:15 +03:00
controllers . WriteSimpleResponse ( w , false , "server url value invalid" )
return
}
// Trim any trailing slash
serverURL := strings . TrimRight ( rawValue , "/" )
if err := data . SetServerURL ( serverURL ) ; err != nil {
2021-02-19 10:05:52 +03:00
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "server url set" )
}
2022-03-07 04:11:51 +03:00
// SetSocketHostOverride will set the host override for the websocket.
func SetSocketHostOverride ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if err := data . SetWebsocketOverrideHost ( configValue . Value . ( string ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "websocket host override set" )
}
2021-02-19 10:05:52 +03:00
// SetDirectoryEnabled will handle the web config request to enable or disable directory registration.
func SetDirectoryEnabled ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if err := data . SetDirectoryEnabled ( configValue . Value . ( bool ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "directory state changed" )
}
// SetStreamLatencyLevel will handle the web config request to set the stream latency level.
func SetStreamLatencyLevel ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
return
}
if err := data . SetStreamLatencyLevel ( configValue . Value . ( float64 ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "error setting stream latency " + err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "set stream latency" )
}
// SetS3Configuration will handle the web config request to set the storage configuration.
func SetS3Configuration ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
type s3ConfigurationRequest struct {
Value models . S3 ` json:"value" `
}
decoder := json . NewDecoder ( r . Body )
var newS3Config s3ConfigurationRequest
if err := decoder . Decode ( & newS3Config ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "unable to update s3 config with provided values" )
return
}
if newS3Config . Value . Enabled {
2021-09-12 10:18:15 +03:00
if newS3Config . Value . Endpoint == "" || ! utils . IsValidURL ( ( newS3Config . Value . Endpoint ) ) {
2021-02-19 10:05:52 +03:00
controllers . WriteSimpleResponse ( w , false , "s3 support requires an endpoint" )
return
}
if newS3Config . Value . AccessKey == "" || newS3Config . Value . Secret == "" {
controllers . WriteSimpleResponse ( w , false , "s3 support requires an access key and secret" )
return
}
if newS3Config . Value . Region == "" {
controllers . WriteSimpleResponse ( w , false , "s3 support requires a region and endpoint" )
return
}
if newS3Config . Value . Bucket == "" {
controllers . WriteSimpleResponse ( w , false , "s3 support requires a bucket created for storing public video segments" )
return
}
}
2021-07-20 09:37:06 +03:00
if err := data . SetS3Config ( newS3Config . Value ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2021-02-19 10:05:52 +03:00
controllers . WriteSimpleResponse ( w , true , "storage configuration changed" )
}
// SetStreamOutputVariants will handle the web config request to set the video output stream variants.
func SetStreamOutputVariants ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
type streamOutputVariantRequest struct {
Value [ ] models . StreamOutputVariant ` json:"value" `
}
decoder := json . NewDecoder ( r . Body )
var videoVariants streamOutputVariantRequest
if err := decoder . Decode ( & videoVariants ) ; err != nil {
2021-03-03 06:10:27 +03:00
controllers . WriteSimpleResponse ( w , false , "unable to update video config with provided values " + err . Error ( ) )
2021-02-19 10:05:52 +03:00
return
}
if err := data . SetStreamOutputVariants ( videoVariants . Value ) ; err != nil {
2021-03-03 06:10:27 +03:00
controllers . WriteSimpleResponse ( w , false , "unable to update video config with provided values " + err . Error ( ) )
2021-02-19 10:05:52 +03:00
return
}
controllers . WriteSimpleResponse ( w , true , "stream output variants updated" )
}
// SetSocialHandles will handle the web config request to set the external social profile links.
func SetSocialHandles ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
type socialHandlesRequest struct {
Value [ ] models . SocialHandle ` json:"value" `
}
decoder := json . NewDecoder ( r . Body )
var socialHandles socialHandlesRequest
if err := decoder . Decode ( & socialHandles ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "unable to update social handles with provided values" )
return
}
if err := data . SetSocialHandles ( socialHandles . Value ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "unable to update social handles with provided values" )
return
}
2022-01-13 00:53:10 +03:00
// Update Fediverse followers about this change.
if err := outbox . UpdateFollowersWithAccountUpdates ( ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2021-02-19 10:05:52 +03:00
controllers . WriteSimpleResponse ( w , true , "social handles updated" )
}
2021-03-14 21:46:27 +03:00
// 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
}
2021-07-20 09:37:06 +03:00
if err := data . SetChatDisabled ( configValue . Value . ( bool ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2021-03-14 21:46:27 +03:00
controllers . WriteSimpleResponse ( w , true , "chat disabled status updated" )
}
2021-04-15 23:55:51 +03:00
// SetVideoCodec will change the codec used for video encoding.
func SetVideoCodec ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
configValue , success := getValueFromRequest ( w , r )
if ! success {
controllers . WriteSimpleResponse ( w , false , "unable to change video codec" )
return
}
if err := data . SetVideoCodec ( configValue . Value . ( string ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "unable to update codec" )
return
}
controllers . WriteSimpleResponse ( w , true , "video codec updated" )
}
2021-03-16 01:32:52 +03:00
// SetExternalActions will set the 3rd party actions for the web interface.
func SetExternalActions ( w http . ResponseWriter , r * http . Request ) {
type externalActionsRequest struct {
Value [ ] models . ExternalAction ` json:"value" `
}
decoder := json . NewDecoder ( r . Body )
var actions externalActionsRequest
if err := decoder . Decode ( & actions ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "unable to update external actions with provided values" )
return
}
if err := data . SetExternalActions ( actions . Value ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "unable to update external actions with provided values" )
2022-04-23 23:19:17 +03:00
return
2021-03-16 01:32:52 +03:00
}
controllers . WriteSimpleResponse ( w , true , "external actions update" )
}
2021-04-12 03:40:22 +03:00
// SetCustomStyles will set the CSS string we insert into the page.
func SetCustomStyles ( w http . ResponseWriter , r * http . Request ) {
customStyles , success := getValueFromRequest ( w , r )
if ! success {
controllers . WriteSimpleResponse ( w , false , "unable to update custom styles" )
return
}
2021-07-20 09:37:06 +03:00
if err := data . SetCustomStyles ( customStyles . Value . ( string ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
2021-04-12 10:06:56 +03:00
controllers . WriteSimpleResponse ( w , true , "custom styles updated" )
2021-05-23 07:50:34 +03:00
}
2023-01-19 09:38:24 +03:00
// SetCustomJavascript will set the Javascript string we insert into the page.
func SetCustomJavascript ( w http . ResponseWriter , r * http . Request ) {
customJavascript , success := getValueFromRequest ( w , r )
if ! success {
controllers . WriteSimpleResponse ( w , false , "unable to update custom javascript" )
return
}
if err := data . SetCustomJavascript ( customJavascript . Value . ( string ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "custom styles updated" )
}
2021-07-20 05:22:29 +03:00
// SetForbiddenUsernameList will set the list of usernames we do not allow to use.
func SetForbiddenUsernameList ( w http . ResponseWriter , r * http . Request ) {
type forbiddenUsernameListRequest struct {
Value [ ] string ` json:"value" `
}
decoder := json . NewDecoder ( r . Body )
var request forbiddenUsernameListRequest
if err := decoder . Decode ( & request ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "unable to update forbidden usernames with provided values" )
2021-05-23 07:50:34 +03:00
return
}
2021-07-20 05:22:29 +03:00
if err := data . SetForbiddenUsernameList ( request . Value ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
2022-04-23 23:19:17 +03:00
return
2021-07-20 05:22:29 +03:00
}
2021-04-12 10:06:56 +03:00
2021-07-20 05:22:29 +03:00
controllers . WriteSimpleResponse ( w , true , "forbidden username list updated" )
2021-04-12 03:40:22 +03:00
}
2022-01-12 21:18:08 +03:00
// SetSuggestedUsernameList will set the list of suggested usernames that newly registered users are assigned if it isn't inferred otherwise (i.e. through a proxy).
func SetSuggestedUsernameList ( w http . ResponseWriter , r * http . Request ) {
type suggestedUsernameListRequest struct {
Value [ ] string ` json:"value" `
}
decoder := json . NewDecoder ( r . Body )
var request suggestedUsernameListRequest
if err := decoder . Decode ( & request ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "unable to update suggested usernames with provided values" )
return
}
if err := data . SetSuggestedUsernamesList ( request . Value ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
2022-04-23 23:19:17 +03:00
return
2022-01-12 21:18:08 +03:00
}
controllers . WriteSimpleResponse ( w , true , "suggested username list updated" )
}
2022-03-06 09:34:06 +03:00
// SetChatJoinMessagesEnabled will enable or disable the chat join messages.
func SetChatJoinMessagesEnabled ( 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 join messages enabled" )
return
}
if err := data . SetChatJoinMessagesEnabled ( configValue . Value . ( bool ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "chat join message status updated" )
}
2022-06-26 10:46:55 +03:00
// SetHideViewerCount will enable or disable hiding the viewer count.
func SetHideViewerCount ( 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 hiding viewer count" )
return
}
if err := data . SetHideViewerCount ( configValue . Value . ( bool ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "hide viewer count setting updated" )
}
2023-05-30 21:09:51 +03:00
// SetDisableSearchIndexing will set search indexing support.
func SetDisableSearchIndexing ( 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 search indexing" )
return
}
if err := data . SetDisableSearchIndexing ( configValue . Value . ( bool ) ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "search indexing support updated" )
}
2023-05-31 00:05:24 +03:00
// SetVideoServingEndpoint will save the video serving endpoint.
func SetVideoServingEndpoint ( w http . ResponseWriter , r * http . Request ) {
endpoint , success := getValueFromRequest ( w , r )
if ! success {
controllers . WriteSimpleResponse ( w , false , "unable to update custom video serving endpoint" )
return
}
value , ok := endpoint . Value . ( string )
if ! ok {
controllers . WriteSimpleResponse ( w , false , "unable to update custom video serving endpoint" )
return
}
if err := data . SetVideoServingEndpoint ( value ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "custom video serving endpoint updated" )
}
2021-02-19 10:05:52 +03:00
func requirePOST ( w http . ResponseWriter , r * http . Request ) bool {
if r . Method != controllers . POST {
controllers . WriteSimpleResponse ( w , false , r . Method + " not supported" )
return false
}
return true
}
func getValueFromRequest ( w http . ResponseWriter , r * http . Request ) ( ConfigValue , bool ) {
decoder := json . NewDecoder ( r . Body )
var configValue ConfigValue
if err := decoder . Decode ( & configValue ) ; err != nil {
log . Warnln ( err )
controllers . WriteSimpleResponse ( w , false , "unable to parse new value" )
return configValue , false
}
return configValue , true
}
func getValuesFromRequest ( w http . ResponseWriter , r * http . Request ) ( [ ] ConfigValue , bool ) {
var values [ ] ConfigValue
decoder := json . NewDecoder ( r . Body )
var configValue ConfigValue
if err := decoder . Decode ( & configValue ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "unable to parse array of values" )
return values , false
}
object := reflect . ValueOf ( configValue . Value )
for i := 0 ; i < object . Len ( ) ; i ++ {
values = append ( values , ConfigValue { Value : object . Index ( i ) . Interface ( ) } )
}
return values , true
}
2022-11-23 09:08:25 +03:00
// SetStreamKeys will set the valid stream keys.
func SetStreamKeys ( w http . ResponseWriter , r * http . Request ) {
if ! requirePOST ( w , r ) {
return
}
2022-11-24 03:39:55 +03:00
type streamKeysRequest struct {
Value [ ] models . StreamKey ` json:"value" `
2022-11-23 09:08:25 +03:00
}
2022-11-24 03:39:55 +03:00
decoder := json . NewDecoder ( r . Body )
var streamKeys streamKeysRequest
if err := decoder . Decode ( & streamKeys ) ; err != nil {
controllers . WriteSimpleResponse ( w , false , "unable to update stream keys with provided values" )
return
2022-11-23 09:08:25 +03:00
}
2023-06-13 22:58:22 +03:00
if len ( streamKeys . Value ) == 0 {
controllers . WriteSimpleResponse ( w , false , "must provide at least one valid stream key" )
return
}
for _ , streamKey := range streamKeys . Value {
if streamKey . Key == "" {
controllers . WriteSimpleResponse ( w , false , "stream key cannot be empty" )
return
}
}
2022-11-24 03:39:55 +03:00
if err := data . SetStreamKeys ( streamKeys . Value ) ; err != nil {
2022-11-23 09:08:25 +03:00
controllers . WriteSimpleResponse ( w , false , err . Error ( ) )
return
}
controllers . WriteSimpleResponse ( w , true , "changed" )
}