You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.1 KiB
111 lines
3.1 KiB
package keybase |
|
|
|
import ( |
|
"bufio" |
|
"encoding/json" |
|
"os/exec" |
|
"time" |
|
) |
|
|
|
// RunOptions holds a set of options to be passed to Run |
|
type RunOptions struct { |
|
Heartbeat int64 // Send a heartbeat through the channel every X minutes (0 = off) |
|
Local bool // Subscribe to local messages |
|
HideExploding bool // Ignore exploding messages |
|
Dev bool // Subscribe to dev channel messages |
|
Wallet bool // Subscribe to wallet events |
|
FilterChannel Channel // Only subscribe to messages from specified channel |
|
FilterChannels []Channel // Only subscribe to messages from specified channels |
|
} |
|
|
|
// Creates a string of a json-encoded channel to pass to keybase chat api-listen --filter-channel |
|
func createFilterString(channel Channel) string { |
|
if channel.Name == "" { |
|
return "" |
|
} |
|
jsonBytes, _ := json.Marshal(channel) |
|
return string(jsonBytes) |
|
} |
|
|
|
// Creates a string of json-encoded channels to pass to keybase chat api-listen --filter-channels |
|
func createFiltersString(channels []Channel) string { |
|
if len(channels) == 0 { |
|
return "" |
|
} |
|
jsonBytes, _ := json.Marshal(channels) |
|
return string(jsonBytes) |
|
} |
|
|
|
// Run `keybase chat api-listen` to get new messages coming into keybase and send them into the channel |
|
func getNewMessages(k *Keybase, c chan<- ChatAPI, execOptions []string) { |
|
execString := []string{"chat", "api-listen"} |
|
if len(execOptions) > 0 { |
|
execString = append(execString, execOptions...) |
|
} |
|
for { |
|
execCmd := exec.Command(k.Path, execString...) |
|
stdOut, _ := execCmd.StdoutPipe() |
|
execCmd.Start() |
|
scanner := bufio.NewScanner(stdOut) |
|
go func(scanner *bufio.Scanner, c chan<- ChatAPI) { |
|
var jsonData ChatAPI |
|
for scanner.Scan() { |
|
json.Unmarshal([]byte(scanner.Text()), &jsonData) |
|
c <- jsonData |
|
} |
|
}(scanner, c) |
|
execCmd.Wait() |
|
} |
|
} |
|
|
|
// Run runs `keybase chat api-listen`, and passes incoming messages to the message handler func |
|
func (k *Keybase) Run(handler func(ChatAPI), options ...RunOptions) { |
|
var heartbeatFreq int64 |
|
runOptions := make([]string, 0) |
|
if len(options) > 0 { |
|
if options[0].Heartbeat > 0 { |
|
heartbeatFreq = options[0].Heartbeat |
|
} |
|
if options[0].Local { |
|
runOptions = append(runOptions, "--local") |
|
} |
|
if options[0].HideExploding { |
|
runOptions = append(runOptions, "--hide-exploding") |
|
} |
|
if options[0].Dev { |
|
runOptions = append(runOptions, "--dev") |
|
} |
|
if len(options[0].FilterChannels) > 0 { |
|
runOptions = append(runOptions, "--filter-channels") |
|
runOptions = append(runOptions, createFiltersString(options[0].FilterChannels)) |
|
|
|
} |
|
if options[0].FilterChannel.Name != "" { |
|
runOptions = append(runOptions, "--filter-channel") |
|
runOptions = append(runOptions, createFilterString(options[0].FilterChannel)) |
|
} |
|
} |
|
c := make(chan ChatAPI, 50) |
|
defer close(c) |
|
if heartbeatFreq > 0 { |
|
go heartbeat(c, time.Duration(heartbeatFreq)*time.Minute) |
|
} |
|
go getNewMessages(k, c, runOptions) |
|
for { |
|
go handler(<-c) |
|
} |
|
} |
|
|
|
// heartbeat sends a message through the channel with a message type of `heartbeat` |
|
func heartbeat(c chan<- ChatAPI, freq time.Duration) { |
|
m := ChatAPI{ |
|
Type: "heartbeat", |
|
} |
|
count := 0 |
|
for { |
|
time.Sleep(freq) |
|
m.Msg.ID = count |
|
c <- m |
|
count++ |
|
} |
|
}
|
|
|