package main import ( "github.com/Plan9-Archive/libauth" "bufio" "fmt" "github.com/mischief/ndb" "log" "os" "os/user" sc "strconv" "strings" ) // Types of auth we can do ­ add handling for new modes to atoam() type AuthModes int const ( Pass AuthModes = iota Factotum Unknown // Placeholder ) //Configuration is a struct that contains all configuration fields type Configuration struct { AuthMode AuthModes Username string LoadBacklog bool Messages int PromptChar string TimestampChar string password string } // Config is the global configuration of discord-cli var Config Configuration var ConfigPath string = "/lib/disco.ndb" // Convert a string such as "true" into true func atob(s string) bool { s = strings.ToLower(s) if s == "true" { return true } return false } // Convert a string such as "factotum" into factotum func atoam(s string) AuthModes { s = strings.ToLower(s) if s == "pass" { return Pass } if s == "factotum" { return Factotum } return Unknown } //GetConfig retrieves configuration file from $home/lib/disco.ndb, if it doesn't exist it calls CreateConfig() func GetConfig() { //Get User Start: usr, err := user.Current() if err != nil { log.Fatal(err) } // Get File file, err := os.Open(usr.HomeDir + ConfigPath) if err != nil { log.Println("Creating new config file") CreateConfig() goto Start } file.Close() // Decode File ndb, err := ndb.Open(usr.HomeDir + ConfigPath) if err != nil { log.Fatal("error: Could not ") } Config.Username = ndb.Search("username", "").Search("username") Config.AuthMode = atoam(ndb.Search("auth", "").Search("auth")) if Config.AuthMode == Pass { Config.password = ndb.Search("username", "").Search("password") } Config.LoadBacklog = atob(ndb.Search("loadbacklog", "").Search("loadbacklog")) Config.Messages, _ = sc.Atoi(ndb.Search("messages", "").Search("messages")) Config.PromptChar = ndb.Search("promptchar", "").Search("promptchar") Config.TimestampChar = ndb.Search("timestampchar", "").Search("timestampchar") } //CreateConfig creates folder inside $home and makes a new empty configuration file func CreateConfig() { // Get User usr, err := user.Current() if err != nil { log.Fatal(err) } // Set Default values fmt.Print("Input your email: ") scan := bufio.NewScanner(os.Stdin) scan.Scan() raw := fmt.Sprintf("auth=pass\nloadbacklog=true\nmessages=10\npromptchar=→\ntimestampchar=>\n\nusername=%s password=\n", scan.Text()) // Create File os.Mkdir(usr.HomeDir+"/lib", 0775) file, err := os.Create(usr.HomeDir + ConfigPath) if err != nil { log.Fatalln(err) } file.Chmod(0600) // PrintToFile _, err = file.Write([]byte(raw)) if err != nil { log.Fatalln(err) } file.Close() } // CheckState checks the current state for essential missing information, errors will fail the program func CheckState() { //Get User usr, err := user.Current() if err != nil { log.Fatal(err) } if Config.Username == "" { log.Fatalln("Error: No Username Specified, please edit " + usr.HomeDir + ConfigPath) } // Check and handle password loading switch Config.AuthMode { case Factotum: // Acquire password from factotum userPwd, err := libauth.Getuserpasswd("proto=pass service=discord user=%s server=discordapp.com", Config.Username) if err != nil { // Factotum didn't get anything fmt.Fprintln(os.Stderr, "Warning: No success getting key from factotum, consider disabling it in ndb.") fmt.Fprintln(os.Stderr, "Libauth gave: ", err) } else { Config.password = userPwd.Password } case Unknown: log.Fatalln("Error: incorrect, or no, authmode specified via auth= config tuple. Consider: auth=(pass factotum).") default: // Password is already loaded in auth=pass mode } if Config.password == "" { log.Fatalln("Error: No password loaded, cannot auth. Are you missing a factotum key or password= tuple?") } }