0b5d7c8a4d
* WIP * fix(test): fix ap test failing * fix: fix unkeyed fields being used * chore(tests): clean up browser tests by splitting out federation UI tests
1004 lines
31 KiB
Go
1004 lines
31 KiB
Go
package configrepository
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/owncast/owncast/config"
|
|
"github.com/owncast/owncast/core/data"
|
|
"github.com/owncast/owncast/models"
|
|
"github.com/owncast/owncast/static"
|
|
"github.com/owncast/owncast/utils"
|
|
"github.com/pkg/errors"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type SqlConfigRepository struct {
|
|
datastore *data.Datastore
|
|
}
|
|
|
|
// NOTE: This is temporary during the transition period.
|
|
var temporaryGlobalInstance ConfigRepository
|
|
|
|
// Get will return the user repository.
|
|
func Get() ConfigRepository {
|
|
if temporaryGlobalInstance == nil {
|
|
i := New(data.GetDatastore())
|
|
temporaryGlobalInstance = i
|
|
}
|
|
return temporaryGlobalInstance
|
|
}
|
|
|
|
// New will create a new instance of the UserRepository.
|
|
func New(datastore *data.Datastore) ConfigRepository {
|
|
r := SqlConfigRepository{
|
|
datastore: datastore,
|
|
}
|
|
|
|
migrateDatastoreValues(datastore)
|
|
|
|
// Set the server initialization date if needed.
|
|
if hasSetInitDate, _ := r.GetServerInitTime(); hasSetInitDate == nil || !hasSetInitDate.Valid {
|
|
_ = r.SetServerInitTime(time.Now())
|
|
}
|
|
|
|
if !r.HasPopulatedDefaults() {
|
|
r.PopulateDefaults()
|
|
}
|
|
|
|
return &r
|
|
}
|
|
|
|
// GetExtraPageBodyContent will return the user-supplied body content.
|
|
func (r *SqlConfigRepository) GetExtraPageBodyContent() string {
|
|
content, err := r.datastore.GetString(extraContentKey)
|
|
if err != nil {
|
|
log.Traceln(extraContentKey, err)
|
|
return config.GetDefaults().PageBodyContent
|
|
}
|
|
|
|
return content
|
|
}
|
|
|
|
// SetExtraPageBodyContent will set the user-supplied body content.
|
|
func (r *SqlConfigRepository) SetExtraPageBodyContent(content string) error {
|
|
return r.datastore.SetString(extraContentKey, content)
|
|
}
|
|
|
|
// GetStreamTitle will return the name of the current stream.
|
|
func (r *SqlConfigRepository) GetStreamTitle() string {
|
|
title, err := r.datastore.GetString(streamTitleKey)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
return title
|
|
}
|
|
|
|
// SetStreamTitle will set the name of the current stream.
|
|
func (r *SqlConfigRepository) SetStreamTitle(title string) error {
|
|
return r.datastore.SetString(streamTitleKey, title)
|
|
}
|
|
|
|
// GetAdminPassword will return the admin password.
|
|
func (r *SqlConfigRepository) GetAdminPassword() string {
|
|
key, _ := r.datastore.GetString(adminPasswordKey)
|
|
return key
|
|
}
|
|
|
|
// SetAdminPassword will set the admin password.
|
|
func (r *SqlConfigRepository) SetAdminPassword(key string) error {
|
|
hashed_pass, err := utils.HashPassword(key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return r.datastore.SetString(adminPasswordKey, hashed_pass)
|
|
}
|
|
|
|
// GetLogoPath will return the path for the logo, relative to webroot.
|
|
func (r *SqlConfigRepository) GetLogoPath() string {
|
|
logo, err := r.datastore.GetString(logoPathKey)
|
|
if err != nil {
|
|
log.Traceln(logoPathKey, err)
|
|
return config.GetDefaults().Logo
|
|
}
|
|
|
|
if logo == "" {
|
|
return config.GetDefaults().Logo
|
|
}
|
|
|
|
return logo
|
|
}
|
|
|
|
// SetLogoPath will set the path for the logo, relative to webroot.
|
|
func (r *SqlConfigRepository) SetLogoPath(logo string) error {
|
|
return r.datastore.SetString(logoPathKey, logo)
|
|
}
|
|
|
|
// SetLogoUniquenessString will set the logo cache busting string.
|
|
func (r *SqlConfigRepository) SetLogoUniquenessString(uniqueness string) error {
|
|
return r.datastore.SetString(logoUniquenessKey, uniqueness)
|
|
}
|
|
|
|
// GetLogoUniquenessString will return the logo cache busting string.
|
|
func (r *SqlConfigRepository) GetLogoUniquenessString() string {
|
|
uniqueness, err := r.datastore.GetString(logoUniquenessKey)
|
|
if err != nil {
|
|
log.Traceln(logoUniquenessKey, err)
|
|
return ""
|
|
}
|
|
|
|
return uniqueness
|
|
}
|
|
|
|
// GetServerSummary will return the server summary text.
|
|
func (r *SqlConfigRepository) GetServerSummary() string {
|
|
summary, err := r.datastore.GetString(serverSummaryKey)
|
|
if err != nil {
|
|
log.Traceln(serverSummaryKey, err)
|
|
return ""
|
|
}
|
|
|
|
return summary
|
|
}
|
|
|
|
// SetServerSummary will set the server summary text.
|
|
func (r *SqlConfigRepository) SetServerSummary(summary string) error {
|
|
return r.datastore.SetString(serverSummaryKey, summary)
|
|
}
|
|
|
|
// GetServerWelcomeMessage will return the server welcome message text.
|
|
func (r *SqlConfigRepository) GetServerWelcomeMessage() string {
|
|
welcomeMessage, err := r.datastore.GetString(serverWelcomeMessageKey)
|
|
if err != nil {
|
|
log.Traceln(serverWelcomeMessageKey, err)
|
|
return config.GetDefaults().ServerWelcomeMessage
|
|
}
|
|
|
|
return welcomeMessage
|
|
}
|
|
|
|
// SetServerWelcomeMessage will set the server welcome message text.
|
|
func (r *SqlConfigRepository) SetServerWelcomeMessage(welcomeMessage string) error {
|
|
return r.datastore.SetString(serverWelcomeMessageKey, welcomeMessage)
|
|
}
|
|
|
|
// GetServerName will return the server name text.
|
|
func (r *SqlConfigRepository) GetServerName() string {
|
|
name, err := r.datastore.GetString(serverNameKey)
|
|
if err != nil {
|
|
log.Traceln(serverNameKey, err)
|
|
return config.GetDefaults().Name
|
|
}
|
|
|
|
return name
|
|
}
|
|
|
|
// SetServerName will set the server name text.
|
|
func (r *SqlConfigRepository) SetServerName(name string) error {
|
|
return r.datastore.SetString(serverNameKey, name)
|
|
}
|
|
|
|
// GetServerURL will return the server URL.
|
|
func (r *SqlConfigRepository) GetServerURL() string {
|
|
url, err := r.datastore.GetString(serverURLKey)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
return url
|
|
}
|
|
|
|
// SetServerURL will set the server URL.
|
|
func (r *SqlConfigRepository) SetServerURL(url string) error {
|
|
return r.datastore.SetString(serverURLKey, url)
|
|
}
|
|
|
|
// GetHTTPPortNumber will return the server HTTP port.
|
|
func (r *SqlConfigRepository) GetHTTPPortNumber() int {
|
|
port, err := r.datastore.GetNumber(httpPortNumberKey)
|
|
if err != nil {
|
|
log.Traceln(httpPortNumberKey, err)
|
|
return config.GetDefaults().WebServerPort
|
|
}
|
|
|
|
if port == 0 {
|
|
return config.GetDefaults().WebServerPort
|
|
}
|
|
return int(port)
|
|
}
|
|
|
|
// SetWebsocketOverrideHost will set the host override for websockets.
|
|
func (r *SqlConfigRepository) SetWebsocketOverrideHost(host string) error {
|
|
return r.datastore.SetString(websocketHostOverrideKey, host)
|
|
}
|
|
|
|
// GetWebsocketOverrideHost will return the host override for websockets.
|
|
func (r *SqlConfigRepository) GetWebsocketOverrideHost() string {
|
|
host, _ := r.datastore.GetString(websocketHostOverrideKey)
|
|
|
|
return host
|
|
}
|
|
|
|
// SetHTTPPortNumber will set the server HTTP port.
|
|
func (r *SqlConfigRepository) SetHTTPPortNumber(port float64) error {
|
|
return r.datastore.SetNumber(httpPortNumberKey, port)
|
|
}
|
|
|
|
// GetHTTPListenAddress will return the HTTP listen address.
|
|
func (r *SqlConfigRepository) GetHTTPListenAddress() string {
|
|
address, err := r.datastore.GetString(httpListenAddressKey)
|
|
if err != nil {
|
|
log.Traceln(httpListenAddressKey, err)
|
|
return config.GetDefaults().WebServerIP
|
|
}
|
|
return address
|
|
}
|
|
|
|
// SetHTTPListenAddress will set the server HTTP listen address.
|
|
func (r *SqlConfigRepository) SetHTTPListenAddress(address string) error {
|
|
return r.datastore.SetString(httpListenAddressKey, address)
|
|
}
|
|
|
|
// GetRTMPPortNumber will return the server RTMP port.
|
|
func (r *SqlConfigRepository) GetRTMPPortNumber() int {
|
|
port, err := r.datastore.GetNumber(rtmpPortNumberKey)
|
|
if err != nil {
|
|
log.Traceln(rtmpPortNumberKey, err)
|
|
return config.GetDefaults().RTMPServerPort
|
|
}
|
|
|
|
if port == 0 {
|
|
return config.GetDefaults().RTMPServerPort
|
|
}
|
|
|
|
return int(port)
|
|
}
|
|
|
|
// SetRTMPPortNumber will set the server RTMP port.
|
|
func (r *SqlConfigRepository) SetRTMPPortNumber(port float64) error {
|
|
return r.datastore.SetNumber(rtmpPortNumberKey, port)
|
|
}
|
|
|
|
// GetServerMetadataTags will return the metadata tags.
|
|
func (r *SqlConfigRepository) GetServerMetadataTags() []string {
|
|
tagsString, err := r.datastore.GetString(serverMetadataTagsKey)
|
|
if tagsString == "" {
|
|
return []string{}
|
|
}
|
|
|
|
if err != nil {
|
|
log.Traceln(serverMetadataTagsKey, err)
|
|
return []string{}
|
|
}
|
|
|
|
return strings.Split(tagsString, ",")
|
|
}
|
|
|
|
// SetServerMetadataTags will return the metadata tags.
|
|
func (r *SqlConfigRepository) SetServerMetadataTags(tags []string) error {
|
|
tagString := strings.Join(tags, ",")
|
|
return r.datastore.SetString(serverMetadataTagsKey, tagString)
|
|
}
|
|
|
|
// GetDirectoryEnabled will return if this server should register to YP.
|
|
func (r *SqlConfigRepository) GetDirectoryEnabled() bool {
|
|
enabled, err := r.datastore.GetBool(directoryEnabledKey)
|
|
if err != nil {
|
|
return config.GetDefaults().YPEnabled
|
|
}
|
|
|
|
return enabled
|
|
}
|
|
|
|
// SetDirectoryEnabled will set if this server should register to YP.
|
|
func (r *SqlConfigRepository) SetDirectoryEnabled(enabled bool) error {
|
|
return r.datastore.SetBool(directoryEnabledKey, enabled)
|
|
}
|
|
|
|
// SetDirectoryRegistrationKey will set the YP protocol registration key.
|
|
func (r *SqlConfigRepository) SetDirectoryRegistrationKey(key string) error {
|
|
return r.datastore.SetString(directoryRegistrationKeyKey, key)
|
|
}
|
|
|
|
// GetDirectoryRegistrationKey will return the YP protocol registration key.
|
|
func (r *SqlConfigRepository) GetDirectoryRegistrationKey() string {
|
|
key, _ := r.datastore.GetString(directoryRegistrationKeyKey)
|
|
return key
|
|
}
|
|
|
|
// GetSocialHandles will return the external social links.
|
|
func (r *SqlConfigRepository) GetSocialHandles() []models.SocialHandle {
|
|
var socialHandles []models.SocialHandle
|
|
|
|
configEntry, err := r.datastore.Get(socialHandlesKey)
|
|
if err != nil {
|
|
log.Traceln(socialHandlesKey, err)
|
|
return socialHandles
|
|
}
|
|
|
|
if err := configEntry.GetObject(&socialHandles); err != nil {
|
|
log.Traceln(err)
|
|
return socialHandles
|
|
}
|
|
|
|
return socialHandles
|
|
}
|
|
|
|
// SetSocialHandles will set the external social links.
|
|
func (r *SqlConfigRepository) SetSocialHandles(socialHandles []models.SocialHandle) error {
|
|
configEntry := models.ConfigEntry{Key: socialHandlesKey, Value: socialHandles}
|
|
return r.datastore.Save(configEntry)
|
|
}
|
|
|
|
// GetPeakSessionViewerCount will return the max number of viewers for this stream.
|
|
func (r *SqlConfigRepository) GetPeakSessionViewerCount() int {
|
|
count, err := r.datastore.GetNumber(peakViewersSessionKey)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return int(count)
|
|
}
|
|
|
|
// SetPeakSessionViewerCount will set the max number of viewers for this stream.
|
|
func (r *SqlConfigRepository) SetPeakSessionViewerCount(count int) error {
|
|
return r.datastore.SetNumber(peakViewersSessionKey, float64(count))
|
|
}
|
|
|
|
// GetPeakOverallViewerCount will return the overall max number of viewers.
|
|
func (r *SqlConfigRepository) GetPeakOverallViewerCount() int {
|
|
count, err := r.datastore.GetNumber(peakViewersOverallKey)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return int(count)
|
|
}
|
|
|
|
// SetPeakOverallViewerCount will set the overall max number of viewers.
|
|
func (r *SqlConfigRepository) SetPeakOverallViewerCount(count int) error {
|
|
return r.datastore.SetNumber(peakViewersOverallKey, float64(count))
|
|
}
|
|
|
|
// GetLastDisconnectTime will return the time the last stream ended.
|
|
func (r *SqlConfigRepository) GetLastDisconnectTime() (*utils.NullTime, error) {
|
|
var disconnectTime utils.NullTime
|
|
|
|
configEntry, err := r.datastore.Get(lastDisconnectTimeKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := configEntry.GetObject(&disconnectTime); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !disconnectTime.Valid || disconnectTime.Time.IsZero() {
|
|
return nil, err
|
|
}
|
|
|
|
return &disconnectTime, nil
|
|
}
|
|
|
|
// SetLastDisconnectTime will set the time the last stream ended.
|
|
func (r *SqlConfigRepository) SetLastDisconnectTime(disconnectTime time.Time) error {
|
|
savedDisconnectTime := utils.NullTime{Time: disconnectTime, Valid: true}
|
|
configEntry := models.ConfigEntry{Key: lastDisconnectTimeKey, Value: savedDisconnectTime}
|
|
return r.datastore.Save(configEntry)
|
|
}
|
|
|
|
// SetNSFW will set if this stream has NSFW content.
|
|
func (r *SqlConfigRepository) SetNSFW(isNSFW bool) error {
|
|
return r.datastore.SetBool(nsfwKey, isNSFW)
|
|
}
|
|
|
|
// GetNSFW will return if this stream has NSFW content.
|
|
func (r *SqlConfigRepository) GetNSFW() bool {
|
|
nsfw, err := r.datastore.GetBool(nsfwKey)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return nsfw
|
|
}
|
|
|
|
// SetFfmpegPath will set the custom ffmpeg path.
|
|
func (r *SqlConfigRepository) SetFfmpegPath(path string) error {
|
|
return r.datastore.SetString(ffmpegPathKey, path)
|
|
}
|
|
|
|
// GetFfMpegPath will return the ffmpeg path.
|
|
func (r *SqlConfigRepository) GetFfMpegPath() string {
|
|
path, err := r.datastore.GetString(ffmpegPathKey)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return path
|
|
}
|
|
|
|
// GetS3Config will return the external storage configuration.
|
|
func (r *SqlConfigRepository) GetS3Config() models.S3 {
|
|
configEntry, err := r.datastore.Get(s3StorageConfigKey)
|
|
if err != nil {
|
|
return models.S3{Enabled: false}
|
|
}
|
|
|
|
var s3Config models.S3
|
|
if err := configEntry.GetObject(&s3Config); err != nil {
|
|
return models.S3{Enabled: false}
|
|
}
|
|
|
|
return s3Config
|
|
}
|
|
|
|
// SetS3Config will set the external storage configuration.
|
|
func (r *SqlConfigRepository) SetS3Config(config models.S3) error {
|
|
configEntry := models.ConfigEntry{Key: s3StorageConfigKey, Value: config}
|
|
return r.datastore.Save(configEntry)
|
|
}
|
|
|
|
// GetStreamLatencyLevel will return the stream latency level.
|
|
func (r *SqlConfigRepository) GetStreamLatencyLevel() models.LatencyLevel {
|
|
level, err := r.datastore.GetNumber(videoLatencyLevel)
|
|
if err != nil {
|
|
level = 2 // default
|
|
} else if level > 4 {
|
|
level = 4 // highest
|
|
}
|
|
|
|
return models.GetLatencyLevel(int(level))
|
|
}
|
|
|
|
// SetStreamLatencyLevel will set the stream latency level.
|
|
func (r *SqlConfigRepository) SetStreamLatencyLevel(level float64) error {
|
|
return r.datastore.SetNumber(videoLatencyLevel, level)
|
|
}
|
|
|
|
// GetStreamOutputVariants will return all of the stream output variants.
|
|
func (r *SqlConfigRepository) GetStreamOutputVariants() []models.StreamOutputVariant {
|
|
configEntry, err := r.datastore.Get(videoStreamOutputVariantsKey)
|
|
if err != nil {
|
|
return config.GetDefaults().StreamVariants
|
|
}
|
|
|
|
var streamOutputVariants []models.StreamOutputVariant
|
|
if err := configEntry.GetObject(&streamOutputVariants); err != nil {
|
|
return config.GetDefaults().StreamVariants
|
|
}
|
|
|
|
if len(streamOutputVariants) == 0 {
|
|
return config.GetDefaults().StreamVariants
|
|
}
|
|
|
|
return streamOutputVariants
|
|
}
|
|
|
|
// SetStreamOutputVariants will set the stream output variants.
|
|
func (r *SqlConfigRepository) SetStreamOutputVariants(variants []models.StreamOutputVariant) error {
|
|
configEntry := models.ConfigEntry{Key: videoStreamOutputVariantsKey, Value: variants}
|
|
return r.datastore.Save(configEntry)
|
|
}
|
|
|
|
// SetChatDisabled will disable chat if set to true.
|
|
func (r *SqlConfigRepository) SetChatDisabled(disabled bool) error {
|
|
return r.datastore.SetBool(chatDisabledKey, disabled)
|
|
}
|
|
|
|
// GetChatDisabled will return if chat is disabled.
|
|
func (r *SqlConfigRepository) GetChatDisabled() bool {
|
|
disabled, err := r.datastore.GetBool(chatDisabledKey)
|
|
if err == nil {
|
|
return disabled
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// SetChatEstablishedUsersOnlyMode sets the state of established user only mode.
|
|
func (r *SqlConfigRepository) SetChatEstablishedUsersOnlyMode(enabled bool) error {
|
|
return r.datastore.SetBool(chatEstablishedUsersOnlyModeKey, enabled)
|
|
}
|
|
|
|
// GetChatEstbalishedUsersOnlyMode returns the state of established user only mode.
|
|
func (r *SqlConfigRepository) GetChatEstbalishedUsersOnlyMode() bool {
|
|
enabled, err := r.datastore.GetBool(chatEstablishedUsersOnlyModeKey)
|
|
if err == nil {
|
|
return enabled
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// SetChatSpamProtectionEnabled will enable chat spam protection if set to true.
|
|
func (r *SqlConfigRepository) SetChatSpamProtectionEnabled(enabled bool) error {
|
|
return r.datastore.SetBool(chatSpamProtectionEnabledKey, enabled)
|
|
}
|
|
|
|
// GetChatSpamProtectionEnabled will return if chat spam protection is enabled.
|
|
func (r *SqlConfigRepository) GetChatSpamProtectionEnabled() bool {
|
|
enabled, err := r.datastore.GetBool(chatSpamProtectionEnabledKey)
|
|
if err == nil {
|
|
return enabled
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// SetChatSlurFilterEnabled will enable the chat slur filter.
|
|
func (r *SqlConfigRepository) SetChatSlurFilterEnabled(enabled bool) error {
|
|
return r.datastore.SetBool(chatSlurFilterEnabledKey, enabled)
|
|
}
|
|
|
|
// GetChatSlurFilterEnabled will return if the chat slur filter is enabled.
|
|
func (r *SqlConfigRepository) GetChatSlurFilterEnabled() bool {
|
|
enabled, err := r.datastore.GetBool(chatSlurFilterEnabledKey)
|
|
if err == nil {
|
|
return enabled
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// GetExternalActions will return the registered external actions.
|
|
func (r *SqlConfigRepository) GetExternalActions() []models.ExternalAction {
|
|
configEntry, err := r.datastore.Get(externalActionsKey)
|
|
if err != nil {
|
|
return []models.ExternalAction{}
|
|
}
|
|
|
|
var externalActions []models.ExternalAction
|
|
if err := configEntry.GetObject(&externalActions); err != nil {
|
|
return []models.ExternalAction{}
|
|
}
|
|
|
|
return externalActions
|
|
}
|
|
|
|
// SetExternalActions will save external actions.
|
|
func (r *SqlConfigRepository) SetExternalActions(actions []models.ExternalAction) error {
|
|
configEntry := models.ConfigEntry{Key: externalActionsKey, Value: actions}
|
|
return r.datastore.Save(configEntry)
|
|
}
|
|
|
|
// SetCustomStyles will save a string with CSS to insert into the page.
|
|
func (r *SqlConfigRepository) SetCustomStyles(styles string) error {
|
|
return r.datastore.SetString(customStylesKey, styles)
|
|
}
|
|
|
|
// GetCustomStyles will return a string with CSS to insert into the page.
|
|
func (r *SqlConfigRepository) GetCustomStyles() string {
|
|
style, err := r.datastore.GetString(customStylesKey)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
return style
|
|
}
|
|
|
|
// SetCustomJavascript will save a string with Javascript to insert into the page.
|
|
func (r *SqlConfigRepository) SetCustomJavascript(styles string) error {
|
|
return r.datastore.SetString(customJavascriptKey, styles)
|
|
}
|
|
|
|
// GetCustomJavascript will return a string with Javascript to insert into the page.
|
|
func (r *SqlConfigRepository) GetCustomJavascript() string {
|
|
style, err := r.datastore.GetString(customJavascriptKey)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
return style
|
|
}
|
|
|
|
// SetVideoCodec will set the codec used for video encoding.
|
|
func (r *SqlConfigRepository) SetVideoCodec(codec string) error {
|
|
return r.datastore.SetString(videoCodecKey, codec)
|
|
}
|
|
|
|
// GetVideoCodec returns the codec to use for transcoding video.
|
|
func (r *SqlConfigRepository) GetVideoCodec() string {
|
|
codec, err := r.datastore.GetString(videoCodecKey)
|
|
if codec == "" || err != nil {
|
|
return "libx264" // Default value
|
|
}
|
|
|
|
return codec
|
|
}
|
|
|
|
// VerifySettings will perform a sanity check for specific settings values.
|
|
func (r *SqlConfigRepository) VerifySettings() error {
|
|
if len(r.GetStreamKeys()) == 0 && config.TemporaryStreamKey == "" {
|
|
log.Errorln("No stream key set. Streaming is disabled. Please set one via the admin or command line arguments")
|
|
}
|
|
|
|
if r.GetAdminPassword() == "" {
|
|
return errors.New("no admin password set. Please set one via the admin or command line arguments")
|
|
}
|
|
|
|
logoPath := r.GetLogoPath()
|
|
if !utils.DoesFileExists(filepath.Join(config.DataDirectory, logoPath)) {
|
|
log.Traceln(logoPath, "not found in the data directory. copying a default logo.")
|
|
logo := static.GetLogo()
|
|
if err := os.WriteFile(filepath.Join(config.DataDirectory, "logo.png"), logo, 0o600); err != nil {
|
|
return errors.Wrap(err, "failed to write logo to disk")
|
|
}
|
|
if err := r.SetLogoPath("logo.png"); err != nil {
|
|
return errors.Wrap(err, "failed to save logo filename")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// FindHighestVideoQualityIndex will return the highest quality from a slice of variants.
|
|
func (r *SqlConfigRepository) FindHighestVideoQualityIndex(qualities []models.StreamOutputVariant) (int, bool) {
|
|
type IndexedQuality struct {
|
|
quality models.StreamOutputVariant
|
|
index int
|
|
}
|
|
|
|
if len(qualities) < 2 {
|
|
return 0, qualities[0].IsVideoPassthrough
|
|
}
|
|
|
|
indexedQualities := make([]IndexedQuality, 0)
|
|
for index, quality := range qualities {
|
|
indexedQuality := IndexedQuality{quality, index}
|
|
indexedQualities = append(indexedQualities, indexedQuality)
|
|
}
|
|
|
|
sort.Slice(indexedQualities, func(a, b int) bool {
|
|
if indexedQualities[a].quality.IsVideoPassthrough && !indexedQualities[b].quality.IsVideoPassthrough {
|
|
return true
|
|
}
|
|
|
|
if !indexedQualities[a].quality.IsVideoPassthrough && indexedQualities[b].quality.IsVideoPassthrough {
|
|
return false
|
|
}
|
|
|
|
return indexedQualities[a].quality.VideoBitrate > indexedQualities[b].quality.VideoBitrate
|
|
})
|
|
|
|
// nolint:gosec
|
|
selectedQuality := indexedQualities[0]
|
|
return selectedQuality.index, selectedQuality.quality.IsVideoPassthrough
|
|
}
|
|
|
|
// GetForbiddenUsernameList will return the blocked usernames as a comma separated string.
|
|
func (r *SqlConfigRepository) GetForbiddenUsernameList() []string {
|
|
usernames, err := r.datastore.GetStringSlice(blockedUsernamesKey)
|
|
if err != nil {
|
|
return config.DefaultForbiddenUsernames
|
|
}
|
|
|
|
if len(usernames) == 0 {
|
|
return config.DefaultForbiddenUsernames
|
|
}
|
|
|
|
return usernames
|
|
}
|
|
|
|
// SetForbiddenUsernameList set the username blocklist as a comma separated string.
|
|
func (r *SqlConfigRepository) SetForbiddenUsernameList(usernames []string) error {
|
|
return r.datastore.SetStringSlice(blockedUsernamesKey, usernames)
|
|
}
|
|
|
|
// GetSuggestedUsernamesList will return the suggested usernames.
|
|
// If the number of suggested usernames is smaller than 10, the number pool is
|
|
// not used (see code in the CreateAnonymousUser function).
|
|
func (r *SqlConfigRepository) GetSuggestedUsernamesList() []string {
|
|
usernames, err := r.datastore.GetStringSlice(suggestedUsernamesKey)
|
|
|
|
if err != nil || len(usernames) == 0 {
|
|
return []string{}
|
|
}
|
|
|
|
return usernames
|
|
}
|
|
|
|
// SetSuggestedUsernamesList sets the username suggestion list.
|
|
func (r *SqlConfigRepository) SetSuggestedUsernamesList(usernames []string) error {
|
|
return r.datastore.SetStringSlice(suggestedUsernamesKey, usernames)
|
|
}
|
|
|
|
// GetServerInitTime will return when the server was first setup.
|
|
func (r *SqlConfigRepository) GetServerInitTime() (*utils.NullTime, error) {
|
|
var t utils.NullTime
|
|
|
|
configEntry, err := r.datastore.Get(serverInitDateKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := configEntry.GetObject(&t); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !t.Valid {
|
|
return nil, err
|
|
}
|
|
|
|
return &t, nil
|
|
}
|
|
|
|
// SetServerInitTime will set when the server was first created.
|
|
func (r *SqlConfigRepository) SetServerInitTime(t time.Time) error {
|
|
nt := utils.NullTime{Time: t, Valid: true}
|
|
configEntry := models.ConfigEntry{Key: serverInitDateKey, Value: nt}
|
|
return r.datastore.Save(configEntry)
|
|
}
|
|
|
|
// SetFederationEnabled will enable federation if set to true.
|
|
func (r *SqlConfigRepository) SetFederationEnabled(enabled bool) error {
|
|
return r.datastore.SetBool(federationEnabledKey, enabled)
|
|
}
|
|
|
|
// GetFederationEnabled will return if federation is enabled.
|
|
func (r *SqlConfigRepository) GetFederationEnabled() bool {
|
|
enabled, err := r.datastore.GetBool(federationEnabledKey)
|
|
if err == nil {
|
|
return enabled
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// SetFederationUsername will set the username used in federated activities.
|
|
func (r *SqlConfigRepository) SetFederationUsername(username string) error {
|
|
return r.datastore.SetString(federationUsernameKey, username)
|
|
}
|
|
|
|
// GetFederationUsername will return the username used in federated activities.
|
|
func (r *SqlConfigRepository) GetFederationUsername() string {
|
|
username, err := r.datastore.GetString(federationUsernameKey)
|
|
if username == "" || err != nil {
|
|
return config.GetDefaults().FederationUsername
|
|
}
|
|
|
|
return username
|
|
}
|
|
|
|
// SetFederationGoLiveMessage will set the message sent when going live.
|
|
func (r *SqlConfigRepository) SetFederationGoLiveMessage(message string) error {
|
|
return r.datastore.SetString(federationGoLiveMessageKey, message)
|
|
}
|
|
|
|
// GetFederationGoLiveMessage will return the message sent when going live.
|
|
func (r *SqlConfigRepository) GetFederationGoLiveMessage() string {
|
|
// Empty message means it's disabled.
|
|
message, err := r.datastore.GetString(federationGoLiveMessageKey)
|
|
if err != nil {
|
|
log.Traceln("unable to fetch go live message.", err)
|
|
}
|
|
|
|
return message
|
|
}
|
|
|
|
// SetFederationIsPrivate will set if federation activity is private.
|
|
func (r *SqlConfigRepository) SetFederationIsPrivate(isPrivate bool) error {
|
|
return r.datastore.SetBool(federationPrivateKey, isPrivate)
|
|
}
|
|
|
|
// GetFederationIsPrivate will return if federation is private.
|
|
func (r *SqlConfigRepository) GetFederationIsPrivate() bool {
|
|
isPrivate, err := r.datastore.GetBool(federationPrivateKey)
|
|
if err == nil {
|
|
return isPrivate
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// SetFederationShowEngagement will set if fediverse engagement shows in chat.
|
|
func (r *SqlConfigRepository) SetFederationShowEngagement(showEngagement bool) error {
|
|
return r.datastore.SetBool(federationShowEngagementKey, showEngagement)
|
|
}
|
|
|
|
// GetFederationShowEngagement will return if fediverse engagement shows in chat.
|
|
func (r *SqlConfigRepository) GetFederationShowEngagement() bool {
|
|
showEngagement, err := r.datastore.GetBool(federationShowEngagementKey)
|
|
if err == nil {
|
|
return showEngagement
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// SetBlockedFederatedDomains will set the blocked federated domains.
|
|
func (r *SqlConfigRepository) SetBlockedFederatedDomains(domains []string) error {
|
|
return r.datastore.SetString(federationBlockedDomainsKey, strings.Join(domains, ","))
|
|
}
|
|
|
|
// GetBlockedFederatedDomains will return a list of blocked federated domains.
|
|
func (r *SqlConfigRepository) GetBlockedFederatedDomains() []string {
|
|
domains, err := r.datastore.GetString(federationBlockedDomainsKey)
|
|
if err != nil {
|
|
return []string{}
|
|
}
|
|
|
|
if domains == "" {
|
|
return []string{}
|
|
}
|
|
|
|
return strings.Split(domains, ",")
|
|
}
|
|
|
|
// SetChatJoinMessagesEnabled will set if chat join messages are enabled.
|
|
func (r *SqlConfigRepository) SetChatJoinMessagesEnabled(enabled bool) error {
|
|
return r.datastore.SetBool(chatJoinMessagesEnabledKey, enabled)
|
|
}
|
|
|
|
// GetChatJoinPartMessagesEnabled will return if chat join messages are enabled.
|
|
func (r *SqlConfigRepository) GetChatJoinPartMessagesEnabled() bool {
|
|
enabled, err := r.datastore.GetBool(chatJoinMessagesEnabledKey)
|
|
if err != nil {
|
|
return true
|
|
}
|
|
|
|
return enabled
|
|
}
|
|
|
|
// SetNotificationsEnabled will save the enabled state of notifications.
|
|
func (r *SqlConfigRepository) SetNotificationsEnabled(enabled bool) error {
|
|
return r.datastore.SetBool(notificationsEnabledKey, enabled)
|
|
}
|
|
|
|
// GetNotificationsEnabled will return the enabled state of notifications.
|
|
func (r *SqlConfigRepository) GetNotificationsEnabled() bool {
|
|
enabled, _ := r.datastore.GetBool(notificationsEnabledKey)
|
|
return enabled
|
|
}
|
|
|
|
// GetDiscordConfig will return the Discord configuration.
|
|
func (r *SqlConfigRepository) GetDiscordConfig() models.DiscordConfiguration {
|
|
configEntry, err := r.datastore.Get(discordConfigurationKey)
|
|
if err != nil {
|
|
return models.DiscordConfiguration{Enabled: false}
|
|
}
|
|
|
|
var config models.DiscordConfiguration
|
|
if err := configEntry.GetObject(&config); err != nil {
|
|
return models.DiscordConfiguration{Enabled: false}
|
|
}
|
|
|
|
return config
|
|
}
|
|
|
|
// SetDiscordConfig will set the Discord configuration.
|
|
func (r *SqlConfigRepository) SetDiscordConfig(config models.DiscordConfiguration) error {
|
|
configEntry := models.ConfigEntry{Key: discordConfigurationKey, Value: config}
|
|
return r.datastore.Save(configEntry)
|
|
}
|
|
|
|
// GetBrowserPushConfig will return the browser push configuration.
|
|
func (r *SqlConfigRepository) GetBrowserPushConfig() models.BrowserNotificationConfiguration {
|
|
configEntry, err := r.datastore.Get(browserPushConfigurationKey)
|
|
if err != nil {
|
|
return models.BrowserNotificationConfiguration{Enabled: false}
|
|
}
|
|
|
|
var config models.BrowserNotificationConfiguration
|
|
if err := configEntry.GetObject(&config); err != nil {
|
|
return models.BrowserNotificationConfiguration{Enabled: false}
|
|
}
|
|
|
|
return config
|
|
}
|
|
|
|
// SetBrowserPushConfig will set the browser push configuration.
|
|
func (r *SqlConfigRepository) SetBrowserPushConfig(config models.BrowserNotificationConfiguration) error {
|
|
configEntry := models.ConfigEntry{Key: browserPushConfigurationKey, Value: config}
|
|
return r.datastore.Save(configEntry)
|
|
}
|
|
|
|
// SetBrowserPushPublicKey will set the public key for browser pushes.
|
|
func (r *SqlConfigRepository) SetBrowserPushPublicKey(key string) error {
|
|
return r.datastore.SetString(browserPushPublicKeyKey, key)
|
|
}
|
|
|
|
// GetBrowserPushPublicKey will return the public key for browser pushes.
|
|
func (r *SqlConfigRepository) GetBrowserPushPublicKey() (string, error) {
|
|
return r.datastore.GetString(browserPushPublicKeyKey)
|
|
}
|
|
|
|
// SetBrowserPushPrivateKey will set the private key for browser pushes.
|
|
func (r *SqlConfigRepository) SetBrowserPushPrivateKey(key string) error {
|
|
return r.datastore.SetString(browserPushPrivateKeyKey, key)
|
|
}
|
|
|
|
// GetBrowserPushPrivateKey will return the private key for browser pushes.
|
|
func (r *SqlConfigRepository) GetBrowserPushPrivateKey() (string, error) {
|
|
return r.datastore.GetString(browserPushPrivateKeyKey)
|
|
}
|
|
|
|
// SetHasPerformedInitialNotificationsConfig sets when performed initial setup.
|
|
func (r *SqlConfigRepository) SetHasPerformedInitialNotificationsConfig(hasConfigured bool) error {
|
|
return r.datastore.SetBool(hasConfiguredInitialNotificationsKey, true)
|
|
}
|
|
|
|
// GetHasPerformedInitialNotificationsConfig gets when performed initial setup.
|
|
func (r *SqlConfigRepository) GetHasPerformedInitialNotificationsConfig() bool {
|
|
configured, _ := r.datastore.GetBool(hasConfiguredInitialNotificationsKey)
|
|
return configured
|
|
}
|
|
|
|
// GetHideViewerCount will return if the viewer count shold be hidden.
|
|
func (r *SqlConfigRepository) GetHideViewerCount() bool {
|
|
hide, _ := r.datastore.GetBool(hideViewerCountKey)
|
|
return hide
|
|
}
|
|
|
|
// SetHideViewerCount will set if the viewer count should be hidden.
|
|
func (r *SqlConfigRepository) SetHideViewerCount(hide bool) error {
|
|
return r.datastore.SetBool(hideViewerCountKey, hide)
|
|
}
|
|
|
|
// GetCustomOfflineMessage will return the custom offline message.
|
|
func (r *SqlConfigRepository) GetCustomOfflineMessage() string {
|
|
message, _ := r.datastore.GetString(customOfflineMessageKey)
|
|
return message
|
|
}
|
|
|
|
// SetCustomOfflineMessage will set the custom offline message.
|
|
func (r *SqlConfigRepository) SetCustomOfflineMessage(message string) error {
|
|
return r.datastore.SetString(customOfflineMessageKey, message)
|
|
}
|
|
|
|
// SetCustomColorVariableValues sets CSS variable names and values.
|
|
func (r *SqlConfigRepository) SetCustomColorVariableValues(variables map[string]string) error {
|
|
return r.datastore.SetStringMap(customColorVariableValuesKey, variables)
|
|
}
|
|
|
|
// GetCustomColorVariableValues gets CSS variable names and values.
|
|
func (r *SqlConfigRepository) GetCustomColorVariableValues() map[string]string {
|
|
values, _ := r.datastore.GetStringMap(customColorVariableValuesKey)
|
|
return values
|
|
}
|
|
|
|
// GetStreamKeys will return valid stream keys.
|
|
func (r *SqlConfigRepository) GetStreamKeys() []models.StreamKey {
|
|
configEntry, err := r.datastore.Get(streamKeysKey)
|
|
if err != nil {
|
|
return []models.StreamKey{}
|
|
}
|
|
|
|
var streamKeys []models.StreamKey
|
|
if err := configEntry.GetObject(&streamKeys); err != nil {
|
|
return []models.StreamKey{}
|
|
}
|
|
|
|
return streamKeys
|
|
}
|
|
|
|
// SetStreamKeys will set valid stream keys.
|
|
func (r *SqlConfigRepository) SetStreamKeys(actions []models.StreamKey) error {
|
|
configEntry := models.ConfigEntry{Key: streamKeysKey, Value: actions}
|
|
return r.datastore.Save(configEntry)
|
|
}
|
|
|
|
// SetDisableSearchIndexing will set if the web server should be indexable.
|
|
func (r *SqlConfigRepository) SetDisableSearchIndexing(disableSearchIndexing bool) error {
|
|
return r.datastore.SetBool(disableSearchIndexingKey, disableSearchIndexing)
|
|
}
|
|
|
|
// GetDisableSearchIndexing will return if the web server should be indexable.
|
|
func (r *SqlConfigRepository) GetDisableSearchIndexing() bool {
|
|
disableSearchIndexing, err := r.datastore.GetBool(disableSearchIndexingKey)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return disableSearchIndexing
|
|
}
|
|
|
|
// GetVideoServingEndpoint returns the custom video endpont.
|
|
func (r *SqlConfigRepository) GetVideoServingEndpoint() string {
|
|
message, _ := r.datastore.GetString(videoServingEndpointKey)
|
|
return message
|
|
}
|
|
|
|
// SetVideoServingEndpoint sets the custom video endpoint.
|
|
func (r *SqlConfigRepository) SetVideoServingEndpoint(message string) error {
|
|
return r.datastore.SetString(videoServingEndpointKey, message)
|
|
}
|