From 8aaae1aa9c99c265fafb605c90fc4e4a19291e87 Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 8 Sep 2020 15:28:23 -0700 Subject: [PATCH] doesn't build yet --- Dockerfile | 23 +++++ Makefile | 32 +++++++ cmd/bot/main.go | 247 ++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 3 + 4 files changed, 305 insertions(+) create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 cmd/bot/main.go create mode 100644 go.mod diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..23936e4 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +FROM golang:1.15 + +WORKDIR /go/src/app +copy . . + +RUN go get -d -v ./... +RUN go install -v ./... + +CMD ["sco"] + + + + +FROM golang:1.15 as builder +RUN mkdir /build +ADD . /build/ +WORKDIR /build +RUN make + +FROM scratch +COPY --from=builder /build/main /app/ +WORKDIR /app +CMD ["./main"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..72f3306 --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +VERSION := $(shell git rev-parse --short HEAD) +BUILDTIME := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ') +BUILDTIMEFILENAME := $(shell date -u '+%Y%m%d-%H%M%SZ') +BUILDTIMETAG := $(shell date -u '+%Y%m%d%H%M%S') +BUILDUSER := $(shell whoami) +BUILDHOST := $(shell hostname -s) +BUILDARCH := $(shell uname -m) + +FN := sco +IMAGENAME := sneak/$(FN) + +UNAME_S := $(shell uname -s) + +GOLDFLAGS += -X main.Version=$(VERSION) +GOLDFLAGS += -X main.Buildarch=$(BUILDARCH) + +# osx can't statically link apparently?! +ifeq ($(UNAME_S),Darwin) + GOFLAGS := -ldflags "$(GOLDFLAGS)" +endif + +ifneq ($(UNAME_S),Darwin) + GOFLAGS = -ldflags "-linkmode external -extldflags -static $(GOLDFLAGS)" +endif + +default: ./$(FN) + +go-get: + cd cmd/$(FN) && go get -v + +./$(FN): */*.go cmd/*/*.go go-get + cd cmd/$(FN) && go build -o ../../$(FN) $(GOFLAGS) . diff --git a/cmd/bot/main.go b/cmd/bot/main.go new file mode 100644 index 0000000..1a0c0e6 --- /dev/null +++ b/cmd/bot/main.go @@ -0,0 +1,247 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package main + +import ( + "os" + "os/signal" + "regexp" + "strings" + + "github.com/mattermost/mattermost-server/v5/model" +) + +const ( + SAMPLE_NAME = "Mattermost Bot Sample" + + USER_EMAIL = "bot@example.com" + USER_PASSWORD = "password1" + USER_NAME = "samplebot" + USER_FIRST = "Sample" + USER_LAST = "Bot" + + TEAM_NAME = "botsample" + CHANNEL_LOG_NAME = "debugging-for-sample-bot" +) + +var client *model.Client4 +var webSocketClient *model.WebSocketClient + +var botUser *model.User +var botTeam *model.Team +var debuggingChannel *model.Channel + +// Documentation for the Go driver can be found +// at https://godoc.org/github.com/mattermost/platform/model#Client +func main() { + println(SAMPLE_NAME) + + SetupGracefulShutdown() + + client = model.NewAPIv4Client("http://localhost:8065") + + // Lets test to see if the mattermost server is up and running + MakeSureServerIsRunning() + + // lets attempt to login to the Mattermost server as the bot user + // This will set the token required for all future calls + // You can get this token with client.AuthToken + LoginAsTheBotUser() + + // If the bot user doesn't have the correct information lets update his profile + UpdateTheBotUserIfNeeded() + + // Lets find our bot team + FindBotTeam() + + // This is an important step. Lets make sure we use the botTeam + // for all future web service requests that require a team. + //client.SetTeamId(botTeam.Id) + + // Lets create a bot channel for logging debug messages into + CreateBotDebuggingChannelIfNeeded() + SendMsgToDebuggingChannel("_"+SAMPLE_NAME+" has **started** running_", "") + + // Lets start listening to some channels via the websocket! + webSocketClient, err := model.NewWebSocketClient4("ws://localhost:8065", client.AuthToken) + if err != nil { + println("We failed to connect to the web socket") + PrintError(err) + } + + webSocketClient.Listen() + + go func() { + for { + select { + case resp := <-webSocketClient.EventChannel: + HandleWebSocketResponse(resp) + } + } + }() + + // You can block forever with + select {} +} + +func MakeSureServerIsRunning() { + if props, resp := client.GetOldClientConfig(""); resp.Error != nil { + println("There was a problem pinging the Mattermost server. Are you sure it's running?") + PrintError(resp.Error) + os.Exit(1) + } else { + println("Server detected and is running version " + props["Version"]) + } +} + +func LoginAsTheBotUser() { + if user, resp := client.Login(USER_EMAIL, USER_PASSWORD); resp.Error != nil { + println("There was a problem logging into the Mattermost server. Are you sure ran the setup steps from the README.md?") + PrintError(resp.Error) + os.Exit(1) + } else { + botUser = user + } +} + +func UpdateTheBotUserIfNeeded() { + if botUser.FirstName != USER_FIRST || botUser.LastName != USER_LAST || botUser.Username != USER_NAME { + botUser.FirstName = USER_FIRST + botUser.LastName = USER_LAST + botUser.Username = USER_NAME + + if user, resp := client.UpdateUser(botUser); resp.Error != nil { + println("We failed to update the Sample Bot user") + PrintError(resp.Error) + os.Exit(1) + } else { + botUser = user + println("Looks like this might be the first run so we've updated the bots account settings") + } + } +} + +func FindBotTeam() { + if team, resp := client.GetTeamByName(TEAM_NAME, ""); resp.Error != nil { + println("We failed to get the initial load") + println("or we do not appear to be a member of the team '" + TEAM_NAME + "'") + PrintError(resp.Error) + os.Exit(1) + } else { + botTeam = team + } +} + +func CreateBotDebuggingChannelIfNeeded() { + if rchannel, resp := client.GetChannelByName(CHANNEL_LOG_NAME, botTeam.Id, ""); resp.Error != nil { + println("We failed to get the channels") + PrintError(resp.Error) + } else { + debuggingChannel = rchannel + return + } + + // Looks like we need to create the logging channel + channel := &model.Channel{} + channel.Name = CHANNEL_LOG_NAME + channel.DisplayName = "Debugging For Sample Bot" + channel.Purpose = "This is used as a test channel for logging bot debug messages" + channel.Type = model.CHANNEL_OPEN + channel.TeamId = botTeam.Id + if rchannel, resp := client.CreateChannel(channel); resp.Error != nil { + println("We failed to create the channel " + CHANNEL_LOG_NAME) + PrintError(resp.Error) + } else { + debuggingChannel = rchannel + println("Looks like this might be the first run so we've created the channel " + CHANNEL_LOG_NAME) + } +} + +func SendMsgToDebuggingChannel(msg string, replyToId string) { + post := &model.Post{} + post.ChannelId = debuggingChannel.Id + post.Message = msg + + post.RootId = replyToId + + if _, resp := client.CreatePost(post); resp.Error != nil { + println("We failed to send a message to the logging channel") + PrintError(resp.Error) + } +} + +func HandleWebSocketResponse(event *model.WebSocketEvent) { + HandleMsgFromDebuggingChannel(event) +} + +func HandleMsgFromDebuggingChannel(event *model.WebSocketEvent) { + // If this isn't the debugging channel then lets ingore it + if event.Broadcast.ChannelId != debuggingChannel.Id { + return + } + + // Lets only reponded to messaged posted events + if event.Event != model.WEBSOCKET_EVENT_POSTED { + return + } + + println("responding to debugging channel msg") + + post := model.PostFromJson(strings.NewReader(event.Data["post"].(string))) + if post != nil { + + // ignore my events + if post.UserId == botUser.Id { + return + } + + // if you see any word matching 'alive' then respond + if matched, _ := regexp.MatchString(`(?:^|\W)alive(?:$|\W)`, post.Message); matched { + 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 { + 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 { + 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 { + SendMsgToDebuggingChannel("Yes I'm running", post.Id) + return + } + } + + SendMsgToDebuggingChannel("I did not understand you!", post.Id) +} + +func PrintError(err *model.AppError) { + println("\tError Details:") + println("\t\t" + err.Message) + println("\t\t" + err.Id) + println("\t\t" + err.DetailedError) +} + +func SetupGracefulShutdown() { + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + go func() { + for _ = range c { + if webSocketClient != nil { + webSocketClient.Close() + } + + SendMsgToDebuggingChannel("_"+SAMPLE_NAME+" has **stopped** running_", "") + os.Exit(0) + } + }() +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..3fe7174 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.eeqj.de/sneak/sco + +go 1.15