package args import ( "flag" "os" "strings" ) type Arguments struct { DatabasePath string TemplatePath string StaticPath string Migrate bool Scheduler bool Port int Server bool // Dns runs the authoritative DNS server for the LAN. DnsZone is the suffix // it owns (e.g. penguins.lan); queries outside it are forwarded to // DnsResolvers (empty = no forwarding, since the LAN has no outside // internet). ServerIP (env SERVER_IP) answers the zone apex so the website // itself resolves; empty leaves the apex unanswered. Dns bool DnsPort int DnsResolvers []string DnsZone string ServerIP string // DevMAC (env DEV_MAC) forces every client's MAC, for testing auth from // loopback where the browser never appears in the ARP table. DevMAC string // Minecraft RCON, for the server status panel. Empty address disables it. RconAddress string RconPassword string // LanSubnet (env LAN_SUBNET, e.g. 192.168.8.0/24) is swept to populate the // ARP table for idle devices. Empty disables the sweep. LanSubnet string } func GetArgs() (*Arguments, error) { databasePath := flag.String("database-path", "./db/penguins.db", "Path to the SQLite database") templatePath := flag.String("template-path", "./templates", "Path to the template directory") staticPath := flag.String("static-path", "./static", "Path to the static directory") migrate := flag.Bool("migrate", false, "Run the migrations on startup") scheduler := flag.Bool("scheduler", false, "Run the background scheduler (ARP refresh, session cleanup)") port := flag.Int("port", 8080, "Port to listen on") server := flag.Bool("server", false, "Run the HTTP server") dns := flag.Bool("dns", false, "Run the authoritative DNS server") dnsPort := flag.Int("dns-port", 8053, "Port for the DNS server to listen on") dnsZone := flag.String("dns-zone", "penguins.lan", "DNS zone this server is authoritative for") dnsResolvers := flag.String("dns-resolvers", "", "Comma-separated upstream resolvers for non-zone queries (empty disables forwarding)") flag.Parse() resolvers := []string{} for _, r := range strings.Split(*dnsResolvers, ",") { if r = strings.TrimSpace(r); r != "" { resolvers = append(resolvers, r) } } return &Arguments{ DatabasePath: *databasePath, TemplatePath: *templatePath, StaticPath: *staticPath, Migrate: *migrate, Scheduler: *scheduler, Port: *port, Server: *server, Dns: *dns, DnsPort: *dnsPort, DnsResolvers: resolvers, DnsZone: *dnsZone, ServerIP: os.Getenv("SERVER_IP"), DevMAC: os.Getenv("DEV_MAC"), RconAddress: os.Getenv("RCON_ADDRESS"), RconPassword: os.Getenv("RCON_PASSWORD"), LanSubnet: os.Getenv("LAN_SUBNET"), }, nil }