From 6ec52ebca92bc21ab75a99fae4a85d10204706c4 Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 8 Sep 2020 20:37:50 -0700 Subject: [PATCH 1/4] fix markdown typo on startup msg --- bot/bot.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/bot.go b/bot/bot.go index ea0333c..117b8a2 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -72,7 +72,7 @@ func (b *Bot) Main() int { // Lets create a bot channel for logging debug messages into b.CreateBotDebuggingChannelIfNeeded() - msg := fmt.Sprintf("_**%s** (version `%s`) is now starting up", b.BotName, b.Version) + msg := fmt.Sprintf("_**%s** (version `%s`) is now starting up_", b.BotName, b.Version) b.SendMsgToDebuggingChannel(msg, "") // Lets start listening to some channels via the websocket! From b8b53e8c5eab9bdae092dca5c5f3d0ee8d1b2398 Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 8 Sep 2020 20:56:24 -0700 Subject: [PATCH 2/4] add zerolog, maybe fix weather --- bot/bot.go | 40 +++++++++++++++++++++++++++++++++------- bot/logger.go | 37 +++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 4 ++++ 4 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 bot/logger.go diff --git a/bot/bot.go b/bot/bot.go index 117b8a2..30dbc5e 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -4,6 +4,8 @@ package bot import ( "fmt" "github.com/mattermost/mattermost-server/v5/model" + "github.com/rs/zerolog/log" + "io/ioutil" "net/http" "os" "os/signal" @@ -43,6 +45,14 @@ func New(options ...func(s *Bot)) *Bot { return b } +func (b *Bot) identify() { + log.Info(). + Str("version", b.Version). + Str("buildarch", b.Buildarch). + Str("commit", b.Commit). + Msg("starting") +} + func (b *Bot) Main() int { println(b.BotName) @@ -50,6 +60,8 @@ func (b *Bot) Main() int { b.SetupGracefulShutdown() + b.setupLogging() + b.client = model.NewAPIv4Client(b.APIURL) // Lets test to see if the mattermost server is up and running @@ -231,20 +243,26 @@ func (b *Bot) Shutdown() { } func (b *Bot) HandleWeatherRequest(channelid string, postid string, message string) { - msg := fmt.Sprintf("weather request received: `%s`", message) - b.SendMsgToChannel(msg, postid, channelid) + + // we are using a very bare image with no CA cert bundle + // actually if you docker bind mount the ca cert bundle in the right + // place, golang will find it and use it. + //http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + + log.Info().Msgf("weather request received: `%s`", message) r := regexp.MustCompile(`metar\s+([A-Za-z]{4})`) - loc := r.FindString(message) - if loc == "" { + matches := r.FindStringSubmatch(message) + if len(matches) < 2 { b.SendMsgToChannel("error, sorry", postid, channelid) } + loc := matches[1] + token := os.Getenv("METAR_API_TOKEN") url := fmt.Sprintf("https://avwx.rest/api/metar/%s?options=&airport=true&reporting=true&format=json&onfail=cache", loc) - msg = fmt.Sprintf("calculated url: `%s`", url) - b.SendMsgToChannel(msg, postid, channelid) + log.Info().Msgf("calculated url: `%s`", url) client := http.Client{ Timeout: 5 * time.Second, @@ -258,7 +276,15 @@ func (b *Bot) HandleWeatherRequest(channelid string, postid string, message stri return } - b.SendMsgToChannel(fmt.Sprintf("weather %s: %s", loc, resp), postid, channelid) + if resp.StatusCode != http.StatusOK { + b.SendMsgToChannel(fmt.Sprintf("weather fetch error: http status %d", resp.StatusCode), postid, channelid) + return + } + + data, _ := ioutil.ReadAll(resp.Body) + + log.Info().Msgf("weather %s: %s", loc, data) + b.SendMsgToChannel(fmt.Sprintf("weather %s: %s", loc, data), postid, channelid) } diff --git a/bot/logger.go b/bot/logger.go new file mode 100644 index 0000000..c555cf0 --- /dev/null +++ b/bot/logger.go @@ -0,0 +1,37 @@ +package bot + +import ( + "github.com/mattn/go-isatty" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "time" +) + +func (b *Bot) setupLogging() { + + log.Logger = log.With().Caller().Logger() + + tty := isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd()) + + if tty { + out := zerolog.NewConsoleWriter( + func(w *zerolog.ConsoleWriter) { + // Customize time format + w.TimeFormat = time.RFC3339 + }, + ) + log.Logger = log.Output(out) + } + + // always log in UTC + zerolog.TimestampFunc = func() time.Time { + return time.Now().UTC() + } + + zerolog.SetGlobalLevel(zerolog.DebugLevel) + //zerolog.SetGlobalLevel(zerolog.InfoLevel) + //if viper.GetBool("debug") { + //} + + b.identify() +} diff --git a/go.mod b/go.mod index a3e9867..c23596b 100644 --- a/go.mod +++ b/go.mod @@ -5,4 +5,5 @@ go 1.15 require ( github.com/kr/pretty v0.1.0 github.com/mattermost/mattermost-server/v5 v5.26.2 + github.com/rs/zerolog v1.19.0 ) diff --git a/go.sum b/go.sum index caabd46..6aae84e 100644 --- a/go.sum +++ b/go.sum @@ -443,6 +443,9 @@ github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qq github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.19.0 h1:hYz4ZVdUgjXTBUmrkrw55j1nHx68LfOKIQk5IYtyScg= +github.com/rs/zerolog v1.19.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo= github.com/rudderlabs/analytics-go v3.2.1+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30= github.com/russellhaering/goxmldsig v0.0.0-20180430223755-7acd5e4a6ef7/go.mod h1:Oz4y6ImuOQZxynhbSXk7btjEfNBtGlj2dcaOvXl2FSM= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -698,6 +701,7 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= From 0d75d4a5ac3918ec3bdc24b1df7bbb240940589c Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 8 Sep 2020 20:59:46 -0700 Subject: [PATCH 3/4] move bot commands out to own files --- bot/bot.go | 103 ++++++++++++++------------------------------------ bot/logger.go | 1 + bot/metar.go | 58 ++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 + 5 files changed, 91 insertions(+), 74 deletions(-) create mode 100644 bot/metar.go diff --git a/bot/bot.go b/bot/bot.go index 30dbc5e..447529c 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -5,8 +5,6 @@ import ( "fmt" "github.com/mattermost/mattermost-server/v5/model" "github.com/rs/zerolog/log" - "io/ioutil" - "net/http" "os" "os/signal" "regexp" @@ -242,52 +240,6 @@ func (b *Bot) Shutdown() { syscall.Kill(syscall.Getpid(), syscall.SIGINT) } -func (b *Bot) HandleWeatherRequest(channelid string, postid string, message string) { - - // we are using a very bare image with no CA cert bundle - // actually if you docker bind mount the ca cert bundle in the right - // place, golang will find it and use it. - //http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - - log.Info().Msgf("weather request received: `%s`", message) - - r := regexp.MustCompile(`metar\s+([A-Za-z]{4})`) - matches := r.FindStringSubmatch(message) - if len(matches) < 2 { - b.SendMsgToChannel("error, sorry", postid, channelid) - } - - loc := matches[1] - - token := os.Getenv("METAR_API_TOKEN") - url := fmt.Sprintf("https://avwx.rest/api/metar/%s?options=&airport=true&reporting=true&format=json&onfail=cache", loc) - - log.Info().Msgf("calculated url: `%s`", url) - - client := http.Client{ - Timeout: 5 * time.Second, - } - req, err := http.NewRequest("GET", url, nil) - req.Header.Add("Authorization", `Token `+token) - resp, err := client.Do(req) - - if err != nil { - b.SendMsgToChannel(fmt.Sprintf("weather fetch error: %s", err), postid, channelid) - return - } - - if resp.StatusCode != http.StatusOK { - b.SendMsgToChannel(fmt.Sprintf("weather fetch error: http status %d", resp.StatusCode), postid, channelid) - return - } - - data, _ := ioutil.ReadAll(resp.Body) - - log.Info().Msgf("weather %s: %s", loc, data) - b.SendMsgToChannel(fmt.Sprintf("weather %s: %s", loc, data), postid, channelid) - -} - func (b *Bot) HandleMsgFromChannel(event *model.WebSocketEvent) { post := model.PostFromJson(strings.NewReader(event.Data["post"].(string))) @@ -330,37 +282,40 @@ func (b *Bot) HandleMsgFromDebuggingChannel(event *model.WebSocketEvent) { println("responding to debugging channel msg") post := model.PostFromJson(strings.NewReader(event.Data["post"].(string))) - if post != nil { + if post == nil { + return + } - // ignore my events - if matched, _ := regexp.MatchString(`(?:^|\W)shutdown(?:$|\W)`, post.Message); matched { - b.Shutdown() - return - } + // FIXME check and see if the message from mm is a bot message, if so, + // ignore it - // if you see any word matching 'alive' then respond - if matched, _ := regexp.MatchString(`(?:^|\W)alive(?:$|\W)`, post.Message); matched { - b.SendMsgToDebuggingChannel("Yes I'm running", post.Id) - return - } + if matched, _ := regexp.MatchString(`(?:^|\W)shutdown(?:$|\W)`, post.Message); matched { + b.Shutdown() + return + } - // if you see any word matching 'up' then respond - if matched, _ := regexp.MatchString(`(?:^|\W)up(?:$|\W)`, post.Message); matched { - b.SendMsgToDebuggingChannel("Yes I'm running", post.Id) - return - } + // if you see any word matching 'alive' then respond + if matched, _ := regexp.MatchString(`(?:^|\W)alive(?:$|\W)`, post.Message); matched { + b.SendMsgToDebuggingChannel("Yes I'm running", post.Id) + return + } - // if you see any word matching 'running' then respond - if matched, _ := regexp.MatchString(`(?:^|\W)running(?:$|\W)`, post.Message); matched { - b.SendMsgToDebuggingChannel("Yes I'm running", post.Id) - return - } + // if you see any word matching 'up' then respond + if matched, _ := regexp.MatchString(`(?:^|\W)up(?:$|\W)`, post.Message); matched { + b.SendMsgToDebuggingChannel("Yes I'm running", post.Id) + return + } - // if you see any word matching 'hello' then respond - if matched, _ := regexp.MatchString(`(?:^|\W)hello(?:$|\W)`, post.Message); matched { - b.SendMsgToDebuggingChannel("Yes I'm running", post.Id) - return - } + // if you see any word matching 'running' then respond + if matched, _ := regexp.MatchString(`(?:^|\W)running(?:$|\W)`, post.Message); matched { + b.SendMsgToDebuggingChannel("Yes I'm running", post.Id) + return + } + + // if you see any word matching 'hello' then respond + if matched, _ := regexp.MatchString(`(?:^|\W)hello(?:$|\W)`, post.Message); matched { + b.SendMsgToDebuggingChannel("Yes I'm running", post.Id) + return } b.SendMsgToChannel("I did not understand your command, sorry", post.Id, post.ChannelId) diff --git a/bot/logger.go b/bot/logger.go index c555cf0..d7c4073 100644 --- a/bot/logger.go +++ b/bot/logger.go @@ -4,6 +4,7 @@ import ( "github.com/mattn/go-isatty" "github.com/rs/zerolog" "github.com/rs/zerolog/log" + "os" "time" ) diff --git a/bot/metar.go b/bot/metar.go new file mode 100644 index 0000000..cf4efc8 --- /dev/null +++ b/bot/metar.go @@ -0,0 +1,58 @@ +package bot + +//import "github.com/kr/pretty" +import ( + "fmt" + "github.com/rs/zerolog/log" + "io/ioutil" + "net/http" + "os" + "regexp" + "time" +) + +func (b *Bot) HandleWeatherRequest(channelid string, postid string, message string) { + + // we are using a very bare image with no CA cert bundle + // actually if you docker bind mount the ca cert bundle in the right + // place, golang will find it and use it. + //http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} + + log.Info().Msgf("weather request received: `%s`", message) + + r := regexp.MustCompile(`metar\s+([A-Za-z]{4})`) + matches := r.FindStringSubmatch(message) + if len(matches) < 2 { + b.SendMsgToChannel("error, sorry", postid, channelid) + } + + loc := matches[1] + + token := os.Getenv("METAR_API_TOKEN") + url := fmt.Sprintf("https://avwx.rest/api/metar/%s?options=&airport=true&reporting=true&format=json&onfail=cache", loc) + + log.Info().Msgf("calculated url: `%s`", url) + + client := http.Client{ + Timeout: 5 * time.Second, + } + req, err := http.NewRequest("GET", url, nil) + req.Header.Add("Authorization", `Token `+token) + resp, err := client.Do(req) + + if err != nil { + b.SendMsgToChannel(fmt.Sprintf("weather fetch error: %s", err), postid, channelid) + return + } + + if resp.StatusCode != http.StatusOK { + b.SendMsgToChannel(fmt.Sprintf("weather fetch error: http status %d", resp.StatusCode), postid, channelid) + return + } + + data, _ := ioutil.ReadAll(resp.Body) + + log.Info().Msgf("weather %s: %s", loc, data) + b.SendMsgToChannel(fmt.Sprintf("weather %s: %s", loc, data), postid, channelid) + +} diff --git a/go.mod b/go.mod index c23596b..27e7050 100644 --- a/go.mod +++ b/go.mod @@ -5,5 +5,6 @@ go 1.15 require ( github.com/kr/pretty v0.1.0 github.com/mattermost/mattermost-server/v5 v5.26.2 + github.com/mattn/go-isatty v0.0.12 github.com/rs/zerolog v1.19.0 ) diff --git a/go.sum b/go.sum index 6aae84e..d81c33a 100644 --- a/go.sum +++ b/go.sum @@ -332,6 +332,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -677,6 +678,7 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From cb1bdab0afbc0f52031f19209a2bef2f14c168cd Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 8 Sep 2020 21:00:37 -0700 Subject: [PATCH 4/4] add prettyprinting to figure out what's in the structur --- bot/bot.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/bot.go b/bot/bot.go index 447529c..f08c894 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -1,6 +1,6 @@ package bot -//import "github.com/kr/pretty" +import "github.com/kr/pretty" import ( "fmt" "github.com/mattermost/mattermost-server/v5/model" @@ -247,7 +247,6 @@ func (b *Bot) HandleMsgFromChannel(event *model.WebSocketEvent) { return } - //pretty.Print(post) if matched, _ := regexp.MatchString(`(?:^|\W)metar(?:$|\W)`, post.Message); matched { b.HandleWeatherRequest(post.ChannelId, post.Id, post.Message) return @@ -288,6 +287,7 @@ func (b *Bot) HandleMsgFromDebuggingChannel(event *model.WebSocketEvent) { // FIXME check and see if the message from mm is a bot message, if so, // ignore it + pretty.Print(post) if matched, _ := regexp.MatchString(`(?:^|\W)shutdown(?:$|\W)`, post.Message); matched { b.Shutdown()