408 lines
12 KiB
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
|
|
}
|