Add support for incoming messages. This breaks NewChat() in previous versions
This commit is contained in:
55
chatIn.go
55
chatIn.go
@ -1,19 +1,17 @@
|
||||
package keybase
|
||||
|
||||
import ()
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
type chatIn struct {
|
||||
type ChatIn struct {
|
||||
Type string `json:"type"`
|
||||
Source string `json:"source"`
|
||||
Msg chatInMsg `json:"msg"`
|
||||
}
|
||||
type chatInChannel struct {
|
||||
Name string `json:"name"`
|
||||
Public bool `json:"public"`
|
||||
MembersType string `json:"members_type"`
|
||||
TopicType string `json:"topic_type"`
|
||||
TopicName string `json:"topic_name"`
|
||||
}
|
||||
type chatInSender struct {
|
||||
UID string `json:"uid"`
|
||||
Username string `json:"username"`
|
||||
@ -84,7 +82,7 @@ type chatInContent struct {
|
||||
}
|
||||
type chatInMsg struct {
|
||||
ID int `json:"id"`
|
||||
Channel chatInChannel `json:"channel"`
|
||||
Channel Channel `json:"channel"`
|
||||
Sender chatInSender `json:"sender"`
|
||||
SentAt int `json:"sent_at"`
|
||||
SentAtMs int64 `json:"sent_at_ms"`
|
||||
@ -96,3 +94,40 @@ type chatInMsg struct {
|
||||
HasPairwiseMacs bool `json:"has_pairwise_macs"`
|
||||
ChannelMention string `json:"channel_mention"`
|
||||
}
|
||||
|
||||
// Creates a string of json-encoded channels to pass to keybase chat api-listen --filter-channels
|
||||
func createFilterString(channelFilters ...Channel) string {
|
||||
if len(channelFilters) == 0 {
|
||||
return "[]"
|
||||
}
|
||||
|
||||
jsonBytes, _ := json.Marshal(channelFilters)
|
||||
return fmt.Sprintf("%s", string(jsonBytes))
|
||||
}
|
||||
|
||||
// Get new messages coming into keybase and send them into the channel
|
||||
func getNewMessages(k Keybase, c chan<- ChatIn, filterString string) {
|
||||
keybaseListen := exec.Command(k.Path, "chat", "api-listen", "--filter-channels", filterString)
|
||||
keybaseOutput, _ := keybaseListen.StdoutPipe()
|
||||
keybaseListen.Start()
|
||||
scanner := bufio.NewScanner(keybaseOutput)
|
||||
var jsonData ChatIn
|
||||
|
||||
for scanner.Scan() {
|
||||
json.Unmarshal([]byte(scanner.Text()), &jsonData)
|
||||
c <- jsonData
|
||||
}
|
||||
}
|
||||
|
||||
// Runner() runs keybase chat api-listen, and passes incoming messages to the message handler func
|
||||
func (k Keybase) Runner(handler func(ChatIn), channelFilters ...Channel) {
|
||||
c := make(chan ChatIn, 10)
|
||||
defer close(c)
|
||||
go getNewMessages(k, c, createFilterString(channelFilters...))
|
||||
for {
|
||||
chat, ok := <-c
|
||||
if ok {
|
||||
go handler(chat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
43
chatOut.go
43
chatOut.go
@ -7,21 +7,22 @@ import (
|
||||
)
|
||||
|
||||
// ---- Struct for sending to API
|
||||
type chatOut struct { // not exported
|
||||
type chatOut struct {
|
||||
Method string `json:"method"`
|
||||
Params chatOutParams `json:"params"`
|
||||
}
|
||||
type chatOutChannel struct {
|
||||
type Channel struct {
|
||||
Name string `json:"name"`
|
||||
Public bool `json:"public"`
|
||||
MembersType string `json:"members_type"`
|
||||
TopicName string `json:"topic_name"`
|
||||
Public bool `json:"public,omitempty"`
|
||||
MembersType string `json:"members_type,omitempty"`
|
||||
TopicType string `json:"topic_type,omitempty"`
|
||||
TopicName string `json:"topic_name,omitempty"`
|
||||
}
|
||||
type chatOutMessage struct {
|
||||
Body string `json:"body"`
|
||||
}
|
||||
type chatOutOptions struct {
|
||||
Channel chatOutChannel `json:"channel"`
|
||||
Channel Channel `json:"channel"`
|
||||
MessageID int `json:"message_id"`
|
||||
Message chatOutMessage `json:"message"`
|
||||
}
|
||||
@ -41,22 +42,15 @@ type chatOutResultRatelimits struct {
|
||||
Reset int `json:"reset,omitempty"`
|
||||
Gas int `json:"gas,omitempty"`
|
||||
}
|
||||
type chatOutResultChannel struct {
|
||||
Name string `json:"name"`
|
||||
Public bool `json:"public"`
|
||||
MembersType string `json:"members_type"`
|
||||
TopicType string `json:"topic_type,omitempty"`
|
||||
TopicName string `json:"topic_name,omitempty"`
|
||||
}
|
||||
type conversation struct {
|
||||
ID string `json:"id"`
|
||||
Channel chatOutResultChannel `json:"channel"`
|
||||
Channel Channel `json:"channel"`
|
||||
Unread bool `json:"unread"`
|
||||
ActiveAt int `json:"active_at"`
|
||||
ActiveAtMs int64 `json:"active_at_ms"`
|
||||
MemberStatus string `json:"member_status"`
|
||||
}
|
||||
type ChatOut struct { // exported
|
||||
type ChatOut struct {
|
||||
Message string `json:"message,omitempty"`
|
||||
ID int `json:"id,omitempty"`
|
||||
Ratelimits []chatOutResultRatelimits `json:"ratelimits,omitempty"`
|
||||
@ -86,10 +80,7 @@ func chatAPIOut(keybasePath string, c chatOut) (chatOutResult, error) {
|
||||
func (c Chat) Send(message ...string) (ChatOut, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "send"
|
||||
m.Params.Options.Channel.Name = c.Name
|
||||
m.Params.Options.Channel.Public = c.Public
|
||||
m.Params.Options.Channel.MembersType = c.MembersType
|
||||
m.Params.Options.Channel.TopicName = c.TopicName
|
||||
m.Params.Options.Channel = c.Channel
|
||||
m.Params.Options.Message.Body = strings.Join(message, " ")
|
||||
|
||||
r, err := chatAPIOut(c.keybase.Path, m)
|
||||
@ -103,10 +94,7 @@ func (c Chat) Send(message ...string) (ChatOut, error) {
|
||||
func (c Chat) Edit(messageId int, message ...string) (ChatOut, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "edit"
|
||||
m.Params.Options.Channel.Name = c.Name
|
||||
m.Params.Options.Channel.Public = c.Public
|
||||
m.Params.Options.Channel.MembersType = c.MembersType
|
||||
m.Params.Options.Channel.TopicName = c.TopicName
|
||||
m.Params.Options.Channel = c.Channel
|
||||
m.Params.Options.Message.Body = strings.Join(message, " ")
|
||||
m.Params.Options.MessageID = messageId
|
||||
|
||||
@ -121,9 +109,7 @@ func (c Chat) Edit(messageId int, message ...string) (ChatOut, error) {
|
||||
func (c Chat) React(messageId int, reaction string) (ChatOut, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "reaction"
|
||||
m.Params.Options.Channel.Name = c.Name
|
||||
m.Params.Options.Channel.MembersType = c.MembersType
|
||||
m.Params.Options.Channel.TopicName = c.TopicName
|
||||
m.Params.Options.Channel = c.Channel
|
||||
m.Params.Options.Message.Body = reaction
|
||||
m.Params.Options.MessageID = messageId
|
||||
|
||||
@ -138,10 +124,7 @@ func (c Chat) React(messageId int, reaction string) (ChatOut, error) {
|
||||
func (c Chat) Delete(messageId int) (ChatOut, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "delete"
|
||||
m.Params.Options.Channel.Name = c.Name
|
||||
m.Params.Options.Channel.Public = c.Public
|
||||
m.Params.Options.Channel.MembersType = c.MembersType
|
||||
m.Params.Options.Channel.TopicName = c.TopicName
|
||||
m.Params.Options.Channel = c.Channel
|
||||
m.Params.Options.MessageID = messageId
|
||||
|
||||
r, err := chatAPIOut(c.keybase.Path, m)
|
||||
|
||||
44
keybase.go
44
keybase.go
@ -25,17 +25,10 @@ type Keybase struct {
|
||||
Version string
|
||||
}
|
||||
|
||||
// Channel is a map of options that can be passed to NewChat()
|
||||
type Channel map[string]interface{}
|
||||
|
||||
// Chat holds basic information about a specific conversation
|
||||
type Chat struct {
|
||||
keybase Keybase
|
||||
Name string
|
||||
Public bool
|
||||
MembersType string
|
||||
TopicName string
|
||||
TopicType string
|
||||
Channel Channel
|
||||
}
|
||||
|
||||
type chat interface {
|
||||
@ -46,7 +39,8 @@ type chat interface {
|
||||
}
|
||||
|
||||
type keybase interface {
|
||||
NewChat(channel map[string]interface{}) Chat
|
||||
NewChat(channel Channel) Chat
|
||||
Runner(handler func(ChatIn), channelFilters ...Channel)
|
||||
ChatList() ([]conversation, error)
|
||||
loggedIn() bool
|
||||
username() string
|
||||
@ -75,35 +69,11 @@ func NewKeybase(path ...string) Keybase {
|
||||
}
|
||||
|
||||
// Return a new Chat instance
|
||||
func (k Keybase) NewChat(channel map[string]interface{}) Chat {
|
||||
var c Chat = Chat{}
|
||||
c.keybase = k
|
||||
if value, ok := channel["Name"].(string); ok == true {
|
||||
c.Name = value
|
||||
func (k Keybase) NewChat(channel Channel) Chat {
|
||||
return Chat{
|
||||
keybase: k,
|
||||
Channel: channel,
|
||||
}
|
||||
if value, ok := channel["Public"].(bool); ok == true {
|
||||
c.Public = value
|
||||
} else {
|
||||
c.Public = false
|
||||
}
|
||||
if value, ok := channel["MembersType"].(string); ok == true {
|
||||
c.MembersType = value
|
||||
} else {
|
||||
c.MembersType = USER
|
||||
}
|
||||
if value, ok := channel["TopicName"].(string); ok == true {
|
||||
c.TopicName = value
|
||||
} else {
|
||||
if c.MembersType == TEAM {
|
||||
c.TopicName = "general"
|
||||
}
|
||||
}
|
||||
if value, ok := channel["TopicType"].(string); ok == true {
|
||||
c.TopicType = value
|
||||
} else {
|
||||
c.TopicType = CHAT
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// username() returns the username of the currently logged-in Keybase user.
|
||||
|
||||
Reference in New Issue
Block a user