From cea5d393874612fbc00a944dc0d16fc9eadfa857 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 14:35:43 +0000 Subject: [PATCH 01/25] moved botConfig to types --- main.go | 6 ------ types.go | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/main.go b/main.go index 7582da4..c115322 100644 --- a/main.go +++ b/main.go @@ -32,12 +32,6 @@ type botConfig struct { KVStoreTeam string `env:"BOT_KVSTORE_TEAM" envDefault:""` } -// hold reply information when needed -type botReply struct { - convID chat1.ConvIDStr - msgID chat1.MessageID -} - // Debug provides printing only when --debug flag is set or BOT_DEBUG env var is set func (b *bot) debug(s string, a ...interface{}) { if b.config.Debug { diff --git a/types.go b/types.go index f14b6d4..0b10799 100644 --- a/types.go +++ b/types.go @@ -1,5 +1,13 @@ package main +import "samhofi.us/x/keybase/types/chat1" + +// hold reply information when needed +type botReply struct { + convID chat1.ConvIDStr + msgID chat1.MessageID +} + // ConvOptions stores team specific options like custom servers type ConvOptions struct { ConvID string `json:"converation_id,omitempty"` From 9ea12ab5f54f197ae0bdc7f3436ef4c22ce8e9af Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 14:36:46 +0000 Subject: [PATCH 02/25] removed kvstore testing code --- main.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/main.go b/main.go index c115322..563f8f5 100644 --- a/main.go +++ b/main.go @@ -105,22 +105,6 @@ func (b *bot) run(args []string) error { b.k.ClearCommands() b.registerCommands() - // this is just for testing, and doesn't work yet - if err := b.KVStorePutStruct("test", &ConvOptions{ConvID: "test", CustomURL: "https://te.st:888"}); err != nil { - log.Printf("KV: %+v", err) - } - var vRes1 ConvOptions - if err := b.KVStoreGetStruct("test", &vRes1); err != nil { - log.Printf("KV: %+v", err) - } else { - fmt.Printf("VR: %+v\n", vRes1) - } - var vRes2 ConvOptions - if err := b.KVStoreGetStruct("test1", &vRes2); err != nil { - log.Printf("KV: %+v", err) - } else { - fmt.Printf("VR: %+v\n", vRes2) - } log.Println("Starting...") b.k.Run(b.handlers, &b.opts) return nil From c08ded2a66557f9c597f77fef67f01c848cc0540 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 15:16:12 +0000 Subject: [PATCH 03/25] moved payments to commands --- commands.go | 16 ++++++++++++++++ handlers.go | 15 ++------------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/commands.go b/commands.go index 23b943e..b152243 100644 --- a/commands.go +++ b/commands.go @@ -9,6 +9,22 @@ import ( "samhofi.us/x/keybase/types/chat1" ) +func (b *bot) handlePayment(m chat1.MsgSummary) { + // there can be multiple payments on each message, iterate them + for _, payment := range m.Content.Text.Payments { + if strings.Contains(payment.PaymentText, b.k.Username) { + // if the payment is successful put log the payment for wallet closure + if payment.Result.ResultTyp__ == 0 && payment.Result.Error__ == nil { + var replyInfo = botReply{convID: m.ConvID, msgID: m.Id} + b.payments[*payment.Result.Sent__] = replyInfo + } else { + // if the payment fails, be sad + b.k.ReactByConvID(m.ConvID, m.Id, ":cry:") + } + } + } +} + func (b *bot) setupMeeting(convid chat1.ConvIDStr, sender string, args []string, membersType string) { b.debug("command recieved in conversation %s", convid) meeting, err := newJitsiMeetingSimple() diff --git a/handlers.go b/handlers.go index 7d4405c..6baa9e5 100644 --- a/handlers.go +++ b/handlers.go @@ -32,19 +32,8 @@ func (b *bot) chatHandler(m chat1.MsgSummary) { } // if this chat message is a payment, add it to the bot payments if m.Content.Text.Payments != nil { - // there can be multiple payments on each message, iterate them - for _, payment := range m.Content.Text.Payments { - if strings.Contains(payment.PaymentText, b.k.Username) { - // if the payment is successful put log the payment for wallet closure - if payment.Result.ResultTyp__ == 0 && payment.Result.Error__ == nil { - var replyInfo = botReply{convID: m.ConvID, msgID: m.Id} - b.payments[*payment.Result.Sent__] = replyInfo - } else { - // if the payment fails, be sad - b.k.ReactByConvID(m.ConvID, m.Id, ":cry:") - } - } - } + b.handlePayment(m) + return } // Determine first if this is a command if strings.HasPrefix(m.Content.Text.Body, "!") || strings.HasPrefix(m.Content.Text.Body, "@") { From cbf091a900e792b9c4632aaf9d6fea53ef0a5cd1 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 15:18:12 +0000 Subject: [PATCH 04/25] documentation --- commands.go | 1 + 1 file changed, 1 insertion(+) diff --git a/commands.go b/commands.go index b152243..b652aec 100644 --- a/commands.go +++ b/commands.go @@ -9,6 +9,7 @@ import ( "samhofi.us/x/keybase/types/chat1" ) +// handlePayment controls how the bot reacts to wallet payments in chat func (b *bot) handlePayment(m chat1.MsgSummary) { // there can be multiple payments on each message, iterate them for _, payment := range m.Content.Text.Payments { From 0c268326d7596863c62c3486e826994a55ac5b5a Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 15:19:19 +0000 Subject: [PATCH 05/25] removed unused global --- main.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/main.go b/main.go index 563f8f5..4ec2272 100644 --- a/main.go +++ b/main.go @@ -10,9 +10,6 @@ import ( "samhofi.us/x/keybase/types/stellar1" ) -// this global controls debug printing -var debug bool - // Bot holds the necessary information for the bot to work. type bot struct { k *keybase.Keybase From 26f8b2b2a62118b01e2b1d87ace563e5e8e05119 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 15:53:35 +0000 Subject: [PATCH 06/25] made logging more generic --- main.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index 4ec2272..6822099 100644 --- a/main.go +++ b/main.go @@ -32,25 +32,21 @@ type botConfig struct { // Debug provides printing only when --debug flag is set or BOT_DEBUG env var is set func (b *bot) debug(s string, a ...interface{}) { if b.config.Debug { - log.Printf(s, a...) - if b.config.LogConvIDStr != "" { - b.logToChat(s, a...) - } + b.log(s, a...) } } -// logToChat will send this message to the keybase chat configured in b.logConv -func (b *bot) logToChat(s string, a ...interface{}) { - // if the ConvIdStr isn't blank try to log +// logToChat will send this message to the keybase chat configured in b.config.LogConvIDStr +func (b *bot) log(s string, a ...interface{}) { + // if the ConvIdStr isn't blank try to log to chat if b.config.LogConvIDStr != "" { // if you can't send the message, log the error to stdout if _, err := b.k.SendMessageByConvID(chat1.ConvIDStr(b.config.LogConvIDStr), s, a...); err != nil { log.Printf("Unable to log to keybase chat: %s", err) } - } else { - // otherwise (and you shouldn't be here but....) log it to stdout - log.Println("Unable to log to keybase chat, logging ConvIDStr is not set") } + // and then log it to stdout + log.Printf(s, a...) } // newBot returns a new empty bot From 04b79c7ad7b254b9f8ac9dec00c816fce9c3aec4 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 15:56:56 +0000 Subject: [PATCH 07/25] added logging to payments --- commands.go | 1 + 1 file changed, 1 insertion(+) diff --git a/commands.go b/commands.go index b652aec..452a9d9 100644 --- a/commands.go +++ b/commands.go @@ -18,6 +18,7 @@ func (b *bot) handlePayment(m chat1.MsgSummary) { if payment.Result.ResultTyp__ == 0 && payment.Result.Error__ == nil { var replyInfo = botReply{convID: m.ConvID, msgID: m.Id} b.payments[*payment.Result.Sent__] = replyInfo + b.log("payment recieved %s", payment.PaymentText) } else { // if the payment fails, be sad b.k.ReactByConvID(m.ConvID, m.Id, ":cry:") From 2c89e9510ecbca184ed56be5f06695dec1edd205 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 16:00:41 +0000 Subject: [PATCH 08/25] changed to use log instead of debug --- utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils.go b/utils.go index b401642..c155fba 100644 --- a/utils.go +++ b/utils.go @@ -33,7 +33,7 @@ func (b *bot) logError(err error) string { // generate the error id eid := shortid.MustGenerate() // send the error to the log - b.debug("`%s` - %s", eid, err) + b.log("`%s` - %s", eid, err) // then return the error id for use return eid } From fc8aaf69d13a3acd33699f4cbf9e3b665b74d15d Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 16:01:07 +0000 Subject: [PATCH 09/25] changed setupMeeting to handleMeeting using new handler syntax --- commands.go | 14 +++++++------- handlers.go | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/commands.go b/commands.go index 452a9d9..cedbf8e 100644 --- a/commands.go +++ b/commands.go @@ -27,17 +27,17 @@ func (b *bot) handlePayment(m chat1.MsgSummary) { } } -func (b *bot) setupMeeting(convid chat1.ConvIDStr, sender string, args []string, membersType string) { - b.debug("command recieved in conversation %s", convid) +func (b *bot) handleMeeting(m chat1.MsgSummary) { + b.debug("command recieved in conversation %s", m.ConvID) meeting, err := newJitsiMeetingSimple() if err != nil { - log.Println(err) - message := fmt.Sprintf("@%s - I'm sorry, i'm not sure what happened... I was unable to set up a new meeting.\nI've written the appropriate logs and notified my humans.", sender) - b.k.SendMessageByConvID(convid, message) + eid := b.logError(err) + message := fmt.Sprintf("@%s - I'm sorry, i'm not sure what happened... I was unable to set up a new meeting.\nI've written the appropriate logs and notified my humans. Please reference Error ID %s", m.Sender.Username, eid) + b.k.SendMessageByConvID(m.ConvID, message) return } - message := fmt.Sprintf("@%s here's your meeting: %s", sender, meeting.getURL()) - b.k.SendMessageByConvID(convid, message) + message := fmt.Sprintf("@%s here's your meeting: %s", m.Sender.Username, meeting.getURL()) + b.k.SendMessageByConvID(m.ConvID, message) } func (b *bot) sendFeedback(convid chat1.ConvIDStr, mesgID chat1.MessageID, sender string, args []string) { diff --git a/handlers.go b/handlers.go index 6baa9e5..9bb575e 100644 --- a/handlers.go +++ b/handlers.go @@ -58,13 +58,13 @@ func (b *bot) chatHandler(m chat1.MsgSummary) { } case "jitsi": if nargs == 0 { - b.setupMeeting(m.ConvID, m.Sender.Username, args, m.Channel.MembersType) + b.handleMeeting(m) } else if nargs >= 1 { // pop the subcommand off the front of the list subcommand, args := args[0], args[1:] switch subcommand { case "meet": - b.setupMeeting(m.ConvID, m.Sender.Username, args, m.Channel.MembersType) + b.handleMeeting(m) case "feedback": b.sendFeedback(m.ConvID, m.Id, m.Sender.Username, args) case "hello": From fbb2d7e19dc21d0473a92f3a757abb309a045f49 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 16:30:06 +0000 Subject: [PATCH 10/25] changed to handleFeedback and new convention --- commands.go | 19 ++++++++++--------- handlers.go | 6 ++---- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/commands.go b/commands.go index cedbf8e..bff3006 100644 --- a/commands.go +++ b/commands.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "log" "net/url" "strings" @@ -40,19 +39,21 @@ func (b *bot) handleMeeting(m chat1.MsgSummary) { b.k.SendMessageByConvID(m.ConvID, message) } -func (b *bot) sendFeedback(convid chat1.ConvIDStr, mesgID chat1.MessageID, sender string, args []string) { - b.debug("feedback recieved in %s", convid) +func (b *bot) handleFeedback(m chat1.MsgSummary) { + b.log("feedback recieved in %s", m.ConvID) if b.config.FeedbackConvIDStr != "" { - feedback := strings.Join(args, " ") + args := strings.Fields(m.Content.Text.Body) + feedback := strings.Join(args[2:], " ") fcID := chat1.ConvIDStr(b.config.FeedbackConvIDStr) - if _, err := b.k.SendMessageByConvID(fcID, "Feedback from @%s:\n```%s```", sender, feedback); err != nil { - b.k.ReplyByConvID(convid, mesgID, "I'm sorry, I was unable to send your feedback because my benevolent overlords have not set a destination for feedback. :sad:") - log.Printf("Unable to send feedback: %s", err) + if _, err := b.k.SendMessageByConvID(fcID, "Feedback from @%s:\n```%s```", m.Sender.Username, feedback); err != nil { + eid := b.logError(err) + b.k.ReactByConvID(m.ConvID, m.Id, "Error ID %s", eid) } else { - b.k.ReplyByConvID(convid, mesgID, "Thanks! Your feedback has been sent to my human overlords!") + b.k.ReplyByConvID(m.ConvID, m.Id, "Thanks! Your feedback has been sent to my human overlords!") } } else { - b.debug("feedback not enabled. set --feedback-convid or BOT_FEEDBACK_CONVID") + b.k.ReplyByConvID(m.ConvID, m.Id, "I'm sorry, I was unable to send your feedback because my benevolent overlords have not set a destination for feedback. :sob:") + b.log("user tried to send feedback, but feedback is not enabled. set --feedback-convid or BOT_FEEDBACK_CONVID") } } diff --git a/handlers.go b/handlers.go index 9bb575e..65aba1f 100644 --- a/handlers.go +++ b/handlers.go @@ -60,13 +60,11 @@ func (b *bot) chatHandler(m chat1.MsgSummary) { if nargs == 0 { b.handleMeeting(m) } else if nargs >= 1 { - // pop the subcommand off the front of the list - subcommand, args := args[0], args[1:] - switch subcommand { + switch args[0] { case "meet": b.handleMeeting(m) case "feedback": - b.sendFeedback(m.ConvID, m.Id, m.Sender.Username, args) + b.handleFeedback(m) case "hello": fallthrough case "help": From 69f59711184ce41979796a38b51e731ac5fffc58 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 16:33:19 +0000 Subject: [PATCH 11/25] documentation --- commands.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/commands.go b/commands.go index bff3006..c3c4078 100644 --- a/commands.go +++ b/commands.go @@ -26,8 +26,11 @@ func (b *bot) handlePayment(m chat1.MsgSummary) { } } +// handleMeeting starts a new jitsi meeting func (b *bot) handleMeeting(m chat1.MsgSummary) { b.debug("command recieved in conversation %s", m.ConvID) + // currently we aren't sending dial-in information, so don't get it just generate the name + // use the simple method meeting, err := newJitsiMeetingSimple() if err != nil { eid := b.logError(err) @@ -35,10 +38,10 @@ func (b *bot) handleMeeting(m chat1.MsgSummary) { b.k.SendMessageByConvID(m.ConvID, message) return } - message := fmt.Sprintf("@%s here's your meeting: %s", m.Sender.Username, meeting.getURL()) - b.k.SendMessageByConvID(m.ConvID, message) + b.k.SendMessageByConvID(m.ConvID, "@%s here's your meeting: %s", m.Sender.Username, meeting.getURL()) } +// handleFeedback sends feedback to a keybase chat, if configured func (b *bot) handleFeedback(m chat1.MsgSummary) { b.log("feedback recieved in %s", m.ConvID) if b.config.FeedbackConvIDStr != "" { From 4c9304b8c297e8a628c2bea0fd4b2f4e86fc5693 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 16:39:03 +0000 Subject: [PATCH 12/25] updated handleWelcome() --- commands.go | 10 ++++++++-- handlers.go | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/commands.go b/commands.go index c3c4078..7192cd3 100644 --- a/commands.go +++ b/commands.go @@ -60,8 +60,14 @@ func (b *bot) handleFeedback(m chat1.MsgSummary) { } } -func (b *bot) sendWelcome(convid chat1.ConvIDStr) { - b.k.SendMessageByConvID(convid, "Hello there!! I'm the Jitsi meeting bot, made by @haukened\nI can start Jitsi meetings right here in this chat!\nI can be activated in 2 ways:\n 1. `@jitsibot`\n 2.`!jitsi`\nYou can provide feedback to my humans using:\n 1. `@jitsibot feedback `\n 2. `!jitsibot feedback `\nYou can also join @jitsi_meet to talk about features, enhancements, or talk to live humans! Everyone is welcome!\nI also accept donations to offset hosting costs, just send some XLM to my wallet if you feel like it by typing `+5XLM@jitsibot`\nIf you ever need to see this message again, ask me for help or say hello to me!") +/* +**** this function is a special case on parameters as it must be called from 2 handlers which +**** get their information from separate types. As a result we're only passing the conversation id. +**** because of this we can't wrap handleWelcome with permissions, not that you'd want to. + */ +// handleWelcome sends the welcome message to new conversations +func (b *bot) handleWelcome(id chat1.ConvIDStr) { + b.k.SendMessageByConvID(id, "Hello there!! I'm the Jitsi meeting bot, made by @haukened\nI can start Jitsi meetings right here in this chat!\nI can be activated in 2 ways:\n 1. `@jitsibot`\n 2.`!jitsi`\nYou can provide feedback to my humans using:\n 1. `@jitsibot feedback `\n 2. `!jitsibot feedback `\nYou can also join @jitsi_meet to talk about features, enhancements, or talk to live humans! Everyone is welcome!\nI also accept donations to offset hosting costs, just send some XLM to my wallet if you feel like it by typing `+5XLM@jitsibot`\nIf you ever need to see this message again, ask me for help or say hello to me!") } func (b *bot) setKValue(convid chat1.ConvIDStr, msgID chat1.MessageID, args []string) { diff --git a/handlers.go b/handlers.go index 65aba1f..e0d995b 100644 --- a/handlers.go +++ b/handlers.go @@ -68,7 +68,7 @@ func (b *bot) chatHandler(m chat1.MsgSummary) { case "hello": fallthrough case "help": - b.sendWelcome(m.ConvID) + b.handleWelcome(m.ConvID) default: return } @@ -90,7 +90,7 @@ func (b *bot) convHandler(m chat1.ConvSummary) { default: b.debug("New convID found %s, sending welcome message.", m.Id) } - b.sendWelcome(m.Id) + b.handleWelcome(m.Id) } // this handles wallet events, like when someone send you money in chat From 1890ee05855c937f1bfa27c84a69edee105f33da Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 16:43:15 +0000 Subject: [PATCH 13/25] re-ordered and comments --- commands.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/commands.go b/commands.go index 7192cd3..35067a3 100644 --- a/commands.go +++ b/commands.go @@ -8,6 +8,22 @@ import ( "samhofi.us/x/keybase/types/chat1" ) +/* +**** this function is a special case on parameters as it must be called from 2 handlers which +**** get their information from separate types. As a result we're only passing the conversation id. +**** because of this we can't wrap handleWelcome with permissions, not that you'd want to. + */ + +// handleWelcome sends the welcome message to new conversations +func (b *bot) handleWelcome(id chat1.ConvIDStr) { + b.k.SendMessageByConvID(id, "Hello there!! I'm the Jitsi meeting bot, made by @haukened\nI can start Jitsi meetings right here in this chat!\nI can be activated in 2 ways:\n 1. `@jitsibot`\n 2.`!jitsi`\nYou can provide feedback to my humans using:\n 1. `@jitsibot feedback `\n 2. `!jitsibot feedback `\nYou can also join @jitsi_meet to talk about features, enhancements, or talk to live humans! Everyone is welcome!\nI also accept donations to offset hosting costs, just send some XLM to my wallet if you feel like it by typing `+5XLM@jitsibot`\nIf you ever need to see this message again, ask me for help or say hello to me!") +} + +/* +**** all other commands here-below should only accept a single argument of type chat1.MsgSummary +**** in order to be compliant with the permissions wrapper. Anything not should be explicitly notated. + */ + // handlePayment controls how the bot reacts to wallet payments in chat func (b *bot) handlePayment(m chat1.MsgSummary) { // there can be multiple payments on each message, iterate them @@ -60,16 +76,6 @@ func (b *bot) handleFeedback(m chat1.MsgSummary) { } } -/* -**** this function is a special case on parameters as it must be called from 2 handlers which -**** get their information from separate types. As a result we're only passing the conversation id. -**** because of this we can't wrap handleWelcome with permissions, not that you'd want to. - */ -// handleWelcome sends the welcome message to new conversations -func (b *bot) handleWelcome(id chat1.ConvIDStr) { - b.k.SendMessageByConvID(id, "Hello there!! I'm the Jitsi meeting bot, made by @haukened\nI can start Jitsi meetings right here in this chat!\nI can be activated in 2 ways:\n 1. `@jitsibot`\n 2.`!jitsi`\nYou can provide feedback to my humans using:\n 1. `@jitsibot feedback `\n 2. `!jitsibot feedback `\nYou can also join @jitsi_meet to talk about features, enhancements, or talk to live humans! Everyone is welcome!\nI also accept donations to offset hosting costs, just send some XLM to my wallet if you feel like it by typing `+5XLM@jitsibot`\nIf you ever need to see this message again, ask me for help or say hello to me!") -} - func (b *bot) setKValue(convid chat1.ConvIDStr, msgID chat1.MessageID, args []string) { if args[0] != "set" { return From 150e0b63ab5f7004ccfbb00c7a58bf500713ad41 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 16:55:50 +0000 Subject: [PATCH 14/25] set command updated to handleSetCommand --- commands.go | 23 +++++++++++++---------- handlers.go | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/commands.go b/commands.go index 35067a3..c8d8b40 100644 --- a/commands.go +++ b/commands.go @@ -76,30 +76,33 @@ func (b *bot) handleFeedback(m chat1.MsgSummary) { } } -func (b *bot) setKValue(convid chat1.ConvIDStr, msgID chat1.MessageID, args []string) { - if args[0] != "set" { +func (b *bot) handleSetCommand(m chat1.MsgSummary) { + // first normalize the text and extract the arguments + args := strings.Fields(strings.ToLower(m.Content.Text.Body)) + if args[1] != "set" { return } switch len(args) { case 3: - if args[1] == "url" { + if args[2] == "url" { // first validate the URL u, err := url.ParseRequestURI(args[2]) if err != nil { - b.k.ReplyByConvID(convid, msgID, "ERROR - `%s`", err) + eid := b.logError(err) + b.k.ReactByConvID(m.ConvID, m.Id, "Error ID %s", eid) return } // then make sure its HTTPS if u.Scheme != "https" { - b.k.ReplyByConvID(convid, msgID, "ERROR - HTTPS Required") + b.k.ReactByConvID(m.ConvID, m.Id, "ERROR: HTTPS Required") return } // then get the current options var opts ConvOptions - err = b.KVStoreGetStruct(convid, &opts) + err = b.KVStoreGetStruct(m.ConvID, &opts) if err != nil { eid := b.logError(err) - b.k.ReactByConvID(convid, msgID, "Error %s", eid) + b.k.ReactByConvID(m.ConvID, m.Id, "Error ID %s", eid) return } // then update the struct using only the scheme and hostname:port @@ -109,13 +112,13 @@ func (b *bot) setKValue(convid chat1.ConvIDStr, msgID chat1.MessageID, args []st opts.CustomURL = fmt.Sprintf("%s://%s/", u.Scheme, u.Hostname()) } // then write that back to kvstore, with revision - err = b.KVStorePutStruct(convid, opts) + err = b.KVStorePutStruct(m.ConvID, opts) if err != nil { eid := b.logError(err) - b.k.ReactByConvID(convid, msgID, "ERROR %s", eid) + b.k.ReactByConvID(m.ConvID, m.Id, "Error ID %s", eid) return } - b.k.ReactByConvID(convid, msgID, "OK!") + b.k.ReactByConvID(m.ConvID, m.Id, "OK!") return } default: diff --git a/handlers.go b/handlers.go index e0d995b..20ded34 100644 --- a/handlers.go +++ b/handlers.go @@ -51,7 +51,7 @@ func (b *bot) chatHandler(m chat1.MsgSummary) { if nargs > 0 { switch args[0] { case "set": - b.setKValue(m.ConvID, m.Id, args) + b.handleSetCommand(m) case "list": b.listKValue(m.ConvID, m.Id, args) } From 1806f87e401cc9b46df0d389077d84a019b59a96 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 16:57:00 +0000 Subject: [PATCH 15/25] handleListCommand updated --- commands.go | 4 +++- handlers.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/commands.go b/commands.go index c8d8b40..5b263f8 100644 --- a/commands.go +++ b/commands.go @@ -126,7 +126,9 @@ func (b *bot) handleSetCommand(m chat1.MsgSummary) { } } -func (b *bot) listKValue(convid chat1.ConvIDStr, msgID chat1.MessageID, args []string) { +func (b *bot) handleListCommand(m chat1.MsgSummary) { + // first normalize the text and extract the arguments + args := strings.Fields(strings.ToLower(m.Content.Text.Body)) if args[0] != "list" { return } diff --git a/handlers.go b/handlers.go index 20ded34..d611d85 100644 --- a/handlers.go +++ b/handlers.go @@ -53,7 +53,7 @@ func (b *bot) chatHandler(m chat1.MsgSummary) { case "set": b.handleSetCommand(m) case "list": - b.listKValue(m.ConvID, m.Id, args) + b.handleListCommand(m) } } case "jitsi": From eebc610720a3deaeafdbc9ab3b039a25df357d3b Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 16:58:34 +0000 Subject: [PATCH 16/25] documentation --- commands.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/commands.go b/commands.go index 5b263f8..6503d61 100644 --- a/commands.go +++ b/commands.go @@ -76,6 +76,7 @@ func (b *bot) handleFeedback(m chat1.MsgSummary) { } } +// handleSetCommand processes all settings SET calls func (b *bot) handleSetCommand(m chat1.MsgSummary) { // first normalize the text and extract the arguments args := strings.Fields(strings.ToLower(m.Content.Text.Body)) @@ -126,6 +127,7 @@ func (b *bot) handleSetCommand(m chat1.MsgSummary) { } } +// handleListCommand lists settings for the conversation func (b *bot) handleListCommand(m chat1.MsgSummary) { // first normalize the text and extract the arguments args := strings.Fields(strings.ToLower(m.Content.Text.Body)) From 0e4cf43c51db4cc17c245c1aef050ec69f93bfcd Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 17:00:36 +0000 Subject: [PATCH 17/25] added description --- utils.go | 1 + 1 file changed, 1 insertion(+) diff --git a/utils.go b/utils.go index c155fba..43a6ba4 100644 --- a/utils.go +++ b/utils.go @@ -14,6 +14,7 @@ func p(b interface{}) string { return string(s) } +// getFeedbackExtendedDescription returns the team name that feedback will be posted to, if configured func getFeedbackExtendedDescription(bc botConfig) *chat1.UserBotExtendedDescription { if bc.FeedbackTeamAdvert != "" { return &chat1.UserBotExtendedDescription{ From 755559d0bb137fddb40d51c91165dd6be0d44c4c Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 17:01:45 +0000 Subject: [PATCH 18/25] moved logging to main --- main.go | 13 ++++++++++++- utils.go | 10 ---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index 6822099..33098cb 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "log" "os" + "github.com/teris-io/shortid" "samhofi.us/x/keybase" "samhofi.us/x/keybase/types/chat1" "samhofi.us/x/keybase/types/stellar1" @@ -29,13 +30,23 @@ type botConfig struct { KVStoreTeam string `env:"BOT_KVSTORE_TEAM" envDefault:""` } -// Debug provides printing only when --debug flag is set or BOT_DEBUG env var is set +// debug provides printing only when --debug flag is set or BOT_DEBUG env var is set func (b *bot) debug(s string, a ...interface{}) { if b.config.Debug { b.log(s, a...) } } +// logError generates an error id and returns it for error reporting, and writes the error to logging locations +func (b *bot) logError(err error) string { + // generate the error id + eid := shortid.MustGenerate() + // send the error to the log + b.log("`%s` - %s", eid, err) + // then return the error id for use + return eid +} + // logToChat will send this message to the keybase chat configured in b.config.LogConvIDStr func (b *bot) log(s string, a ...interface{}) { // if the ConvIdStr isn't blank try to log to chat diff --git a/utils.go b/utils.go index 43a6ba4..f3db1ec 100644 --- a/utils.go +++ b/utils.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" - "github.com/teris-io/shortid" "samhofi.us/x/keybase/types/chat1" ) @@ -29,12 +28,3 @@ func getFeedbackExtendedDescription(bc botConfig) *chat1.UserBotExtendedDescript MobileBody: "Please note: Your feedback will be public!", } } - -func (b *bot) logError(err error) string { - // generate the error id - eid := shortid.MustGenerate() - // send the error to the log - b.log("`%s` - %s", eid, err) - // then return the error id for use - return eid -} From f30bd2a4407deea9cc47bed29675c89ab61f7a02 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 18:30:53 +0000 Subject: [PATCH 19/25] added hasCommandPrefix --- utils.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/utils.go b/utils.go index f3db1ec..c4f7771 100644 --- a/utils.go +++ b/utils.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "strings" "samhofi.us/x/keybase/types/chat1" ) @@ -28,3 +29,21 @@ func getFeedbackExtendedDescription(bc botConfig) *chat1.UserBotExtendedDescript MobileBody: "Please note: Your feedback will be public!", } } + +// hasCommandPrefix determines if the command matches either command or name variant +func hasCommandPrefix(s string, baseCommand string, botName string, subCommands string) bool { + // if this is actually a command + if strings.HasPrefix(s, "!") || strings.HasPrefix(s, "@") { + // generate the two possible command variants + botCommand := fmt.Sprintf("%s %s", baseCommand, subCommands) + nameCommand := fmt.Sprintf("%s %s", botName, subCommands) + // then remove the ! or @ from the string + s = strings.Replace(s, "!", "", 1) + s = strings.Replace(s, "@", "", 1) + // then check if either command variant is a match to the subCommands sent + if strings.HasPrefix(s, botCommand) || strings.HasPrefix(s, nameCommand) { + return true + } + } + return false +} From f475bddacd97b616c436a7dbb307d89299a3f550 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 20:29:48 +0000 Subject: [PATCH 20/25] added isRoot Command --- utils.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/utils.go b/utils.go index c4f7771..c593c21 100644 --- a/utils.go +++ b/utils.go @@ -47,3 +47,13 @@ func hasCommandPrefix(s string, baseCommand string, botName string, subCommands } return false } + +// isRootCommand determines if the command is the root command or name with no arguments +func isRootCommand(s string, baseCommand string, botName string) bool { + botCommand := fmt.Sprintf("!%s", baseCommand) + nameCommand := fmt.Sprintf("@%s", botName) + if s == botCommand || s == nameCommand { + return true + } + return false +} From a428d39fffec2163a0adae61a3710d9d1a9e879f Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 20:30:20 +0000 Subject: [PATCH 21/25] added bot.cmd() function to reliably return configured cmd --- main.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/main.go b/main.go index 33098cb..260f6f8 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,11 @@ type bot struct { config botConfig } +// this allows you to change the command the bot listens to (in additon to its username) +func (b *bot) cmd() string { + return "jitsi" +} + // botConfig hold env and cli flags and options // fields must be exported for package env (reflect) to work type botConfig struct { From 4477f62b96e60dca37df3bb674f7b135ccc58373 Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 20:30:32 +0000 Subject: [PATCH 22/25] new prettier handler --- handlers.go | 73 +++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/handlers.go b/handlers.go index d611d85..334570e 100644 --- a/handlers.go +++ b/handlers.go @@ -35,45 +35,42 @@ func (b *bot) chatHandler(m chat1.MsgSummary) { b.handlePayment(m) return } - // Determine first if this is a command + + // if its not a payment evaluate if this is a command at all if strings.HasPrefix(m.Content.Text.Body, "!") || strings.HasPrefix(m.Content.Text.Body, "@") { - // determine the root command - body := strings.ToLower(m.Content.Text.Body) - words := strings.Fields(body) - command := strings.Replace(words[0], "@", "", 1) - command = strings.Replace(command, "!", "", 1) - command = strings.ToLower(command) - // create the args - args := words[1:] - nargs := len(args) - switch command { - case b.k.Username: - if nargs > 0 { - switch args[0] { - case "set": - b.handleSetCommand(m) - case "list": - b.handleListCommand(m) - } - } - case "jitsi": - if nargs == 0 { - b.handleMeeting(m) - } else if nargs >= 1 { - switch args[0] { - case "meet": - b.handleMeeting(m) - case "feedback": - b.handleFeedback(m) - case "hello": - fallthrough - case "help": - b.handleWelcome(m.ConvID) - default: - return - } - } - default: + // first return if its not a command for me + if !strings.Contains(m.Content.Text.Body, b.cmd()) && !strings.Contains(m.Content.Text.Body, b.k.Username) { + return + } + // then check if this is the root command + if isRootCommand(m.Content.Text.Body, b.cmd(), b.k.Username) { + b.handleMeeting(m) + return + } + // then check sub-command variants + // feedback + if hasCommandPrefix(m.Content.Text.Body, b.cmd(), b.k.Username, "feedback") { + b.handleFeedback(m) + return + } + // help + if hasCommandPrefix(m.Content.Text.Body, b.cmd(), b.k.Username, "help") { + b.handleWelcome(m.ConvID) + return + } + // hello + if hasCommandPrefix(m.Content.Text.Body, b.cmd(), b.k.Username, "hello") { + b.handleWelcome(m.ConvID) + return + } + // set commands + if hasCommandPrefix(m.Content.Text.Body, b.cmd(), b.k.Username, "set") { + b.handleSetCommand(m) + return + } + // list commands + if hasCommandPrefix(m.Content.Text.Body, b.cmd(), b.k.Username, "list") { + b.handleSetCommand(m) return } } From a8b173036f5ea59b653c01470d4be4369a771e6c Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 20:33:33 +0000 Subject: [PATCH 23/25] added meet subcommand back --- handlers.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/handlers.go b/handlers.go index 334570e..3a60446 100644 --- a/handlers.go +++ b/handlers.go @@ -48,6 +48,11 @@ func (b *bot) chatHandler(m chat1.MsgSummary) { return } // then check sub-command variants + // meet + if hasCommandPrefix(m.Content.Text.Body, b.cmd(), b.k.Username, "meet") { + b.handleMeeting(m) + return + } // feedback if hasCommandPrefix(m.Content.Text.Body, b.cmd(), b.k.Username, "feedback") { b.handleFeedback(m) From 61e92f3b85e21bbcb950e8f9346c2361abdccacb Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 20:46:11 +0000 Subject: [PATCH 24/25] fixed root command to have trailing space --- utils.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils.go b/utils.go index c593c21..b618b16 100644 --- a/utils.go +++ b/utils.go @@ -50,8 +50,9 @@ func hasCommandPrefix(s string, baseCommand string, botName string, subCommands // isRootCommand determines if the command is the root command or name with no arguments func isRootCommand(s string, baseCommand string, botName string) bool { - botCommand := fmt.Sprintf("!%s", baseCommand) - nameCommand := fmt.Sprintf("@%s", botName) + // the space after is important because keybase autocompletes ! and @ with a space after + botCommand := fmt.Sprintf("!%s ", baseCommand) + nameCommand := fmt.Sprintf("@%s ", botName) if s == botCommand || s == nameCommand { return true } From 984efecf7e39db04ead5a85e3201673e704fc5cc Mon Sep 17 00:00:00 2001 From: David Haukeness Date: Tue, 31 Mar 2020 20:46:32 +0000 Subject: [PATCH 25/25] added debug and fixed indexes --- commands.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/commands.go b/commands.go index 6503d61..35b5b01 100644 --- a/commands.go +++ b/commands.go @@ -78,16 +78,17 @@ func (b *bot) handleFeedback(m chat1.MsgSummary) { // handleSetCommand processes all settings SET calls func (b *bot) handleSetCommand(m chat1.MsgSummary) { + b.debug("%s called set command in %s", m.Sender.Username, m.ConvID) // first normalize the text and extract the arguments args := strings.Fields(strings.ToLower(m.Content.Text.Body)) if args[1] != "set" { return } switch len(args) { - case 3: + case 4: if args[2] == "url" { // first validate the URL - u, err := url.ParseRequestURI(args[2]) + u, err := url.ParseRequestURI(args[3]) if err != nil { eid := b.logError(err) b.k.ReactByConvID(m.ConvID, m.Id, "Error ID %s", eid)