2023-02-05 08:53:50 +00:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"html/template"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"git.kirsle.net/apps/barertc/pkg/log"
|
|
|
|
"github.com/BurntSushi/toml"
|
2023-07-30 17:32:08 +00:00
|
|
|
"github.com/google/uuid"
|
2023-02-05 08:53:50 +00:00
|
|
|
)
|
|
|
|
|
2023-02-09 04:01:06 +00:00
|
|
|
// Version of the config format - when new fields are added, it will attempt
|
|
|
|
// to write the settings.toml to disk so new defaults populate.
|
2024-05-17 06:33:19 +00:00
|
|
|
var currentVersion = 13
|
2023-02-09 04:01:06 +00:00
|
|
|
|
2023-02-05 08:53:50 +00:00
|
|
|
// Config for your BareRTC app.
|
|
|
|
type Config struct {
|
2023-02-09 04:01:06 +00:00
|
|
|
Version int // will re-save your settings.toml on migrations
|
|
|
|
|
2023-02-05 08:53:50 +00:00
|
|
|
JWT struct {
|
2023-07-01 01:41:06 +00:00
|
|
|
Enabled bool
|
|
|
|
Strict bool
|
|
|
|
SecretKey string
|
|
|
|
LandingPageURL string
|
2023-02-05 08:53:50 +00:00
|
|
|
}
|
|
|
|
|
2023-02-06 04:26:00 +00:00
|
|
|
Title string
|
2023-02-06 21:27:29 +00:00
|
|
|
Branding string
|
2023-02-06 01:42:09 +00:00
|
|
|
WebsiteURL string
|
2023-02-11 06:46:39 +00:00
|
|
|
|
2023-07-30 17:32:08 +00:00
|
|
|
CORSHosts []string
|
|
|
|
AdminAPIKey string
|
|
|
|
PermitNSFW bool
|
2023-02-06 01:42:09 +00:00
|
|
|
|
2023-02-09 04:01:06 +00:00
|
|
|
UseXForwardedFor bool
|
|
|
|
|
2023-09-30 19:46:45 +00:00
|
|
|
WebSocketReadLimit int64
|
|
|
|
WebSocketSendTimeout int
|
|
|
|
MaxImageWidth int
|
|
|
|
PreviewImageWidth int
|
2023-03-22 04:29:24 +00:00
|
|
|
|
2023-06-14 04:57:31 +00:00
|
|
|
TURN TurnConfig
|
|
|
|
|
2023-02-05 08:53:50 +00:00
|
|
|
PublicChannels []Channel
|
2023-08-13 04:35:41 +00:00
|
|
|
|
|
|
|
WebhookURLs []WebhookURL
|
2023-09-03 19:08:23 +00:00
|
|
|
|
|
|
|
VIP VIP
|
2023-09-30 02:10:34 +00:00
|
|
|
|
|
|
|
MessageFilters []*MessageFilter
|
2024-05-17 06:33:19 +00:00
|
|
|
ModerationRule []*ModerationRule
|
2023-11-11 22:59:49 +00:00
|
|
|
|
2024-03-29 06:20:09 +00:00
|
|
|
DirectMessageHistory DirectMessageHistory
|
|
|
|
|
2023-11-11 22:59:49 +00:00
|
|
|
Logging Logging
|
2023-02-05 08:53:50 +00:00
|
|
|
}
|
|
|
|
|
2023-06-14 04:57:31 +00:00
|
|
|
type TurnConfig struct {
|
|
|
|
URLs []string
|
|
|
|
Username string
|
|
|
|
Credential string
|
|
|
|
}
|
|
|
|
|
2023-09-03 19:08:23 +00:00
|
|
|
type VIP struct {
|
|
|
|
Name string
|
|
|
|
Branding string
|
|
|
|
Icon string
|
|
|
|
MutuallySecret bool
|
|
|
|
}
|
|
|
|
|
2024-03-29 06:20:09 +00:00
|
|
|
type DirectMessageHistory struct {
|
|
|
|
Enabled bool
|
|
|
|
SQLiteDatabase string
|
|
|
|
RetentionDays int
|
|
|
|
DisclaimerMessage string
|
|
|
|
}
|
|
|
|
|
2023-02-05 08:53:50 +00:00
|
|
|
// GetChannels returns a JavaScript safe array of the default PublicChannels.
|
|
|
|
func (c Config) GetChannels() template.JS {
|
|
|
|
data, _ := json.Marshal(c.PublicChannels)
|
|
|
|
return template.JS(data)
|
|
|
|
}
|
|
|
|
|
2023-09-03 19:48:21 +00:00
|
|
|
// GetChannel looks up and returns a channel by ID.
|
|
|
|
func (c Config) GetChannel(id string) (Channel, bool) {
|
|
|
|
for _, ch := range c.PublicChannels {
|
|
|
|
if ch.ID == id {
|
|
|
|
return ch, true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Channel{}, false
|
|
|
|
}
|
|
|
|
|
2023-02-05 08:53:50 +00:00
|
|
|
// Channel config for a default public room.
|
|
|
|
type Channel struct {
|
2024-05-14 01:51:54 +00:00
|
|
|
ID string // Like "lobby"
|
|
|
|
Name string // Like "Main Chat Room"
|
|
|
|
Icon string `toml:",omitempty"` // CSS class names for room icon (optional)
|
|
|
|
VIP bool // For VIP users only
|
|
|
|
PermitPhotos bool // photos are allowed to be shared
|
2023-02-06 01:42:09 +00:00
|
|
|
|
|
|
|
// ChatServer messages to send to the user immediately upon connecting.
|
|
|
|
WelcomeMessages []string
|
2023-02-05 08:53:50 +00:00
|
|
|
}
|
|
|
|
|
2023-08-13 04:35:41 +00:00
|
|
|
// WebhookURL allows tighter integration with your website.
|
|
|
|
type WebhookURL struct {
|
|
|
|
Name string
|
|
|
|
Enabled bool
|
|
|
|
URL string
|
|
|
|
}
|
|
|
|
|
2023-11-11 22:59:49 +00:00
|
|
|
// Logging configs to monitor channels or usernames.
|
|
|
|
type Logging struct {
|
|
|
|
Enabled bool
|
|
|
|
Directory string
|
|
|
|
Channels []string
|
|
|
|
Usernames []string
|
|
|
|
}
|
|
|
|
|
2024-05-17 06:33:19 +00:00
|
|
|
// ModerationRule applies certain rules to moderate specific users.
|
|
|
|
type ModerationRule struct {
|
|
|
|
Username string
|
|
|
|
CameraAlwaysNSFW bool
|
|
|
|
DisableCamera bool
|
|
|
|
}
|
|
|
|
|
2023-02-05 08:53:50 +00:00
|
|
|
// Current loaded configuration.
|
|
|
|
var Current = DefaultConfig()
|
|
|
|
|
|
|
|
// DefaultConfig returns sensible defaults and will write the initial
|
|
|
|
// settings.toml file to disk.
|
|
|
|
func DefaultConfig() Config {
|
|
|
|
var c = Config{
|
2023-07-30 17:32:08 +00:00
|
|
|
Title: "BareRTC",
|
|
|
|
Branding: "BareRTC",
|
|
|
|
WebsiteURL: "https://www.example.com",
|
|
|
|
AdminAPIKey: uuid.New().String(),
|
2023-02-10 07:03:06 +00:00
|
|
|
CORSHosts: []string{
|
|
|
|
"https://www.example.com",
|
|
|
|
},
|
2023-09-30 19:46:45 +00:00
|
|
|
WebSocketReadLimit: 1024 * 1024 * 40, // 40 MB.
|
|
|
|
WebSocketSendTimeout: 10, // seconds
|
|
|
|
MaxImageWidth: 1280,
|
|
|
|
PreviewImageWidth: 360,
|
2023-02-05 08:53:50 +00:00
|
|
|
PublicChannels: []Channel{
|
|
|
|
{
|
|
|
|
ID: "lobby",
|
|
|
|
Name: "Lobby",
|
2023-02-06 01:42:09 +00:00
|
|
|
WelcomeMessages: []string{
|
|
|
|
"Welcome to the chat server!",
|
|
|
|
"Please follow the basic rules:\n\n1. Have fun\n2. Be kind",
|
|
|
|
},
|
2023-02-05 08:53:50 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
ID: "offtopic",
|
|
|
|
Name: "Off Topic",
|
2023-02-06 01:42:09 +00:00
|
|
|
WelcomeMessages: []string{
|
|
|
|
"Welcome to the Off Topic channel!",
|
|
|
|
},
|
2024-05-14 01:51:54 +00:00
|
|
|
PermitPhotos: true,
|
2023-02-05 08:53:50 +00:00
|
|
|
},
|
2023-09-03 19:48:21 +00:00
|
|
|
{
|
2024-05-14 01:51:54 +00:00
|
|
|
ID: "vip",
|
|
|
|
Name: "VIPs Only",
|
|
|
|
VIP: true,
|
|
|
|
PermitPhotos: true,
|
2023-09-03 19:48:21 +00:00
|
|
|
WelcomeMessages: []string{
|
|
|
|
"This channel is only for operators and VIPs.",
|
|
|
|
},
|
|
|
|
},
|
2023-02-05 08:53:50 +00:00
|
|
|
},
|
2023-06-14 04:57:31 +00:00
|
|
|
TURN: TurnConfig{
|
|
|
|
URLs: []string{
|
|
|
|
"stun:stun.l.google.com:19302",
|
|
|
|
},
|
|
|
|
},
|
2023-08-13 04:35:41 +00:00
|
|
|
WebhookURLs: []WebhookURL{
|
|
|
|
{
|
|
|
|
Name: "report",
|
|
|
|
URL: "https://example.com/barertc/report",
|
|
|
|
},
|
2023-10-07 20:22:41 +00:00
|
|
|
{
|
|
|
|
Name: "profile",
|
|
|
|
URL: "https://example.com/barertc/user-profile",
|
|
|
|
},
|
2023-08-13 04:35:41 +00:00
|
|
|
},
|
2023-09-03 19:08:23 +00:00
|
|
|
VIP: VIP{
|
|
|
|
Name: "VIP",
|
|
|
|
Branding: "<em>VIP Members</em>",
|
|
|
|
Icon: "fa fa-circle",
|
|
|
|
},
|
2023-09-30 02:10:34 +00:00
|
|
|
MessageFilters: []*MessageFilter{
|
|
|
|
{
|
|
|
|
PublicChannels: true,
|
|
|
|
PrivateChannels: true,
|
|
|
|
KeywordPhrases: []string{
|
|
|
|
`\bswear words\b`,
|
|
|
|
`\b(swearing|cursing)\b`,
|
|
|
|
`suck my ([^\s]+)`,
|
|
|
|
},
|
|
|
|
CensorMessage: true,
|
|
|
|
ChatServerResponse: "Watch your language.",
|
|
|
|
},
|
|
|
|
},
|
2024-05-17 06:33:19 +00:00
|
|
|
ModerationRule: []*ModerationRule{
|
|
|
|
{
|
|
|
|
Username: "example",
|
|
|
|
},
|
|
|
|
},
|
2024-03-29 06:20:09 +00:00
|
|
|
DirectMessageHistory: DirectMessageHistory{
|
|
|
|
Enabled: false,
|
|
|
|
SQLiteDatabase: "database.sqlite",
|
|
|
|
RetentionDays: 90,
|
|
|
|
DisclaimerMessage: `<i class="fa fa-info-circle mr-1"></i> <strong>Reminder:</strong> please conduct yourself honorably in Direct Messages.`,
|
|
|
|
},
|
2023-11-11 22:59:49 +00:00
|
|
|
Logging: Logging{
|
|
|
|
Directory: "./logs",
|
|
|
|
Channels: []string{"lobby", "offtopic"},
|
|
|
|
Usernames: []string{},
|
|
|
|
},
|
2023-02-05 08:53:50 +00:00
|
|
|
}
|
2023-02-06 01:42:09 +00:00
|
|
|
c.JWT.Strict = true
|
2023-02-05 08:53:50 +00:00
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
// LoadSettings reads a settings.toml from disk if available.
|
|
|
|
func LoadSettings() error {
|
|
|
|
data, err := os.ReadFile("./settings.toml")
|
|
|
|
if err != nil {
|
|
|
|
// Settings file didn't exist, create the default one.
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
WriteSettings()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = toml.Decode(string(data), &Current)
|
2023-08-13 04:35:41 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-02-09 04:01:06 +00:00
|
|
|
|
|
|
|
// Have we added new config fields? Save the settings.toml.
|
2023-03-22 04:29:24 +00:00
|
|
|
if Current.Version != currentVersion {
|
2023-02-09 04:01:06 +00:00
|
|
|
log.Warn("New options are available for your settings.toml file. Your settings will be re-saved now.")
|
|
|
|
Current.Version = currentVersion
|
|
|
|
if err := WriteSettings(); err != nil {
|
|
|
|
log.Error("Couldn't write your settings.toml file: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-05 08:53:50 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteSettings will commit the settings.toml to disk.
|
|
|
|
func WriteSettings() error {
|
|
|
|
log.Error("Note: initial settings.toml was written to disk.")
|
|
|
|
var buf = new(bytes.Buffer)
|
|
|
|
err := toml.NewEncoder(buf).Encode(Current)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return os.WriteFile("./settings.toml", buf.Bytes(), 0644)
|
|
|
|
}
|
2024-05-17 06:33:19 +00:00
|
|
|
|
|
|
|
// GetModerationRule returns a matching ModerationRule for the given user, or nil if no rule is found.
|
|
|
|
func (c Config) GetModerationRule(username string) *ModerationRule {
|
|
|
|
for _, rule := range c.ModerationRule {
|
|
|
|
if rule.Username == username {
|
|
|
|
return rule
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|