Skip to content

Commit

Permalink
Clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
raed-shomali committed Mar 28, 2023
1 parent de05828 commit 4a92703
Show file tree
Hide file tree
Showing 17 changed files with 586 additions and 335 deletions.
244 changes: 162 additions & 82 deletions README.md

Large diffs are not rendered by default.

51 changes: 25 additions & 26 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,74 +12,73 @@ type CommandDefinition struct {
Description string
Examples []string
BlockID string
AuthorizationFunc func(botCtx BotContext, request Request) bool
Handler func(botCtx BotContext, request Request, response ResponseWriter)
Interactive func(*Slacker, *socketmode.Event, *slack.InteractionCallback, *socketmode.Request)
AuthorizationFunc func(BotContext, Request) bool
Handler func(BotContext, Request, ResponseWriter)
Interactive func(InteractiveBotContext, *socketmode.Request, *slack.InteractionCallback)

// HideHelp will hide this command definition from appearing in the `help` results.
HideHelp bool
}

// NewBotCommand creates a new bot command object
func NewBotCommand(usage string, definition *CommandDefinition) BotCommand {
command := commander.NewCommand(usage)
return &botCommand{
// NewCommand creates a new bot command object
func NewCommand(usage string, definition *CommandDefinition) Command {
return &command{
usage: usage,
definition: definition,
command: command,
cmd: commander.NewCommand(usage),
}
}

// BotCommand interface
type BotCommand interface {
// Command interface
type Command interface {
Usage() string
Definition() *CommandDefinition

Match(text string) (*proper.Properties, bool)
Match(string) (*proper.Properties, bool)
Tokenize() []*commander.Token
Execute(botCtx BotContext, request Request, response ResponseWriter)
Interactive(*Slacker, *socketmode.Event, *slack.InteractionCallback, *socketmode.Request)
Execute(BotContext, Request, ResponseWriter)
Interactive(InteractiveBotContext, *socketmode.Request, *slack.InteractionCallback)
}

// botCommand structure contains the bot's command, description and handler
type botCommand struct {
// command structure contains the bot's command, description and handler
type command struct {
usage string
definition *CommandDefinition
command *commander.Command
cmd *commander.Command
}

// Usage returns the command usage
func (c *botCommand) Usage() string {
func (c *command) Usage() string {
return c.usage
}

// Description returns the command description
func (c *botCommand) Definition() *CommandDefinition {
// Definition returns the command definition
func (c *command) Definition() *CommandDefinition {
return c.definition
}

// Match determines whether the bot should respond based on the text received
func (c *botCommand) Match(text string) (*proper.Properties, bool) {
return c.command.Match(text)
func (c *command) Match(text string) (*proper.Properties, bool) {
return c.cmd.Match(text)
}

// Tokenize returns the command format's tokens
func (c *botCommand) Tokenize() []*commander.Token {
return c.command.Tokenize()
func (c *command) Tokenize() []*commander.Token {
return c.cmd.Tokenize()
}

// Execute executes the handler logic
func (c *botCommand) Execute(botCtx BotContext, request Request, response ResponseWriter) {
func (c *command) Execute(botCtx BotContext, request Request, response ResponseWriter) {
if c.definition == nil || c.definition.Handler == nil {
return
}
c.definition.Handler(botCtx, request, response)
}

// Interactive executes the interactive logic
func (c *botCommand) Interactive(slacker *Slacker, evt *socketmode.Event, callback *slack.InteractionCallback, req *socketmode.Request) {
func (c *command) Interactive(botContext InteractiveBotContext, request *socketmode.Request, callback *slack.InteractionCallback) {
if c.definition == nil || c.definition.Interactive == nil {
return
}
c.definition.Interactive(slacker, evt, callback, req)
c.definition.Interactive(botContext, request, callback)
}
103 changes: 88 additions & 15 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,24 @@ import (
"github.com/slack-go/slack/socketmode"
)

// A BotContext interface is used to respond to an event
// BotContext interface is for bot command contexts
type BotContext interface {
Context() context.Context
Event() *MessageEvent
SocketMode() *socketmode.Client
Client() *slack.Client
ApiClient() *slack.Client
SocketModeClient() *socketmode.Client
}

// NewBotContext creates a new bot context
func NewBotContext(ctx context.Context, client *slack.Client, socketmode *socketmode.Client, evt *MessageEvent) BotContext {
return &botContext{ctx: ctx, event: evt, client: client, socketmode: socketmode}
func NewBotContext(ctx context.Context, apiClient *slack.Client, socketModeClient *socketmode.Client, event *MessageEvent) BotContext {
return &botContext{ctx: ctx, event: event, apiClient: apiClient, socketModeClient: socketModeClient}
}

type botContext struct {
ctx context.Context
event *MessageEvent
client *slack.Client
socketmode *socketmode.Client
ctx context.Context
event *MessageEvent
apiClient *slack.Client
socketModeClient *socketmode.Client
}

// Context returns the context
Expand All @@ -37,12 +37,85 @@ func (r *botContext) Event() *MessageEvent {
return r.event
}

// SocketMode returns the SocketMode client
func (r *botContext) SocketMode() *socketmode.Client {
return r.socketmode
// ApiClient returns the slack API client
func (r *botContext) ApiClient() *slack.Client {
return r.apiClient
}

// Client returns the slack client
func (r *botContext) Client() *slack.Client {
return r.client
// SocketModeClient returns the slack socket mode client
func (r *botContext) SocketModeClient() *socketmode.Client {
return r.socketModeClient
}

// InteractiveBotContext interface is interactive bot command contexts
type InteractiveBotContext interface {
Context() context.Context
Event() *socketmode.Event
ApiClient() *slack.Client
SocketModeClient() *socketmode.Client
}

// NewInteractiveBotContext creates a new interactive bot context
func NewInteractiveBotContext(ctx context.Context, apiClient *slack.Client, socketModeClient *socketmode.Client, event *socketmode.Event) InteractiveBotContext {
return &interactiveBotContext{ctx: ctx, event: event, apiClient: apiClient, socketModeClient: socketModeClient}
}

type interactiveBotContext struct {
ctx context.Context
event *socketmode.Event
apiClient *slack.Client
socketModeClient *socketmode.Client
}

// Context returns the context
func (r *interactiveBotContext) Context() context.Context {
return r.ctx
}

// Event returns the socket event
func (r *interactiveBotContext) Event() *socketmode.Event {
return r.event
}

// ApiClient returns the slack API client
func (r *interactiveBotContext) ApiClient() *slack.Client {
return r.apiClient
}

// SocketModeClient returns the slack socket mode client
func (r *interactiveBotContext) SocketModeClient() *socketmode.Client {
return r.socketModeClient
}

// JobContext interface is for job command contexts
type JobContext interface {
Context() context.Context
ApiClient() *slack.Client
SocketModeClient() *socketmode.Client
}

// NewJobContext creates a new bot context
func NewJobContext(ctx context.Context, apiClient *slack.Client, socketModeClient *socketmode.Client) JobContext {
return &jobContext{ctx: ctx, apiClient: apiClient, socketModeClient: socketModeClient}
}

type jobContext struct {
ctx context.Context
apiClient *slack.Client
socketModeClient *socketmode.Client
}

// Context returns the context
func (r *jobContext) Context() context.Context {
return r.ctx
}

// ApiClient returns the slack API client
func (r *jobContext) ApiClient() *slack.Client {
return r.apiClient
}

// SocketModeClient returns the slack socket mode client
func (r *jobContext) SocketModeClient() *socketmode.Client {
return r.socketModeClient
}
10 changes: 4 additions & 6 deletions defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ func WithDebug(debug bool) ClientOption {
}
}

// WithBotInteractionMode instructs Slacker on how to handle message events coming from a
// bot.
// WithBotInteractionMode instructs Slacker on how to handle message events coming from a bot.
func WithBotInteractionMode(mode BotInteractionMode) ClientOption {
return func(defaults *ClientDefaults) {
defaults.BotMode = mode
Expand Down Expand Up @@ -91,15 +90,14 @@ type ReportErrorDefaults struct {
ThreadResponse bool
}

// WithThreadError specifies the reply to be inside a thread of the original message
func WithThreadError(useThread bool) ReportErrorOption {
// WithThreadReplyError specifies the reply to be inside a thread of the original message
func WithThreadReplyError(useThread bool) ReportErrorOption {
return func(defaults *ReportErrorDefaults) {
defaults.ThreadResponse = useThread
}
}

// NewReportErrorDefaults builds our ReportErrorDefaults from zero or more
// ReportErrorOption.
// NewReportErrorDefaults builds our ReportErrorDefaults from zero or more ReportErrorOption.
func NewReportErrorDefaults(options ...ReportErrorOption) *ReportErrorDefaults {
config := &ReportErrorDefaults{
ThreadResponse: false,
Expand Down
10 changes: 5 additions & 5 deletions examples/10/example10.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type MyCustomResponseWriter struct {
func (r *MyCustomResponseWriter) ReportError(err error, options ...slacker.ReportErrorOption) {
defaults := slacker.NewReportErrorDefaults(options...)

client := r.botCtx.Client()
apiClient := r.botCtx.ApiClient()
event := r.botCtx.Event()

opts := []slack.MsgOption{
Expand All @@ -63,7 +63,7 @@ func (r *MyCustomResponseWriter) ReportError(err error, options ...slacker.Repor
opts = append(opts, slack.MsgOptionTS(event.TimeStamp))
}

_, _, err = client.PostMessage(event.Channel, opts...)
_, _, err = apiClient.PostMessage(event.ChannelID, opts...)
if err != nil {
fmt.Printf("failed to report error: %v\n", err)
}
Expand All @@ -75,14 +75,14 @@ func (r *MyCustomResponseWriter) Reply(message string, options ...slacker.ReplyO
if ev == nil {
return fmt.Errorf("unable to get message event details")
}
return r.Post(ev.Channel, message, options...)
return r.Post(ev.ChannelID, message, options...)
}

// Post send a message to a channel
func (r *MyCustomResponseWriter) Post(channel string, message string, options ...slacker.ReplyOption) error {
defaults := slacker.NewReplyDefaults(options...)

client := r.botCtx.Client()
apiClient := r.botCtx.ApiClient()
ev := r.botCtx.Event()
if ev == nil {
return fmt.Errorf("unable to get message event details")
Expand All @@ -98,7 +98,7 @@ func (r *MyCustomResponseWriter) Post(channel string, message string, options ..
opts = append(opts, slack.MsgOptionTS(ev.TimeStamp))
}

_, _, err := client.PostMessage(
_, _, err := apiClient.PostMessage(
channel,
opts...,
)
Expand Down
5 changes: 3 additions & 2 deletions examples/11/example11.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package main

import (
"context"
"github.com/shomali11/slacker"
"log"
"os"

"github.com/shomali11/slacker"
)

func main() {
bot := slacker.NewClient(os.Getenv("SLACK_BOT_TOKEN"), os.Getenv("SLACK_APP_TOKEN"))
bot := slacker.NewClient(os.Getenv("SLACK_BOT_TOKEN"), os.Getenv("SLACK_APP_TOKEN"), slacker.WithDebug(true))

definition := &slacker.CommandDefinition{
Description: "Ping!",
Expand Down
22 changes: 18 additions & 4 deletions examples/12/example12.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,33 @@ import (
func main() {
bot := slacker.NewClient(os.Getenv("SLACK_BOT_TOKEN"), os.Getenv("SLACK_APP_TOKEN"))

authorizedUsers := []string{"<User ID>"}
authorizedUserIds := []string{"<User ID>"}
authorizedUserNames := []string{"shomali11"}

authorizedDefinition := &slacker.CommandDefinition{
authorizedDefinitionById := &slacker.CommandDefinition{
Description: "Very secret stuff",
Examples: []string{"secret-id"},
AuthorizationFunc: func(botCtx slacker.BotContext, request slacker.Request) bool {
return contains(authorizedUsers, botCtx.Event().User)
return contains(authorizedUserIds, botCtx.Event().UserID)
},
Handler: func(botCtx slacker.BotContext, request slacker.Request, response slacker.ResponseWriter) {
response.Reply("You are authorized!")
},
}

bot.Command("secret", authorizedDefinition)
authorizedDefinitionByName := &slacker.CommandDefinition{
Description: "Very secret stuff",
Examples: []string{"secret-name"},
AuthorizationFunc: func(botCtx slacker.BotContext, request slacker.Request) bool {
return contains(authorizedUserNames, botCtx.Event().UserProfile.DisplayName)
},
Handler: func(botCtx slacker.BotContext, request slacker.Request, response slacker.ResponseWriter) {
response.Reply("You are authorized!")
},
}

bot.Command("secret-id", authorizedDefinitionById)
bot.Command("secret-name", authorizedDefinitionByName)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand Down
15 changes: 8 additions & 7 deletions examples/15/example15.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ package main

import (
"context"
"github.com/shomali11/slacker"
"github.com/slack-go/slack"
"github.com/slack-go/slack/socketmode"
"log"
"os"

"github.com/shomali11/slacker"
"github.com/slack-go/slack"
)

func main() {
bot := slacker.NewClient(os.Getenv("SLACK_BOT_TOKEN"), os.Getenv("SLACK_APP_TOKEN"))

bot.Interactive(func(s *slacker.Slacker, event *socketmode.Event, callback *slack.InteractionCallback) {
bot.Interactive(func(botCtx slacker.InteractiveBotContext, callback *slack.InteractionCallback) {
if callback.Type != slack.InteractionTypeBlockActions {
return
}
Expand All @@ -36,10 +36,10 @@ func main() {
text = "I don't understand your mood..."
}

_, _, _ = s.Client().PostMessage(callback.Channel.ID, slack.MsgOptionText(text, false),
_, _, _ = botCtx.ApiClient().PostMessage(callback.Channel.ID, slack.MsgOptionText(text, false),
slack.MsgOptionReplaceOriginal(callback.ResponseURL))

s.SocketMode().Ack(*event.Request)
botCtx.SocketModeClient().Ack(*botCtx.Event().Request)
})

definition := &slacker.CommandDefinition{
Expand All @@ -53,8 +53,9 @@ func main() {
slack.NewSectionBlock(slack.NewTextBlockObject(slack.PlainTextType, "What is your mood today?", true, false), nil, nil),
slack.NewActionBlock("mood-block", happyBtn, sadBtn),
}))

if err != nil {
panic(err)
response.ReportError(err)
}
},
}
Expand Down
Loading

0 comments on commit 4a92703

Please sign in to comment.