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.
557 lines
13 KiB
557 lines
13 KiB
6 years ago
|
package keybase
|
||
6 years ago
|
|
||
6 years ago
|
import (
|
||
|
"bufio"
|
||
5 years ago
|
"encoding/base64"
|
||
|
"encoding/binary"
|
||
6 years ago
|
"encoding/json"
|
||
6 years ago
|
"errors"
|
||
6 years ago
|
"os/exec"
|
||
6 years ago
|
"strings"
|
||
6 years ago
|
"time"
|
||
6 years ago
|
)
|
||
6 years ago
|
|
||
5 years ago
|
// Returns a string representation of a message id suitable for use in a
|
||
|
// pagination struct
|
||
5 years ago
|
func getID(id uint) string {
|
||
5 years ago
|
var b []byte
|
||
|
switch {
|
||
|
case id < 128:
|
||
|
// 7-bit int
|
||
|
b = make([]byte, 1)
|
||
|
b = []byte{byte(id)}
|
||
|
|
||
|
case id <= 255:
|
||
|
// uint8
|
||
|
b = make([]byte, 2)
|
||
|
b = []byte{204, byte(id)}
|
||
|
|
||
|
case id > 255 && id <= 65535:
|
||
|
// uint16
|
||
|
b = make([]byte, 2)
|
||
|
binary.BigEndian.PutUint16(b, uint16(id))
|
||
|
b = append([]byte{205}, b...)
|
||
|
|
||
|
case id > 65535 && id <= 4294967295:
|
||
|
// uint32
|
||
|
b = make([]byte, 4)
|
||
|
binary.BigEndian.PutUint32(b, uint32(id))
|
||
|
b = append([]byte{206}, b...)
|
||
|
}
|
||
|
return base64.StdEncoding.EncodeToString(b)
|
||
|
}
|
||
|
|
||
6 years ago
|
// 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 ""
|
||
6 years ago
|
}
|
||
6 years ago
|
jsonBytes, _ := json.Marshal(channel)
|
||
|
return string(jsonBytes)
|
||
|
}
|
||
6 years ago
|
|
||
6 years ago
|
// 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)
|
||
6 years ago
|
}
|
||
|
|
||
6 years ago
|
// Run `keybase chat api-listen` to get new messages coming into keybase and send them into the channel
|
||
6 years ago
|
func getNewMessages(k *Keybase, c chan<- ChatAPI, execOptions []string) {
|
||
6 years ago
|
execString := []string{"chat", "api-listen"}
|
||
6 years ago
|
if len(execOptions) > 0 {
|
||
6 years ago
|
execString = append(execString, execOptions...)
|
||
6 years ago
|
}
|
||
6 years ago
|
for {
|
||
6 years ago
|
execCmd := exec.Command(k.Path, execString...)
|
||
|
stdOut, _ := execCmd.StdoutPipe()
|
||
|
execCmd.Start()
|
||
|
scanner := bufio.NewScanner(stdOut)
|
||
6 years ago
|
go func(scanner *bufio.Scanner, c chan<- ChatAPI) {
|
||
6 years ago
|
for scanner.Scan() {
|
||
5 years ago
|
var jsonData ChatAPI
|
||
6 years ago
|
json.Unmarshal([]byte(scanner.Text()), &jsonData)
|
||
5 years ago
|
if jsonData.ErrorRaw != nil {
|
||
|
var errorListen = string(*jsonData.ErrorRaw)
|
||
5 years ago
|
jsonData.ErrorListen = &errorListen
|
||
|
}
|
||
6 years ago
|
c <- jsonData
|
||
|
}
|
||
|
}(scanner, c)
|
||
6 years ago
|
execCmd.Wait()
|
||
6 years ago
|
}
|
||
6 years ago
|
}
|
||
|
|
||
6 years ago
|
// Run runs `keybase chat api-listen`, and passes incoming messages to the message handler func
|
||
6 years ago
|
func (k *Keybase) Run(handler func(ChatAPI), options ...RunOptions) {
|
||
6 years ago
|
var heartbeatFreq int64
|
||
5 years ago
|
var channelCapacity = 100
|
||
|
|
||
6 years ago
|
runOptions := make([]string, 0)
|
||
|
if len(options) > 0 {
|
||
5 years ago
|
if options[0].Capacity > 0 {
|
||
|
channelCapacity = options[0].Capacity
|
||
|
}
|
||
6 years ago
|
if options[0].Heartbeat > 0 {
|
||
|
heartbeatFreq = options[0].Heartbeat
|
||
|
}
|
||
6 years ago
|
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))
|
||
6 years ago
|
|
||
6 years ago
|
}
|
||
|
if options[0].FilterChannel.Name != "" {
|
||
|
runOptions = append(runOptions, "--filter-channel")
|
||
|
runOptions = append(runOptions, createFilterString(options[0].FilterChannel))
|
||
|
}
|
||
|
}
|
||
5 years ago
|
c := make(chan ChatAPI, channelCapacity)
|
||
6 years ago
|
defer close(c)
|
||
6 years ago
|
if heartbeatFreq > 0 {
|
||
|
go heartbeat(c, time.Duration(heartbeatFreq)*time.Minute)
|
||
|
}
|
||
6 years ago
|
go getNewMessages(k, c, runOptions)
|
||
6 years ago
|
for {
|
||
6 years ago
|
go handler(<-c)
|
||
6 years ago
|
}
|
||
|
}
|
||
6 years ago
|
|
||
6 years ago
|
// heartbeat sends a message through the channel with a message type of `heartbeat`
|
||
6 years ago
|
func heartbeat(c chan<- ChatAPI, freq time.Duration) {
|
||
|
m := ChatAPI{
|
||
6 years ago
|
Type: "heartbeat",
|
||
|
}
|
||
|
count := 0
|
||
|
for {
|
||
|
time.Sleep(freq)
|
||
|
m.Msg.ID = count
|
||
|
c <- m
|
||
6 years ago
|
count++
|
||
6 years ago
|
}
|
||
|
}
|
||
6 years ago
|
|
||
6 years ago
|
// chatAPIOut sends JSON requests to the chat API and returns its response.
|
||
5 years ago
|
func chatAPIOut(k *Keybase, c ChatAPI) (ChatAPI, error) {
|
||
6 years ago
|
jsonBytes, _ := json.Marshal(c)
|
||
|
|
||
5 years ago
|
cmdOut, err := k.Exec("chat", "api", "-m", string(jsonBytes))
|
||
6 years ago
|
if err != nil {
|
||
|
return ChatAPI{}, err
|
||
|
}
|
||
|
|
||
|
var r ChatAPI
|
||
|
if err := json.Unmarshal(cmdOut, &r); err != nil {
|
||
|
return ChatAPI{}, err
|
||
|
}
|
||
5 years ago
|
if r.ErrorRaw != nil {
|
||
5 years ago
|
var errorRead Error
|
||
5 years ago
|
json.Unmarshal([]byte(*r.ErrorRaw), &errorRead)
|
||
5 years ago
|
r.ErrorRead = &errorRead
|
||
|
return r, errors.New(r.ErrorRead.Message)
|
||
6 years ago
|
}
|
||
6 years ago
|
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
// Send sends a chat message
|
||
|
func (c Chat) Send(message ...string) (ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
5 years ago
|
m.Params.Options = options{
|
||
|
Message: &mesg{},
|
||
|
}
|
||
|
|
||
6 years ago
|
m.Method = "send"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
6 years ago
|
m.Params.Options.Message.Body = strings.Join(message, " ")
|
||
|
|
||
5 years ago
|
r, err := chatAPIOut(c.keybase, m)
|
||
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
5 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
5 years ago
|
// SendEphemeral sends an exploding chat message, with specified duration
|
||
|
func (c Chat) SendEphemeral(duration time.Duration, message ...string) (ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Params.Options = options{
|
||
|
Message: &mesg{},
|
||
|
}
|
||
|
m.Params.Options.ExplodingLifetime.Duration = duration
|
||
|
m.Method = "send"
|
||
|
m.Params.Options.Channel = &c.Channel
|
||
|
m.Params.Options.Message.Body = strings.Join(message, " ")
|
||
|
|
||
|
r, err := chatAPIOut(c.keybase, m)
|
||
|
if err != nil {
|
||
|
return r, err
|
||
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
5 years ago
|
// Reply sends a reply to a chat message
|
||
|
func (c Chat) Reply(replyTo int, message ...string) (ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Params.Options = options{
|
||
|
Message: &mesg{},
|
||
|
}
|
||
|
|
||
|
m.Method = "send"
|
||
|
m.Params.Options.Channel = &c.Channel
|
||
|
m.Params.Options.ReplyTo = replyTo
|
||
|
m.Params.Options.Message.Body = strings.Join(message, " ")
|
||
|
|
||
5 years ago
|
r, err := chatAPIOut(c.keybase, m)
|
||
6 years ago
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
6 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
// Edit edits a previously sent chat message
|
||
6 years ago
|
func (c Chat) Edit(messageID int, message ...string) (ChatAPI, error) {
|
||
6 years ago
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
5 years ago
|
m.Params.Options = options{
|
||
|
Message: &mesg{},
|
||
|
}
|
||
6 years ago
|
m.Method = "edit"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
6 years ago
|
m.Params.Options.Message.Body = strings.Join(message, " ")
|
||
6 years ago
|
m.Params.Options.MessageID = messageID
|
||
6 years ago
|
|
||
5 years ago
|
r, err := chatAPIOut(c.keybase, m)
|
||
6 years ago
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
6 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
// React sends a reaction to a message.
|
||
6 years ago
|
func (c Chat) React(messageID int, reaction string) (ChatAPI, error) {
|
||
6 years ago
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
5 years ago
|
m.Params.Options = options{
|
||
|
Message: &mesg{},
|
||
|
}
|
||
6 years ago
|
m.Method = "reaction"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
6 years ago
|
m.Params.Options.Message.Body = reaction
|
||
6 years ago
|
m.Params.Options.MessageID = messageID
|
||
6 years ago
|
|
||
5 years ago
|
r, err := chatAPIOut(c.keybase, m)
|
||
6 years ago
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
6 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
// Delete deletes a chat message
|
||
6 years ago
|
func (c Chat) Delete(messageID int) (ChatAPI, error) {
|
||
6 years ago
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Method = "delete"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
6 years ago
|
m.Params.Options.MessageID = messageID
|
||
6 years ago
|
|
||
5 years ago
|
r, err := chatAPIOut(c.keybase, m)
|
||
6 years ago
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
6 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
// ChatList returns a list of all conversations.
|
||
5 years ago
|
// You can pass a Channel to use as a filter here, but you'll probably want to
|
||
|
// leave the TopicName empty.
|
||
|
func (k *Keybase) ChatList(opts ...Channel) (ChatAPI, error) {
|
||
5 years ago
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
|
||
5 years ago
|
if len(opts) > 0 {
|
||
|
m.Params.Options.Name = opts[0].Name
|
||
|
m.Params.Options.Public = opts[0].Public
|
||
|
m.Params.Options.MembersType = opts[0].MembersType
|
||
|
m.Params.Options.TopicType = opts[0].TopicType
|
||
|
m.Params.Options.TopicName = opts[0].TopicName
|
||
5 years ago
|
}
|
||
6 years ago
|
m.Method = "list"
|
||
|
|
||
5 years ago
|
r, err := chatAPIOut(k, m)
|
||
6 years ago
|
return r, err
|
||
|
}
|
||
|
|
||
5 years ago
|
// ReadMessage fetches the chat message with the specified message id from a conversation.
|
||
|
func (c Chat) ReadMessage(messageID int) (*ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Params.Options = options{
|
||
|
Pagination: &pagination{},
|
||
|
}
|
||
|
|
||
|
m.Method = "read"
|
||
|
m.Params.Options.Channel = &c.Channel
|
||
|
m.Params.Options.Pagination.Num = 1
|
||
|
|
||
5 years ago
|
m.Params.Options.Pagination.Previous = getID(uint(messageID - 1))
|
||
5 years ago
|
|
||
|
r, err := chatAPIOut(c.keybase, m)
|
||
|
if err != nil {
|
||
5 years ago
|
return &r, err
|
||
5 years ago
|
}
|
||
|
r.keybase = *c.keybase
|
||
|
return &r, nil
|
||
|
}
|
||
|
|
||
6 years ago
|
// Read fetches chat messages from a conversation. By default, 10 messages will
|
||
|
// be fetched at a time. However, if count is passed, then that is the number of
|
||
|
// messages that will be fetched.
|
||
|
func (c Chat) Read(count ...int) (*ChatAPI, error) {
|
||
6 years ago
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
5 years ago
|
m.Params.Options = options{
|
||
|
Pagination: &pagination{},
|
||
|
}
|
||
|
|
||
6 years ago
|
m.Method = "read"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
6 years ago
|
if len(count) == 0 {
|
||
|
m.Params.Options.Pagination.Num = 10
|
||
|
} else {
|
||
|
m.Params.Options.Pagination.Num = count[0]
|
||
|
}
|
||
|
|
||
5 years ago
|
r, err := chatAPIOut(c.keybase, m)
|
||
6 years ago
|
if err != nil {
|
||
5 years ago
|
return &r, err
|
||
6 years ago
|
}
|
||
|
r.keybase = *c.keybase
|
||
|
return &r, nil
|
||
|
}
|
||
|
|
||
|
// Next fetches the next page of chat messages that were fetched with Read. By
|
||
|
// default, Next will fetch the same amount of messages that were originally
|
||
|
// fetched with Read. However, if count is passed, then that is the number of
|
||
|
// messages that will be fetched.
|
||
|
func (c *ChatAPI) Next(count ...int) (*ChatAPI, error) {
|
||
6 years ago
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
5 years ago
|
m.Params.Options = options{
|
||
|
Pagination: &pagination{},
|
||
|
}
|
||
|
|
||
6 years ago
|
m.Method = "read"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Result.Messages[0].Msg.Channel
|
||
6 years ago
|
if len(count) == 0 {
|
||
|
m.Params.Options.Pagination.Num = c.Result.Pagination.Num
|
||
|
} else {
|
||
|
m.Params.Options.Pagination.Num = count[0]
|
||
|
}
|
||
|
m.Params.Options.Pagination.Next = c.Result.Pagination.Next
|
||
|
|
||
5 years ago
|
result, err := chatAPIOut(&c.keybase, m)
|
||
6 years ago
|
if err != nil {
|
||
5 years ago
|
return &result, err
|
||
6 years ago
|
}
|
||
|
k := c.keybase
|
||
|
*c = result
|
||
|
c.keybase = k
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
// Previous fetches the previous page of chat messages that were fetched with Read.
|
||
|
// By default, Previous will fetch the same amount of messages that were
|
||
|
// originally fetched with Read. However, if count is passed, then that is the
|
||
|
// number of messages that will be fetched.
|
||
|
func (c *ChatAPI) Previous(count ...int) (*ChatAPI, error) {
|
||
6 years ago
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
5 years ago
|
m.Params.Options = options{
|
||
|
Pagination: &pagination{},
|
||
|
}
|
||
|
|
||
6 years ago
|
m.Method = "read"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Result.Messages[0].Msg.Channel
|
||
6 years ago
|
if len(count) == 0 {
|
||
|
m.Params.Options.Pagination.Num = c.Result.Pagination.Num
|
||
|
} else {
|
||
|
m.Params.Options.Pagination.Num = count[0]
|
||
|
}
|
||
|
m.Params.Options.Pagination.Previous = c.Result.Pagination.Previous
|
||
|
|
||
5 years ago
|
result, err := chatAPIOut(&c.keybase, m)
|
||
6 years ago
|
if err != nil {
|
||
5 years ago
|
return &result, err
|
||
6 years ago
|
}
|
||
|
k := c.keybase
|
||
|
*c = result
|
||
|
c.keybase = k
|
||
|
return c, nil
|
||
|
}
|
||
5 years ago
|
|
||
5 years ago
|
// Upload attaches a file to a conversation
|
||
|
// The filepath must be an absolute path
|
||
5 years ago
|
func (c Chat) Upload(title string, filepath string) (ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Method = "attach"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
5 years ago
|
m.Params.Options.Filename = filepath
|
||
|
m.Params.Options.Title = title
|
||
|
|
||
5 years ago
|
r, err := chatAPIOut(c.keybase, m)
|
||
5 years ago
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
5 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
5 years ago
|
// Download downloads a file from a conversation
|
||
5 years ago
|
func (c Chat) Download(messageID int, filepath string) (ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Method = "download"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
5 years ago
|
m.Params.Options.Output = filepath
|
||
|
m.Params.Options.MessageID = messageID
|
||
|
|
||
5 years ago
|
r, err := chatAPIOut(c.keybase, m)
|
||
5 years ago
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
5 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
5 years ago
|
|
||
5 years ago
|
// LoadFlip returns the results of a flip
|
||
|
// If the flip is still in progress, this can be expected to change if called again
|
||
5 years ago
|
func (c Chat) LoadFlip(messageID int, conversationID string, flipConversationID string, gameID string) (ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Method = "loadflip"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
5 years ago
|
m.Params.Options.MsgID = messageID
|
||
|
m.Params.Options.ConversationID = conversationID
|
||
|
m.Params.Options.FlipConversationID = flipConversationID
|
||
|
m.Params.Options.GameID = gameID
|
||
|
|
||
5 years ago
|
r, err := chatAPIOut(c.keybase, m)
|
||
5 years ago
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
5 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
5 years ago
|
|
||
|
// Pin pins a message to a channel
|
||
|
func (c Chat) Pin(messageID int) (ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Method = "pin"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
5 years ago
|
m.Params.Options.MessageID = messageID
|
||
|
|
||
|
r, err := chatAPIOut(c.keybase, m)
|
||
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
5 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
// Unpin clears any pinned messages from a channel
|
||
|
func (c Chat) Unpin() (ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Method = "unpin"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
5 years ago
|
|
||
|
r, err := chatAPIOut(c.keybase, m)
|
||
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
5 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
5 years ago
|
|
||
|
// Mark marks a conversation as read up to a specified message
|
||
|
func (c Chat) Mark(messageID int) (ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Method = "mark"
|
||
5 years ago
|
m.Params.Options.Channel = &c.Channel
|
||
5 years ago
|
m.Params.Options.MessageID = messageID
|
||
|
|
||
|
r, err := chatAPIOut(c.keybase, m)
|
||
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
5 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
5 years ago
|
|
||
|
// ClearCommands clears bot advertisements
|
||
|
func (k *Keybase) ClearCommands() (ChatAPI, error) {
|
||
|
m := ChatAPI{}
|
||
|
m.Method = "clearcommands"
|
||
|
|
||
|
r, err := chatAPIOut(k, m)
|
||
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
5 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
// AdvertiseCommands sets up bot command advertisements
|
||
|
// This method allows you to set up multiple different types of advertisements at once.
|
||
|
// Use this method if you have commands whose visibility differs from each other.
|
||
|
func (k *Keybase) AdvertiseCommands(advertisements []BotAdvertisement) (ChatAPI, error) {
|
||
|
m := ChatAPI{
|
||
|
Params: ¶ms{},
|
||
|
}
|
||
|
m.Method = "advertisecommands"
|
||
|
m.Params.Options.BotAdvertisements = advertisements
|
||
|
|
||
|
r, err := chatAPIOut(k, m)
|
||
|
if err != nil {
|
||
5 years ago
|
return r, err
|
||
5 years ago
|
}
|
||
|
return r, nil
|
||
|
}
|
||
|
|
||
|
// AdvertiseCommand sets up bot command advertisements
|
||
|
// This method allows you to set up one type of advertisement.
|
||
|
// Use this method if you have commands whose visibility should all be the same.
|
||
|
func (k *Keybase) AdvertiseCommand(advertisement BotAdvertisement) (ChatAPI, error) {
|
||
|
return k.AdvertiseCommands([]BotAdvertisement{
|
||
|
advertisement,
|
||
|
})
|
||
|
}
|