package main import ( "bufio" "flag" "fmt" "log" "maps" "os" "slices" "strconv" "strings" "time" "go.rctt.net/solec/core" "go.rctt.net/solec/server" "go.rctt.net/solec/storage" _ "github.com/mattn/go-sqlite3" ) var ( cmds = map[string]func(args []string){ "broadcast": sendBroadcast, "read": readHistory, "user_set": setUser, "user_del": delUser, "perm_set": setPerm, "exit": exit, } serv *server.Server ) func main() { fmt.Println("SOLEC SERVER") fmt.Println("Commands:", slices.Sorted(maps.Keys(cmds))) addr := flag.String("a", "localhost:9999", "listening address:port") name := flag.String("n", "localhost", "server name") enableTls := flag.Bool("tls", false, "Enable TLS") certPath := flag.String("tls-cert", "", "TLS certificate PEM file path") keyPath := flag.String("tls-key", "", "TLS key PEM file path") test := flag.Bool("test", false, "Create test database entries") dbPath := flag.String("db", "solec.db", "SQLite database path") flag.Parse() db, err := storage.InitDb(*dbPath) if err != nil { panic(err) } cfg := server.Config{ ListenAddr: *addr, Name: *name, } if *enableTls { cfg.Tls = true cfg.CertPem, cfg.KeyPem = loadKeys(*certPath, *keyPath) } serv = server.NewServer(cfg, db) if *test { seedDatabase() } go func() { if err := serv.Start(); err != nil { panic(err) } }() log.Println("listening on", *addr) readCmds() } func loadKeys(certPath, keyPath string) ([]byte, []byte) { cert, err := os.ReadFile(certPath) if err != nil { panic(err) } key, err := os.ReadFile(keyPath) if err != nil { panic(err) } return cert, key } func readCmds() { sc := bufio.NewScanner(os.Stdin) for sc.Scan() { args := strings.Split(sc.Text(), " ") cmd, ok := cmds[args[0]] if !ok { fmt.Println("unknown command") continue } cmd(args[1:]) } if err := sc.Err(); err != nil { log.Println(err) } } func sendBroadcast(args []string) { msg := strings.Join(args[0:], " ") serv.SendBroadcast(msg) } func readHistory(args []string) { if len(args) != 1 { fmt.Println("usage: read ") return } hist, err := serv.Storage.GetHistory(args[0], time.Time{}, 999999, 0) if err != nil { printErr(err) return } fmt.Println(hist) } func setUser(args []string) { if len(args) != 2 { fmt.Println("usage: user_set ") return } pass, err := core.HashPass(args[1]) if err != nil { printErr(err) return } user := core.UserData{ Name: args[0], Pass: pass, } if err := serv.Storage.SetUser(user); err != nil { printErr(err) } } func delUser(args []string) { if len(args) != 1 { fmt.Println("usage: user_del ") return } if err := serv.Storage.DelUser(args[0]); err != nil { printErr(err) } } func setPerm(args []string) { if len(args) != 4 { fmt.Println("usage: perm_set ") return } perm := core.PermissionData{ User: args[0], Channel: args[1], } var err error if perm.Read, err = strconv.ParseBool(args[2]); err != nil { printErr(err) return } if perm.Write, err = strconv.ParseBool(args[3]); err != nil { printErr(err) return } if err := serv.Storage.SetPermission(perm); err != nil { printErr(err) } } func seedDatabase() { log.Println("creating test users") log.Println("user1, user2, user3") setUser([]string{"user1@localhost", "test"}) setUser([]string{"user2@localhost", "test"}) setUser([]string{"user3@localhost", "test"}) log.Println("setting #test@localhost channel permissions") log.Println("user1, user2 -> #test") setPerm([]string{"user1@localhost", "#test@localhost", "1", "1"}) setPerm([]string{"user2@localhost", "#test@localhost", "1", "1"}) log.Println("setting user channel permissions") log.Println("user1 -> user1, user2, user3") setPerm([]string{"user1@localhost", "user1@localhost", "1", "1"}) setPerm([]string{"user1@localhost", "user2@localhost", "1", "1"}) setPerm([]string{"user1@localhost", "user3@localhost", "1", "1"}) log.Println("user2 -> user1, user2") setPerm([]string{"user2@localhost", "user1@localhost", "1", "1"}) setPerm([]string{"user2@localhost", "user2@localhost", "1", "1"}) log.Println("user3 -> user1, user3") setPerm([]string{"user3@localhost", "user1@localhost", "1", "1"}) setPerm([]string{"user3@localhost", "user3@localhost", "1", "1"}) } func exit(args []string) { os.Exit(0) } func printErr(err error) { log.Println("error:", err) }