Files
techircd/config.go

408 lines
12 KiB
Go

package main
import (
"encoding/json"
"fmt"
"os"
"time"
)
type Config struct {
Server struct {
Name string `json:"name"`
Network string `json:"network"`
Description string `json:"description"`
Version string `json:"version"`
AdminInfo string `json:"admin_info"`
Listen struct {
Host string `json:"host"`
Port int `json:"port"`
SSLPort int `json:"ssl_port"`
EnableSSL bool `json:"enable_ssl"`
} `json:"listen"`
SSL struct {
CertFile string `json:"cert_file"`
KeyFile string `json:"key_file"`
RequireSSL bool `json:"require_ssl"`
} `json:"ssl"`
} `json:"server"`
Limits struct {
MaxClients int `json:"max_clients"`
MaxChannels int `json:"max_channels"`
MaxChannelUsers int `json:"max_channel_users"`
MaxNickLength int `json:"max_nick_length"`
MaxChannelLength int `json:"max_channel_length"`
MaxTopicLength int `json:"max_topic_length"`
MaxKickLength int `json:"max_kick_length"`
MaxAwayLength int `json:"max_away_length"`
PingTimeout int `json:"ping_timeout"`
RegistrationTimeout int `json:"registration_timeout"`
FloodLines int `json:"flood_lines"`
FloodSeconds int `json:"flood_seconds"`
} `json:"limits"`
Features struct {
EnableOper bool `json:"enable_oper"`
EnableServices bool `json:"enable_services"`
EnableModes bool `json:"enable_modes"`
EnableCTCP bool `json:"enable_ctcp"`
EnableDCC bool `json:"enable_dcc"`
CaseMapping string `json:"case_mapping"`
} `json:"features"`
NickChangeNotification struct {
ShowToEveryone bool `json:"to_everyone"`
ShowToOpers bool `json:"to_opers"`
ShowToSelf bool `json:"to_self"`
} `json:"nick_change_notification"`
Privacy struct {
HideHostsFromUsers bool `json:"hide_hosts_from_users"`
OperBypassHostHide bool `json:"oper_bypass_host_hide"`
MaskedHostSuffix string `json:"masked_host_suffix"`
} `json:"privacy"`
WhoisFeatures struct {
// Basic information visibility
ShowUserModes struct {
ToEveryone bool `json:"to_everyone"`
ToOpers bool `json:"to_opers"`
ToSelf bool `json:"to_self"`
} `json:"show_user_modes"`
ShowSSLStatus struct {
ToEveryone bool `json:"to_everyone"`
ToOpers bool `json:"to_opers"`
ToSelf bool `json:"to_self"`
} `json:"show_ssl_status"`
ShowIdleTime struct {
ToEveryone bool `json:"to_everyone"`
ToOpers bool `json:"to_opers"`
ToSelf bool `json:"to_self"`
} `json:"show_idle_time"`
ShowSignonTime struct {
ToEveryone bool `json:"to_everyone"`
ToOpers bool `json:"to_opers"`
ToSelf bool `json:"to_self"`
} `json:"show_signon_time"`
ShowRealHost struct {
ToEveryone bool `json:"to_everyone"`
ToOpers bool `json:"to_opers"`
ToSelf bool `json:"to_self"`
} `json:"show_real_host"`
ShowChannels struct {
ToEveryone bool `json:"to_everyone"`
ToOpers bool `json:"to_opers"`
ToSelf bool `json:"to_self"`
HideSecret bool `json:"hide_secret_channels"`
HidePrivate bool `json:"hide_private_channels"`
ShowMembership bool `json:"show_membership_levels"`
} `json:"show_channels"`
ShowOperClass struct {
ToEveryone bool `json:"to_everyone"`
ToOpers bool `json:"to_opers"`
ToSelf bool `json:"to_self"`
} `json:"show_oper_class"`
ShowClientInfo struct {
ToEveryone bool `json:"to_everyone"`
ToOpers bool `json:"to_opers"`
ToSelf bool `json:"to_self"`
} `json:"show_client_info"`
ShowAccountName struct {
ToEveryone bool `json:"to_everyone"`
ToOpers bool `json:"to_opers"`
ToSelf bool `json:"to_self"`
} `json:"show_account_name"`
// Advanced/unique features
ShowActivityStats bool `json:"show_activity_stats"`
ShowGitHubIntegration bool `json:"show_github_integration"`
ShowGeolocation bool `json:"show_geolocation"`
ShowPerformanceStats bool `json:"show_performance_stats"`
ShowDeviceInfo bool `json:"show_device_info"`
ShowSocialGraph bool `json:"show_social_graph"`
ShowSecurityScore bool `json:"show_security_score"`
// Custom fields
CustomFields []struct {
Name string `json:"name"`
ToEveryone bool `json:"to_everyone"`
ToOpers bool `json:"to_opers"`
ToSelf bool `json:"to_self"`
Format string `json:"format"`
Description string `json:"description"`
} `json:"custom_fields"`
} `json:"whois_features"`
Channels struct {
DefaultModes string `json:"default_modes"`
AutoJoin []string `json:"auto_join"`
AdminChannels []string `json:"admin_channels"`
FounderMode string `json:"founder_mode"` // Mode given to first user joining a channel: "o", "a", "q"
AllowedModes struct {
Voice bool `json:"voice"` // +v
Halfop bool `json:"halfop"` // +h
Operator bool `json:"operator"` // +o
Admin bool `json:"admin"` // +a
Owner bool `json:"owner"` // +q
} `json:"allowed_modes"`
Modes struct {
BanListSize int `json:"ban_list_size"`
ExceptListSize int `json:"except_list_size"`
InviteListSize int `json:"invite_list_size"`
} `json:"modes"`
} `json:"channels"`
Opers []struct {
Name string `json:"name"`
Password string `json:"password"`
Host string `json:"host"`
Class string `json:"class"`
Flags []string `json:"flags"`
} `json:"opers"`
OperConfig struct {
ConfigFile string `json:"config_file"`
Enable bool `json:"enable"`
} `json:"oper_config"`
MOTD []string `json:"motd"`
Linking struct {
Enable bool `json:"enable"`
ServerPort int `json:"server_port"`
Password string `json:"password"`
Hub bool `json:"hub"`
AutoConnect bool `json:"auto_connect"`
Links []struct {
Name string `json:"name"`
Host string `json:"host"`
Port int `json:"port"`
Password string `json:"password"`
AutoConnect bool `json:"auto_connect"`
Hub bool `json:"hub"`
Description string `json:"description"`
} `json:"links"`
} `json:"linking"`
Logging struct {
Level string `json:"level"`
File string `json:"file"`
MaxSize int `json:"max_size"`
MaxBackups int `json:"max_backups"`
MaxAge int `json:"max_age"`
} `json:"logging"`
}
func LoadConfig(filename string) (*Config, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("failed to read config file: %v", err)
}
var config Config
if err := json.Unmarshal(data, &config); err != nil {
return nil, fmt.Errorf("failed to parse config file: %v", err)
}
return &config, nil
}
func (c *Config) PingTimeoutDuration() time.Duration {
return time.Duration(c.Limits.PingTimeout) * time.Second
}
func (c *Config) RegistrationTimeoutDuration() time.Duration {
return time.Duration(c.Limits.RegistrationTimeout) * time.Second
}
func DefaultConfig() *Config {
return &Config{
Server: struct {
Name string `json:"name"`
Network string `json:"network"`
Description string `json:"description"`
Version string `json:"version"`
AdminInfo string `json:"admin_info"`
Listen struct {
Host string `json:"host"`
Port int `json:"port"`
SSLPort int `json:"ssl_port"`
EnableSSL bool `json:"enable_ssl"`
} `json:"listen"`
SSL struct {
CertFile string `json:"cert_file"`
KeyFile string `json:"key_file"`
RequireSSL bool `json:"require_ssl"`
} `json:"ssl"`
}{
Name: "TechIRCd",
Network: "TechNet",
Description: "A modern IRC server written in Go",
Version: "1.0.0",
AdminInfo: "admin@example.com",
Listen: struct {
Host string `json:"host"`
Port int `json:"port"`
SSLPort int `json:"ssl_port"`
EnableSSL bool `json:"enable_ssl"`
}{
Host: "localhost",
Port: 6667,
SSLPort: 6697,
EnableSSL: false,
},
SSL: struct {
CertFile string `json:"cert_file"`
KeyFile string `json:"key_file"`
RequireSSL bool `json:"require_ssl"`
}{
CertFile: "server.crt",
KeyFile: "server.key",
RequireSSL: false,
},
},
Limits: struct {
MaxClients int `json:"max_clients"`
MaxChannels int `json:"max_channels"`
MaxChannelUsers int `json:"max_channel_users"`
MaxNickLength int `json:"max_nick_length"`
MaxChannelLength int `json:"max_channel_length"`
MaxTopicLength int `json:"max_topic_length"`
MaxKickLength int `json:"max_kick_length"`
MaxAwayLength int `json:"max_away_length"`
PingTimeout int `json:"ping_timeout"`
RegistrationTimeout int `json:"registration_timeout"`
FloodLines int `json:"flood_lines"`
FloodSeconds int `json:"flood_seconds"`
}{
MaxClients: 1000,
MaxChannels: 100,
MaxChannelUsers: 500,
MaxNickLength: 30,
MaxChannelLength: 50,
MaxTopicLength: 307,
MaxKickLength: 307,
MaxAwayLength: 307,
PingTimeout: 300,
RegistrationTimeout: 60,
FloodLines: 20,
FloodSeconds: 10,
},
Features: struct {
EnableOper bool `json:"enable_oper"`
EnableServices bool `json:"enable_services"`
EnableModes bool `json:"enable_modes"`
EnableCTCP bool `json:"enable_ctcp"`
EnableDCC bool `json:"enable_dcc"`
CaseMapping string `json:"case_mapping"`
}{
EnableOper: true,
EnableServices: false,
EnableModes: true,
EnableCTCP: true,
EnableDCC: false,
CaseMapping: "rfc1459",
},
Channels: struct {
DefaultModes string `json:"default_modes"`
AutoJoin []string `json:"auto_join"`
AdminChannels []string `json:"admin_channels"`
FounderMode string `json:"founder_mode"` // Mode given to first user joining a channel: "o", "a", "q"
AllowedModes struct {
Voice bool `json:"voice"` // +v
Halfop bool `json:"halfop"` // +h
Operator bool `json:"operator"` // +o
Admin bool `json:"admin"` // +a
Owner bool `json:"owner"` // +q
} `json:"allowed_modes"`
Modes struct {
BanListSize int `json:"ban_list_size"`
ExceptListSize int `json:"except_list_size"`
InviteListSize int `json:"invite_list_size"`
} `json:"modes"`
}{
DefaultModes: "+nt",
AutoJoin: []string{"#general"},
AdminChannels: []string{"#admin"},
FounderMode: "o", // Default to operator mode for channel founders
AllowedModes: struct {
Voice bool `json:"voice"`
Halfop bool `json:"halfop"`
Operator bool `json:"operator"`
Admin bool `json:"admin"`
Owner bool `json:"owner"`
}{
Voice: true,
Halfop: true,
Operator: true,
Admin: true,
Owner: true,
},
Modes: struct {
BanListSize int `json:"ban_list_size"`
ExceptListSize int `json:"except_list_size"`
InviteListSize int `json:"invite_list_size"`
}{
BanListSize: 100,
ExceptListSize: 100,
InviteListSize: 100,
},
},
Opers: []struct {
Name string `json:"name"`
Password string `json:"password"`
Host string `json:"host"`
Class string `json:"class"`
Flags []string `json:"flags"`
}{
{
Name: "admin",
Password: "changeme",
Host: "*@localhost",
Class: "admin",
Flags: []string{"global_kill", "remote", "connect", "squit"},
},
},
MOTD: []string{
"Welcome to TechIRCd!",
"A modern IRC server written in Go",
"Enjoy your stay on TechNet!",
},
Logging: struct {
Level string `json:"level"`
File string `json:"file"`
MaxSize int `json:"max_size"`
MaxBackups int `json:"max_backups"`
MaxAge int `json:"max_age"`
}{
Level: "info",
File: "techircd.log",
MaxSize: 100,
MaxBackups: 3,
MaxAge: 28,
},
}
}
func SaveConfig(config *Config, filename string) error {
data, err := json.MarshalIndent(config, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal config: %v", err)
}
if err := os.WriteFile(filename, data, 0644); err != nil {
return fmt.Errorf("failed to write config file: %v", err)
}
return nil
}