Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 17e3a7ab6d | |||
| a3c0fbf447 | |||
| 63e41c70ab | |||
| e5fa55e398 | |||
| 399e0b4e94 | |||
| db332e733a | |||
| ae3ed73adc | |||
| 4728aa6133 | |||
| efd8dab359 | |||
| 003ba3a4e0 |
75
chatIn.go
75
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"`
|
||||
@ -32,10 +30,33 @@ type chatInAddedtoteam struct {
|
||||
type chatInBulkaddtoconv struct {
|
||||
Usernames []string `json:"usernames"`
|
||||
}
|
||||
type chatInCommits struct {
|
||||
CommitHash string `json:"commitHash"`
|
||||
Message string `json:"message"`
|
||||
AuthorName string `json:"authorName"`
|
||||
AuthorEmail string `json:"authorEmail"`
|
||||
Ctime int `json:"ctime"`
|
||||
}
|
||||
type chatInRefs struct {
|
||||
RefName string `json:"refName"`
|
||||
Commits []chatInCommits `json:"commits"`
|
||||
MoreCommitsAvailable bool `json:"moreCommitsAvailable"`
|
||||
IsDelete bool `json:"isDelete"`
|
||||
}
|
||||
type chatInGitpush struct {
|
||||
Team string `json:"team"`
|
||||
Pusher string `json:"pusher"`
|
||||
RepoName string `json:"repoName"`
|
||||
RepoID string `json:"repoID"`
|
||||
Refs []chatInRefs `json:"refs"`
|
||||
PushType int `json:"pushType"`
|
||||
PreviousRepoName string `json:"previousRepoName"`
|
||||
}
|
||||
type chatInSystem struct {
|
||||
SystemType int `json:"systemType"`
|
||||
Addedtoteam chatInAddedtoteam `json:"addedtoteam"`
|
||||
Bulkaddtoconv chatInBulkaddtoconv `json:"bulkaddtoconv"`
|
||||
Gitpush chatInGitpush `json:"gitpush"`
|
||||
}
|
||||
type chatInResult struct {
|
||||
ResultTyp int `json:"resultTyp"`
|
||||
@ -84,7 +105,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 +117,37 @@ 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, 50)
|
||||
defer close(c)
|
||||
go getNewMessages(k, c, createFilterString(channelFilters...))
|
||||
for {
|
||||
go handler(<-c)
|
||||
}
|
||||
}
|
||||
|
||||
103
chatOut.go
103
chatOut.go
@ -7,20 +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"`
|
||||
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"`
|
||||
}
|
||||
@ -40,26 +42,19 @@ 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 chatOutResultConversations struct {
|
||||
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"`
|
||||
Conversations []chatOutResultConversations `json:"conversations,omitempty"`
|
||||
Conversations []conversation `json:"conversations,omitempty"`
|
||||
Offline bool `json:"offline,omitempty"`
|
||||
}
|
||||
|
||||
@ -81,92 +76,58 @@ func chatAPIOut(keybasePath string, c chatOut) (chatOutResult, error) {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// ChatSendText() sends a chat message to a user.
|
||||
func (k Keybase) ChatSendText(user string, message ...string) (ChatOut, error) {
|
||||
// Send() sends a chat message
|
||||
func (c Chat) Send(message ...string) (ChatOut, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "send"
|
||||
m.Params.Options.Channel.Name = user
|
||||
m.Params.Options.Channel = c.Channel
|
||||
m.Params.Options.Message.Body = strings.Join(message, " ")
|
||||
|
||||
r, err := chatAPIOut(k.path, m)
|
||||
r, err := chatAPIOut(c.keybase.Path, m)
|
||||
if err != nil {
|
||||
return ChatOut{}, err
|
||||
}
|
||||
return r.Result, nil
|
||||
}
|
||||
|
||||
// ChatSendTextTeam() sends a chat message to a team.
|
||||
func (k Keybase) ChatSendTextTeam(team, channel string, message ...string) (ChatOut, error) {
|
||||
// Edit() edits a previously sent chat message
|
||||
func (c Chat) Edit(messageId int, message ...string) (ChatOut, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "send"
|
||||
m.Params.Options.Channel.Name = team
|
||||
m.Params.Options.Channel.MembersType = "team"
|
||||
m.Params.Options.Channel.TopicName = channel
|
||||
m.Method = "edit"
|
||||
m.Params.Options.Channel = c.Channel
|
||||
m.Params.Options.Message.Body = strings.Join(message, " ")
|
||||
m.Params.Options.MessageID = messageId
|
||||
|
||||
r, err := chatAPIOut(k.path, m)
|
||||
r, err := chatAPIOut(c.keybase.Path, m)
|
||||
if err != nil {
|
||||
return ChatOut{}, err
|
||||
}
|
||||
return r.Result, nil
|
||||
}
|
||||
|
||||
// ChatReact() sends a reaction to a user's message.
|
||||
func (k Keybase) ChatReact(user, reaction string, messageId int) (ChatOut, error) {
|
||||
// React() sends a reaction to a message.
|
||||
func (c Chat) React(messageId int, reaction string) (ChatOut, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "reaction"
|
||||
m.Params.Options.Channel.Name = user
|
||||
m.Params.Options.MessageID = messageId
|
||||
m.Params.Options.Channel = c.Channel
|
||||
m.Params.Options.Message.Body = reaction
|
||||
m.Params.Options.MessageID = messageId
|
||||
|
||||
r, err := chatAPIOut(k.path, m)
|
||||
r, err := chatAPIOut(c.keybase.Path, m)
|
||||
if err != nil {
|
||||
return ChatOut{}, err
|
||||
}
|
||||
return r.Result, nil
|
||||
}
|
||||
|
||||
// ChatReactTeam() sends a reaction to a message on a team.
|
||||
func (k Keybase) ChatReactTeam(team, channel, reaction string, messageId int) (ChatOut, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "reaction"
|
||||
m.Params.Options.Channel.Name = team
|
||||
m.Params.Options.Channel.MembersType = "team"
|
||||
m.Params.Options.Channel.TopicName = channel
|
||||
m.Params.Options.MessageID = messageId
|
||||
m.Params.Options.Message.Body = reaction
|
||||
|
||||
r, err := chatAPIOut(k.path, m)
|
||||
if err != nil {
|
||||
return ChatOut{}, err
|
||||
}
|
||||
return r.Result, nil
|
||||
}
|
||||
|
||||
// ChatDeleteMessage() deletes a message from a one-on-one conversation.
|
||||
func (k Keybase) ChatDeleteMessage(user string, messageId int) (ChatOut, error) {
|
||||
// Delete() deletes a chat message
|
||||
func (c Chat) Delete(messageId int) (ChatOut, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "delete"
|
||||
m.Params.Options.Channel.Name = user
|
||||
m.Params.Options.Channel = c.Channel
|
||||
m.Params.Options.MessageID = messageId
|
||||
|
||||
r, err := chatAPIOut(k.path, m)
|
||||
if err != nil {
|
||||
return ChatOut{}, err
|
||||
}
|
||||
return r.Result, nil
|
||||
}
|
||||
|
||||
// ChatDeleteMessageTeam() deletes a message from a team conversation.
|
||||
func (k Keybase) ChatDeleteMessageTeam(team, channel string, messageId int) (ChatOut, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "delete"
|
||||
m.Params.Options.Channel.Name = team
|
||||
m.Params.Options.Channel.MembersType = "team"
|
||||
m.Params.Options.Channel.TopicName = channel
|
||||
m.Params.Options.MessageID = messageId
|
||||
|
||||
r, err := chatAPIOut(k.path, m)
|
||||
r, err := chatAPIOut(c.keybase.Path, m)
|
||||
if err != nil {
|
||||
return ChatOut{}, err
|
||||
}
|
||||
@ -174,10 +135,10 @@ func (k Keybase) ChatDeleteMessageTeam(team, channel string, messageId int) (Cha
|
||||
}
|
||||
|
||||
// ChatList() returns a list of all conversations.
|
||||
func (k Keybase) ChatList() ([]chatOutResultConversations, error) {
|
||||
func (k Keybase) ChatList() ([]conversation, error) {
|
||||
m := chatOut{}
|
||||
m.Method = "list"
|
||||
|
||||
r, err := chatAPIOut(k.path, m)
|
||||
r, err := chatAPIOut(k.Path, m)
|
||||
return r.Result.Conversations, err
|
||||
}
|
||||
|
||||
87
keybase.go
87
keybase.go
@ -5,21 +5,46 @@ import (
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// Possible MemberTypes
|
||||
const (
|
||||
TEAM string = "team"
|
||||
USER string = "impteamnative"
|
||||
)
|
||||
|
||||
// Possible TopicTypes
|
||||
const (
|
||||
DEV string = "dev"
|
||||
CHAT string = "chat"
|
||||
)
|
||||
|
||||
// Keybase holds basic information about the local Keybase executable
|
||||
type Keybase struct {
|
||||
path string
|
||||
Path string
|
||||
Username string
|
||||
LoggedIn bool
|
||||
Version string
|
||||
}
|
||||
|
||||
// Chat holds basic information about a specific conversation
|
||||
type Chat struct {
|
||||
keybase Keybase
|
||||
Channel Channel
|
||||
}
|
||||
|
||||
type chat interface {
|
||||
Send(message ...string) (ChatOut, error)
|
||||
Edit(messageId int, message ...string) (ChatOut, error)
|
||||
React(messageId int, reaction string) (ChatOut, error)
|
||||
Delete(messageId int) (ChatOut, error)
|
||||
}
|
||||
|
||||
type keybase interface {
|
||||
ChatSendText(user string, message ...string) (ChatOut, error)
|
||||
ChatSendTextTeam(team, channel, message string) (ChatOut, error)
|
||||
ChatReact(user, reaction string, messageId int) (ChatOut, error)
|
||||
ChatReactTeam(team, channel, reaction string, messageId int) (ChatOut, error)
|
||||
ChatDeleteMessage(user string, messageId int) (ChatOut, error)
|
||||
ChatDeleteMessageTeam(team, channel string, messageId int) (ChatOut, error)
|
||||
ChatList() ([]chatOutResultConversations, error)
|
||||
LoggedIn() bool
|
||||
Username() string
|
||||
Version() string
|
||||
NewChat(channel Channel) Chat
|
||||
Runner(handler func(ChatIn), channelFilters ...Channel)
|
||||
ChatList() ([]conversation, error)
|
||||
loggedIn() bool
|
||||
username() string
|
||||
version() string
|
||||
}
|
||||
|
||||
type status struct {
|
||||
@ -28,16 +53,32 @@ type status struct {
|
||||
}
|
||||
|
||||
// New() returns a new instance of Keybase object. Optionally, you can pass a string containing the path to the Keybase executable as the first argument.
|
||||
func New(path ...string) Keybase {
|
||||
func NewKeybase(path ...string) Keybase {
|
||||
k := Keybase{}
|
||||
if len(path) < 1 {
|
||||
return Keybase{path: "/usr/bin/keybase"}
|
||||
k.Path = "keybase"
|
||||
} else {
|
||||
k.Path = path[0]
|
||||
}
|
||||
return Keybase{path: path[0]}
|
||||
k.Version = k.version()
|
||||
k.LoggedIn = k.loggedIn()
|
||||
if k.LoggedIn == true {
|
||||
k.Username = k.username()
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
// Username() returns the username of the currently logged-in Keybase user.
|
||||
func (k Keybase) Username() string {
|
||||
cmd := exec.Command(k.path, "status", "-j")
|
||||
// Return a new Chat instance
|
||||
func (k Keybase) NewChat(channel Channel) Chat {
|
||||
return Chat{
|
||||
keybase: k,
|
||||
Channel: channel,
|
||||
}
|
||||
}
|
||||
|
||||
// username() returns the username of the currently logged-in Keybase user.
|
||||
func (k Keybase) username() string {
|
||||
cmd := exec.Command(k.Path, "status", "-j")
|
||||
cmdOut, err := cmd.Output()
|
||||
if err != nil {
|
||||
return ""
|
||||
@ -49,9 +90,9 @@ func (k Keybase) Username() string {
|
||||
return s.Username
|
||||
}
|
||||
|
||||
// LoggedIn() returns true if Keybase is currently logged in, otherwise returns false.
|
||||
func (k Keybase) LoggedIn() bool {
|
||||
cmd := exec.Command(k.path, "status", "-j")
|
||||
// loggedIn() returns true if Keybase is currently logged in, otherwise returns false.
|
||||
func (k Keybase) loggedIn() bool {
|
||||
cmd := exec.Command(k.Path, "status", "-j")
|
||||
cmdOut, err := cmd.Output()
|
||||
if err != nil {
|
||||
return false
|
||||
@ -63,9 +104,9 @@ func (k Keybase) LoggedIn() bool {
|
||||
return s.LoggedIn
|
||||
}
|
||||
|
||||
// Version() returns the version string of the client.
|
||||
func (k Keybase) Version() string {
|
||||
cmd := exec.Command(k.path, "version", "-S", "-f", "s")
|
||||
// version() returns the version string of the client.
|
||||
func (k Keybase) version() string {
|
||||
cmd := exec.Command(k.Path, "version", "-S", "-f", "s")
|
||||
cmdOut, err := cmd.Output()
|
||||
if err != nil {
|
||||
return ""
|
||||
|
||||
106
wallet.go
Normal file
106
wallet.go
Normal file
@ -0,0 +1,106 @@
|
||||
package keybase
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// ---- Struct for sending to API
|
||||
type walletOut struct {
|
||||
Method string `json:"method"`
|
||||
Params walletOutParams `json:"params"`
|
||||
}
|
||||
type walletOutOptions struct {
|
||||
Txid string `json:"txid"`
|
||||
}
|
||||
type walletOutParams struct {
|
||||
Options walletOutOptions `json:"options"`
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
// ---- Struct for data received after sending to API
|
||||
type walletOutResult struct {
|
||||
Result WalletResult `json:"result"`
|
||||
}
|
||||
type asset struct {
|
||||
Type string `json:"type"`
|
||||
Code string `json:"code"`
|
||||
Issuer string `json:"issuer"`
|
||||
VerifiedDomain string `json:"verifiedDomain"`
|
||||
IssuerName string `json:"issuerName"`
|
||||
Desc string `json:"desc"`
|
||||
InfoURL string `json:"infoUrl"`
|
||||
}
|
||||
type sourceAsset struct {
|
||||
Type string `json:"type"`
|
||||
Code string `json:"code"`
|
||||
Issuer string `json:"issuer"`
|
||||
VerifiedDomain string `json:"verifiedDomain"`
|
||||
IssuerName string `json:"issuerName"`
|
||||
Desc string `json:"desc"`
|
||||
InfoURL string `json:"infoUrl"`
|
||||
}
|
||||
type balance struct {
|
||||
Asset asset `json:"asset"`
|
||||
Amount string `json:"amount"`
|
||||
Limit string `json:"limit"`
|
||||
}
|
||||
type exchangeRate struct {
|
||||
Currency string `json:"currency"`
|
||||
Rate string `json:"rate"`
|
||||
}
|
||||
type WalletResult struct {
|
||||
AccountID string `json:"accountID"`
|
||||
IsPrimary bool `json:"isPrimary"`
|
||||
Name string `json:"name"`
|
||||
Balance []balance `json:"balance"`
|
||||
ExchangeRate exchangeRate `json:"exchangeRate"`
|
||||
AccountMode int `json:"accountMode"`
|
||||
TxID string `json:"txID"`
|
||||
Time int64 `json:"time"`
|
||||
Status string `json:"status"`
|
||||
StatusDetail string `json:"statusDetail"`
|
||||
Amount string `json:"amount"`
|
||||
Asset asset `json:"asset"`
|
||||
DisplayAmount string `json:"displayAmount"`
|
||||
DisplayCurrency string `json:"displayCurrency"`
|
||||
SourceAmountMax string `json:"sourceAmountMax"`
|
||||
SourceAmountActual string `json:"sourceAmountActual"`
|
||||
SourceAsset sourceAsset `json:"sourceAsset"`
|
||||
FromStellar string `json:"fromStellar"`
|
||||
ToStellar string `json:"toStellar"`
|
||||
FromUsername string `json:"fromUsername"`
|
||||
ToUsername string `json:"toUsername"`
|
||||
Note string `json:"note"`
|
||||
NoteErr string `json:"noteErr"`
|
||||
Unread bool `json:"unread"`
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
// walletAPIOut() sends JSON requests to the wallet API and returns its response.
|
||||
func walletAPIOut(keybasePath string, w walletOut) (walletOutResult, error) {
|
||||
jsonBytes, _ := json.Marshal(w)
|
||||
|
||||
cmd := exec.Command(keybasePath, "wallet", "api", "-m", string(jsonBytes))
|
||||
cmdOut, err := cmd.Output()
|
||||
if err != nil {
|
||||
return walletOutResult{}, err
|
||||
}
|
||||
|
||||
var r walletOutResult
|
||||
json.Unmarshal(cmdOut, &r)
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// TxDetail() returns details of a stellar transaction
|
||||
func (k Keybase) TxDetail(txid string) (WalletResult, error) {
|
||||
m := walletOut{}
|
||||
m.Method = "details"
|
||||
m.Params.Options.Txid = txid
|
||||
|
||||
r, err := walletAPIOut(k.Path, m)
|
||||
return r.Result, err
|
||||
}
|
||||
Reference in New Issue
Block a user