diff --git a/adapter/adapter.go b/adapter/adapter.go index dc048d4..bd661be 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -9,6 +9,6 @@ type Adapter interface { Name() string Subscribe(string) []error Fetch(string, []string) error - Do(string, []string) error + Do(string, map[string]string) error DefaultSubscriptionFilter() string } diff --git a/adapter/honk.go b/adapter/honk.go new file mode 100644 index 0000000..d8f9f35 --- /dev/null +++ b/adapter/honk.go @@ -0,0 +1,96 @@ +package adapter + +import ( + "errors" + "fmt" + . "forge.lightcrystal.systems/lightcrystal/underbbs/models" + "net/http" + "net/url" + "os" + "strings" +) + +type HonkAdapter struct { + data *chan SocketData + nickname string + server string + username string + password string + token string +} + +func (self *HonkAdapter) send(data SocketData) { + if self.data != nil { + *self.data <- data + } else { + fmt.Fprintln(os.Stdout, string(data.ToDatagram())) + } +} + +func (self *HonkAdapter) Name() string { + return self.nickname +} + +func (self *HonkAdapter) Init(settings Settings, data *chan SocketData) error { + // separate name and server in handle + parts := strings.Split(*settings.Handle, "@") + self.username = parts[1] + self.server = "https://" + parts[2] + self.password = *settings.Password + self.nickname = settings.Nickname + // store all the settings + // make a request to get the token + r, err := http.PostForm(self.server+"/dologin", url.Values{ + "username": []string{self.username}, + "password": []string{self.password}, + "gettoken": []string{"1"}, + }) + if err != nil { + return err + } + + var buf [32]byte + _, err = r.Body.Read(buf[:]) + if err != nil { + return err + } + + self.token = string(buf[:]) + fmt.Println(self.token) + return nil +} + +func (self *HonkAdapter) Subscribe(string) []error { + return nil +} + +func (self *HonkAdapter) Fetch(etype string, ids []string) error { + return nil +} + +func (self *HonkAdapter) Do(action string, data map[string]string) error { + switch action { + case "post": + res, err := http.PostForm(self.server+"/api", url.Values{ + "action": []string{"honk"}, + "token": []string{self.token}, + "noise": []string{data["content"]}, + }) + if err != nil { + return err + } + var buf [256]byte + _, err = res.Body.Read(buf[:]) + if err != nil { + return err + } + fmt.Println(string(buf[:])) + default: + return errors.New("Do: unknown action") + } + return nil +} + +func (self *HonkAdapter) DefaultSubscriptionFilter() string { + return "" +} diff --git a/adapter/mastodon.go b/adapter/mastodon.go index 99cf317..a7efd1d 100644 --- a/adapter/mastodon.go +++ b/adapter/mastodon.go @@ -104,7 +104,7 @@ func (self *MastoAdapter) Fetch(etype string, ids []string) error { return nil } -func (self *MastoAdapter) Do(action string, data []string) error { +func (self *MastoAdapter) Do(action string, data map[string]string) error { return nil } diff --git a/adapter/misskey.go b/adapter/misskey.go index 2728b25..eba427c 100644 --- a/adapter/misskey.go +++ b/adapter/misskey.go @@ -367,7 +367,7 @@ func (self *MisskeyAdapter) Fetch(etype string, ids []string) error { return nil } -func (self *MisskeyAdapter) Do(action string, data []string) error { +func (self *MisskeyAdapter) Do(action string, data map[string]string) error { return nil } diff --git a/adapter/nostr.go b/adapter/nostr.go index 7f07712..04e805e 100644 --- a/adapter/nostr.go +++ b/adapter/nostr.go @@ -90,7 +90,7 @@ func (self *NostrAdapter) Fetch(etype string, ids []string) error { return nil } -func (self *NostrAdapter) Do(action string, data []string) error { +func (self *NostrAdapter) Do(action string, data map[string]string) error { return nil } diff --git a/cli/cli.go b/cli/cli.go index e864f28..cff7fd3 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -5,11 +5,40 @@ import ( "errors" "io/ioutil" "log" + "os" + "path/filepath" + "runtime" + "strings" "forge.lightcrystal.systems/lightcrystal/underbbs/adapter" "forge.lightcrystal.systems/lightcrystal/underbbs/models" ) +func GetConfigLocation() string { + home := os.Getenv("HOME") + appdata := os.Getenv("APPDATA") + switch runtime.GOOS { + case "windows": + return filepath.Join(appdata, "underbbs") + case "darwin": + return filepath.Join(home, "Library", "Application Support", "underbbs") + case "plan9": + return filepath.Join(home, "lib", "underbbs") + default: + return filepath.Join(home, ".config", "underbbs") + } +} + +func EnsureConfigLocationExists() { + fileInfo, err := os.Stat(GetConfigLocation()) + + if os.IsNotExist(err) { + os.MkdirAll(GetConfigLocation(), os.ModePerm) + } else if !fileInfo.IsDir() { + panic("Config location is not a directory!") + } +} + func Process(args ...string) error { // allocate storage for the settings array var settings []models.Settings @@ -19,17 +48,20 @@ func Process(args ...string) error { return errors.New("CLI requires at least 3 args: ADAPTER ACTION DATA...") } + EnsureConfigLocationExists() + cfgdir := GetConfigLocation() + // get adapter from first arg adapterName := args[0] args = args[1:] // get config from config fle based on adapter - content, err := ioutil.ReadFile("./config.json") + content, err := ioutil.ReadFile(filepath.Join(cfgdir, "config.json")) if err != nil { return err } - err = json.Unmarshal(content, settings) + err = json.Unmarshal(content, &settings) if err != nil { return err } @@ -53,6 +85,8 @@ func Process(args ...string) error { a = &adapter.MastoAdapter{} case "misskey": a = &adapter.MisskeyAdapter{} + case "honk": + a = &adapter.HonkAdapter{} default: break } @@ -63,7 +97,18 @@ func Process(args ...string) error { case "fetch": a.Fetch(args[1], args[2:]) case "do": - a.Do(args[1], args[2:]) + data := map[string]string{} + for _, a := range args[2:] { + if !strings.Contains(a, "=") { + return errors.New("args are in the form KEY=VALUE") + } else { + aa := strings.Split(a, "=") + k := aa[0] + v := strings.Join(aa[1:], "=") + data[k] = v + } + } + a.Do(args[1], data) default: log.Print(args) } diff --git a/models/settings.go b/models/settings.go index 79a7412..e4f6a90 100644 --- a/models/settings.go +++ b/models/settings.go @@ -7,4 +7,6 @@ type Settings struct { Relays []string `json:"relays",omitempty` Server *string `json:"server",omitempty` ApiKey *string `json:"apiKey",omitempty` + Handle *string `json:"handle",omitempty` + Password *string `json:"password",omitempty` } diff --git a/underbbs.go b/underbbs.go index 804f5b1..7917c85 100644 --- a/underbbs.go +++ b/underbbs.go @@ -2,6 +2,7 @@ package main import ( "context" + "fmt" "log" "net" "net/http" @@ -21,23 +22,21 @@ func main() { var err error = nil - switch filepath.Base(args[0]) { + progname := filepath.Base(args[0]) + switch progname { case "underbbs-cli": err = run_cli(args[1:]...) - break default: err = run_srvr() - break } if err != nil { - log.Fatal(err) + fmt.Println(err.Error()) } } func run_cli(args ...string) error { - cli.Process(args...) - return nil + return cli.Process(args...) } func run_srvr() error {