Browse Source

More cleanup and refactoring

main
Sam Hofius 2 years ago
parent
commit
f5ac97e534
  1. 47
      chat.go
  2. 55
      keybase.go
  3. 60
      keybase_test.go

47
chat.go

@ -15,28 +15,47 @@ type ChatAPI struct {
fromStdout chan []byte fromStdout chan []byte
fromListen chan []byte fromListen chan []byte
errors chan error errors chan error
kbLoc string
} }
func NewChatAPI(ctx context.Context, opts *Options) (api *ChatAPI, err error) { func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
if opts.ChannelBufferSize <= 0 {
opts.ChannelBufferSize = 10
}
// set up the channels // set up the channels
api.toStdin = make(chan []byte, opts.ChannelBufferSize) api = &ChatAPI{
api.fromStdout = make(chan []byte, opts.ChannelBufferSize) toStdin: make(chan []byte, opts.ChannelBufferSize),
api.fromListen = make(chan []byte, opts.ChannelBufferSize) fromStdout: make(chan []byte, opts.ChannelBufferSize),
api.errors = make(chan error, opts.ChannelBufferSize) fromListen: make(chan []byte, opts.ChannelBufferSize),
errors: make(chan error, opts.ChannelBufferSize),
}
// get the basics // get the basics
kbCmd := opts.locateKeybase() if opts.KeybaseLocation == "" {
chatApiArgs := opts.buildArgs("chat", "api") opts.KeybaseLocation, err = locateKeybase()
chatApiListenArgs := opts.buildArgs("chat", "api-listen") if err != nil {
return nil, fmt.Errorf("failed to locate keybase: %v", err)
}
}
api.kbLoc = opts.KeybaseLocation
chatApiArgs, err := buildArgs(opts, "chat", "api")
if err != nil {
return nil, fmt.Errorf("failed to build api args: %v", err)
}
chatApiListenArgs, err := buildArgs(opts, "chat", "api-listen")
if err != nil {
return nil, fmt.Errorf("failed to build api-listen args: %v", err)
}
// build the commands // build the commands
chatApi, err := newApiCmd(ctx, kbCmd, chatApiArgs...) chatApi, err := newApiCmd(ctx, api.kbLoc, chatApiArgs...)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to build api command")
} }
chatListen, err := newApiCmd(ctx, kbCmd, chatApiListenArgs...) chatListen, err := newApiCmd(ctx, api.kbLoc, chatApiListenArgs...)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to build api-listen command")
} }
// create the goroutines // create the goroutines
@ -95,10 +114,6 @@ func NewChatAPI(ctx context.Context, opts *Options) (api *ChatAPI, err error) {
return return
} }
func (c *ChatAPI) Listen() chan []byte {
return c.fromListen
}
func (c *ChatAPI) SendRaw(msg []byte) ([]byte, error) { func (c *ChatAPI) SendRaw(msg []byte) ([]byte, error) {
c.Lock() c.Lock()
defer c.Unlock() defer c.Unlock()

55
keybase.go

@ -1,52 +1,55 @@
package keybase package keybase
import ( import (
"log" "fmt"
"os/exec" "os/exec"
) )
// Options holds... run... options... // Options holds... run... options...
type Options struct { type Options struct {
KeybaseLoction string // Optional, but required if keybase is not in your path // Optional, but required if keybase is not in your path
HomeDir string // Only use this if you know what you're doing KeybaseLocation string
EnableTyping bool // Show others a typing notification while the bot is working on a command
BotLiteMode bool // Defaults to true - only disable if you need to.
ChannelBufferSize int // The size of the channel buffers, may vary on rate of message ingestion
}
// NewOptions returns a new instance of *Options with sensible defaults // Only use this if you know what you're doing
func NewOptions() *Options { HomeDir string
return &Options{
BotLiteMode: true, // Show others a typing notification while the bot is working on a command
ChannelBufferSize: 10, EnableTyping bool
}
// Turn off Keybase's 'bot lite' mode. Only disable if you need to.
DisableLiteMode bool
// The size of the channel buffers, may vary on rate of message ingestion
ChannelBufferSize int
} }
// locateKeybase attempts to find the location of the keybase binary in the following order: // locateKeybase attempts to find the location of the keybase binary in the following order:
// 1. What the user has specified as the location [user specified] // 1. What the user has specified as the location [user specified]
// 2. Looks up the binary location using exec.LookPath [default] // 2. Looks up the binary location using exec.LookPath [default]
// 3. Returns "keybase" and hopes its pathed on the users system [fallback] // 3. Returns "keybase" and hopes its pathed on the users system [fallback]
func (opt *Options) locateKeybase() string { func locateKeybase() (string, error) {
if opt.KeybaseLoction != "" {
return opt.KeybaseLoction
}
path, err := exec.LookPath("keybase") path, err := exec.LookPath("keybase")
if err != nil { if err != nil {
log.Println("INFO: Could not detect keybase in path") return "", fmt.Errorf("could not determine path for keybase binary: %v", err)
return "keybase"
} }
return path return path, nil
} }
// buildBaseCommand adds the homedirectory before the args, when required // buildBaseCommand adds the homedirectory before the args, when required
func (opt *Options) buildArgs(args ...string) []string { func buildArgs(opts Options, args ...string) ([]string, error) {
var cmd []string if len(args) == 0 {
if opt.HomeDir != "" { return nil, fmt.Errorf("no arguments")
cmd = append(cmd, "--home", opt.HomeDir) }
// initialize slice so we never return a nil object
cmd := make([]string, 0)
if opts.HomeDir != "" {
cmd = append(cmd, "--home", opts.HomeDir)
} }
if opt.BotLiteMode { if !opts.DisableLiteMode {
cmd = append(cmd, "--enable-bot-lite-mode") cmd = append(cmd, "--enable-bot-lite-mode")
} }
cmd = append(cmd, args...) cmd = append(cmd, args...)
return cmd
return cmd, nil
} }

60
keybase_test.go

@ -2,41 +2,39 @@ package keybase
import ( import (
"reflect" "reflect"
"strings"
"testing" "testing"
) )
func TestNewOptions(t *testing.T) { func TestBuildArgs(t *testing.T) {
want := &Options{ cases := []struct {
KeybaseLoction: "", Opts Options
HomeDir: "", Args []string
EnableTyping: false, Expected []string
BotLiteMode: true, }{
{
Opts: Options{HomeDir: "/home/foo"},
Args: []string{"arg1"},
Expected: []string{"--home", "/home/foo", "--enable-bot-lite-mode", "arg1"},
},
{
Opts: Options{HomeDir: "/home/foo"},
Args: []string{"arg1", "arg2"},
Expected: []string{"--home", "/home/foo", "--enable-bot-lite-mode", "arg1", "arg2"},
},
{
Opts: Options{HomeDir: "/home/foo", DisableLiteMode: true},
Args: []string{"arg1"},
Expected: []string{"--home", "/home/foo", "arg1"},
},
} }
got := NewOptions()
if !reflect.DeepEqual(want, got) {
t.Errorf("NewOptions returned non-equal structs")
}
}
func TestLocateKeybase(t *testing.T) {
opts := NewOptions()
opts.KeybaseLoction = "/usr/bin/keybase"
if opts.locateKeybase() != "/usr/bin/keybase" {
t.Errorf("locateKeybase returned non-specified keybase")
}
opts2 := NewOptions()
if !strings.Contains(opts2.locateKeybase(), "keybase") {
t.Errorf("locateKeybase did not return a keybase path")
}
}
func TestBaseCommand(t *testing.T) { for i, c := range cases {
opts := NewOptions() actual, err := buildArgs(c.Opts, c.Args...)
opts.HomeDir = "/home/foo" if err != nil {
want := []string{"--home", "/home/foo", "--enable-bot-lite-mode", "arg"} t.Errorf("[case %d] returned error: %v", i, err)
got := opts.buildArgs("arg") }
if !reflect.DeepEqual(want, got) { if !reflect.DeepEqual(actual, c.Expected) {
t.Errorf("buildBaseCommand returned invalid command set") t.Errorf("[case %d] expected: %#v, got: %#v", i, c.Expected, actual)
}
} }
} }

Loading…
Cancel
Save