Browse Source

initial working version based on a medium article

pull/1/head
rodley82 4 years ago
commit
c38ee89a69
  1. 3
      .env.example
  2. 0
      README.md
  3. 9
      go.mod
  4. 14
      go.sum
  5. 168
      main.go

3
.env.example

@ -0,0 +1,3 @@
SLACK_AUTH_TOKEN=""
SLACK_CHANNEL_ID=""
SLACK_APP_TOKEN=""

0
README.md

9
go.mod

@ -0,0 +1,9 @@
module rodleyserverbot/slack-bot
go 1.13
require (
github.com/gorilla/websocket v1.5.0 // indirect
github.com/joho/godotenv v1.4.0 // indirect
github.com/slack-go/slack v0.11.0 // indirect
)

14
go.sum

@ -0,0 +1,14 @@
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/slack-go/slack v0.11.0 h1:sBBjQz8LY++6eeWhGJNZpRm5jvLRNnWBFZ/cAq58a6k=
github.com/slack-go/slack v0.11.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

168
main.go

@ -0,0 +1,168 @@
package main
import (
"context"
"errors"
"fmt"
"log"
"os"
"strings"
"github.com/joho/godotenv"
"github.com/slack-go/slack"
"github.com/slack-go/slack/slackevents"
"github.com/slack-go/slack/socketmode"
)
func main() {
// Load Env variables from .dot file
godotenv.Load(".env")
token := os.Getenv("SLACK_AUTH_TOKEN")
appToken := os.Getenv("SLACK_APP_TOKEN")
// Create a new client to slack by giving token
// Set debug to true while developing
// Also add a ApplicationToken option to the client
client := slack.New(token, slack.OptionDebug(true), slack.OptionAppLevelToken(appToken))
// go-slack comes with a SocketMode package that we need to use that accepts a Slack client and outputs a Socket mode client instead
socketClient := socketmode.New(
client,
socketmode.OptionDebug(true),
// Option to set a custom logger
socketmode.OptionLog(log.New(os.Stdout, "socketmode: ", log.Lshortfile|log.LstdFlags)),
)
// Create a context that can be used to cancel goroutine
ctx, cancel := context.WithCancel(context.Background())
// Make this cancel called properly in a real program , graceful shutdown etc
defer cancel()
go func(ctx context.Context, client *slack.Client, socketClient *socketmode.Client) {
// Create a for loop that selects either the context cancellation or the events incomming
for {
select {
// inscase context cancel is called exit the goroutine
case <-ctx.Done():
log.Println("Shutting down socketmode listener")
return
case event := <-socketClient.Events:
// We have a new Events, let's type switch the event
// Add more use cases here if you want to listen to other events.
switch event.Type {
// handle EventInteractive events
case socketmode.EventTypeInteractive:
fmt.Println("Recivimos un Interactive!", event)
eventsInteractive, ok := event.Data.(slackevents.EventsAPICallbackEvent)
if !ok {
log.Printf("Could not type cast the event to the EventsAPICallbackEvent: %v\n", event)
continue
}
fmt.Println("Se pudo castear!!", eventsInteractive)
// handle EventAPI events
case socketmode.EventTypeEventsAPI:
// The Event sent on the channel is not the same as the EventAPI events so we need to type cast it
eventsAPIEvent, ok := event.Data.(slackevents.EventsAPIEvent)
if !ok {
log.Printf("Could not type cast the event to the EventsAPIEvent: %v\n", event)
continue
}
// We need to send an Acknowledge to the slack server
socketClient.Ack(*event.Request)
// Now we have an Events API event, but this event type can in turn be many types, so we actually need another type switch
log.Println(eventsAPIEvent)
err := handleEventMessage(eventsAPIEvent, client)
if err != nil {
// Replace with actual err handeling
log.Fatal(err)
}
}
}
}
}(ctx, client, socketClient)
socketClient.Run()
}
// handleEventMessage will take an event and handle it properly based on the type of event
func handleEventMessage(event slackevents.EventsAPIEvent, client *slack.Client) error {
switch event.Type {
// First we check if this is an CallbackEvent
case slackevents.CallbackEvent:
innerEvent := event.InnerEvent
fmt.Println("We received an event!", innerEvent)
// Yet Another Type switch on the actual Data to see if its an AppMentionEvent
switch ev := innerEvent.Data.(type) {
case *slackevents.AppMentionEvent:
// The application has been mentioned since this Event is a Mention event
log.Println(ev)
handleAppMentionEvent(ev, client)
}
default:
return errors.New("unsupported event type")
}
return nil
}
// handleAppMentionEvent is used to take care of the AppMentionEvent when the bot is mentioned
func handleAppMentionEvent(event *slackevents.AppMentionEvent, client *slack.Client) error {
// Grab the user name based on the ID of the one who mentioned the bot
user, err := client.GetUserInfo(event.User)
if err != nil {
return err
}
// Check if the user said Hello to the bot
text := strings.ToLower(event.Text)
// Create the attachment and assigned based on the message
attachment := slack.Attachment{}
// Add Some default context like user who mentioned the bot
// attachment.Fields = []slack.AttachmentField{
// {
// Title: "Date",
// Value: time.Now().String(),
// }, {
// Title: "Initializer",
// Value: user.Name,
// },
// }
attachment.CallbackID = "server_action"
if strings.Contains(text, "hello") {
// Greet the user
attachment.Text = fmt.Sprintf("Hello %s", user.Name)
attachment.Pretext = "Greetings"
attachment.Color = "#4af030"
} else {
// Send a message to the user
attachment.Text = "Por el momento esto es lo que se hacer"
attachment.Pretext = fmt.Sprintf("Como te puedo ayudar %s?", user.Name)
attachment.Color = "#3d3d3d"
powerOnAction := slack.AttachmentAction{}
powerOnAction.Name = "poweron"
powerOnAction.Text = "Encender"
powerOnAction.Value = "poweron"
powerOnAction.Type = "button"
powerOffAction := slack.AttachmentAction{}
powerOffAction.Name = "poweroff"
powerOffAction.Text = "Apagar"
powerOffAction.Value = "poweroff"
powerOffAction.Type = "button"
powerOffAction.Style = "danger"
actions := []slack.AttachmentAction{powerOnAction, powerOffAction}
fmt.Println(actions)
attachment.Actions = actions
}
// Send the message to the channel
// The Channel is available in the event message
_, _, err = client.PostMessage(event.Channel, slack.MsgOptionAttachments(attachment))
if err != nil {
return fmt.Errorf("failed to post message: %w", err)
}
return nil
}
Loading…
Cancel
Save