|
|
|
@ -12,12 +12,23 @@ import (
@@ -12,12 +12,23 @@ import (
|
|
|
|
|
type ChatAPI struct { |
|
|
|
|
sync.Mutex |
|
|
|
|
toStdin chan []byte |
|
|
|
|
fromStdout chan []byte |
|
|
|
|
fromStdout chan msg |
|
|
|
|
fromListen chan []byte |
|
|
|
|
errors chan error |
|
|
|
|
kbLoc string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type msg interface{} |
|
|
|
|
|
|
|
|
|
type apiMsg []byte |
|
|
|
|
|
|
|
|
|
type errMsg struct { |
|
|
|
|
Err error |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e errMsg) Error() string { |
|
|
|
|
return e.Err.Error() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) { |
|
|
|
|
if opts.ChannelBufferSize <= 0 { |
|
|
|
|
opts.ChannelBufferSize = 10 |
|
|
|
@ -26,9 +37,8 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
@@ -26,9 +37,8 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
|
|
|
|
|
// set up the channels
|
|
|
|
|
api = &ChatAPI{ |
|
|
|
|
toStdin: make(chan []byte, opts.ChannelBufferSize), |
|
|
|
|
fromStdout: make(chan []byte, opts.ChannelBufferSize), |
|
|
|
|
fromStdout: make(chan msg, opts.ChannelBufferSize), |
|
|
|
|
fromListen: make(chan []byte, opts.ChannelBufferSize), |
|
|
|
|
errors: make(chan error, opts.ChannelBufferSize), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// get the basics
|
|
|
|
@ -75,7 +85,7 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
@@ -75,7 +85,7 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
|
|
|
|
|
case msg := <-api.toStdin: |
|
|
|
|
_, err := chatApi.Stdin().Write(msg) |
|
|
|
|
if err != nil { |
|
|
|
|
api.errors <- err |
|
|
|
|
api.fromStdout <- errMsg{Err: err} |
|
|
|
|
} |
|
|
|
|
case <-ctx.Done(): |
|
|
|
|
return |
|
|
|
@ -97,7 +107,7 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
@@ -97,7 +107,7 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
|
|
|
|
|
cr := ctxreader.NewContextReader(ctx, chatApi.Stderr()) |
|
|
|
|
scanner := bufio.NewScanner(cr) |
|
|
|
|
for scanner.Scan() { |
|
|
|
|
api.errors <- fmt.Errorf("%v", scanner.Text()) |
|
|
|
|
api.fromStdout <- errMsg{Err: fmt.Errorf("%v", scanner.Text())} |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
@ -114,14 +124,27 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
@@ -114,14 +124,27 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (c *ChatAPI) SendRaw(msg []byte) ([]byte, error) { |
|
|
|
|
func (c *ChatAPI) SendRaw(ctx context.Context, msg []byte) ([]byte, error) { |
|
|
|
|
c.Lock() |
|
|
|
|
defer c.Unlock() |
|
|
|
|
|
|
|
|
|
// send message to api
|
|
|
|
|
c.toStdin <- msg |
|
|
|
|
select { |
|
|
|
|
case resp := <-c.fromStdout: |
|
|
|
|
return resp, nil |
|
|
|
|
case err := <-c.errors: |
|
|
|
|
return nil, err |
|
|
|
|
|
|
|
|
|
// wait for response
|
|
|
|
|
for { |
|
|
|
|
select { |
|
|
|
|
case resp := <-c.fromStdout: |
|
|
|
|
switch resp := resp.(type) { |
|
|
|
|
case apiMsg: |
|
|
|
|
return resp, nil |
|
|
|
|
case errMsg: |
|
|
|
|
return nil, resp.Err |
|
|
|
|
} |
|
|
|
|
case <-ctx.Done(): |
|
|
|
|
return nil, ctx.Err() |
|
|
|
|
default: |
|
|
|
|
// still waiting, do nothing
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|