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 }