commit
c38ee89a69
5 changed files with 194 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||
SLACK_AUTH_TOKEN="" |
|||
SLACK_CHANNEL_ID="" |
|||
SLACK_APP_TOKEN="" |
|||
@ -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 |
|||
) |
|||
@ -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= |
|||
@ -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…
Reference in new issue