Skip to content
This repository has been archived by the owner on Jan 3, 2023. It is now read-only.

Commit

Permalink
add command/component/modal checks & translation stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
topi314 committed Jul 25, 2022
1 parent 45a879c commit 9f8a84a
Show file tree
Hide file tree
Showing 15 changed files with 302 additions and 73 deletions.
31 changes: 15 additions & 16 deletions _example/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@ package main

import (
"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/disgoorg/handler"
)

func TestCommand(b *Bot) handler.Command {
return handler.Command{
Create: discord.SlashCommandCreate{
CommandName: "test",
Name: "test",
Description: "Test command",
Options: []discord.ApplicationCommandOption{
discord.ApplicationCommandOptionSubCommand{
CommandName: "test1",
Name: "test1",
Description: "Test command 1",
},
discord.ApplicationCommandOptionSubCommandGroup{
GroupName: "test",
Name: "test",
Description: "Test command 1",
Options: []discord.ApplicationCommandOptionSubCommand{
{
CommandName: "test2",
Name: "test2",
Description: "Test command 2",
},
},
Expand All @@ -30,22 +29,22 @@ func TestCommand(b *Bot) handler.Command {
},
Check: simpleCommandCheck(b),
CommandHandlers: map[string]handler.CommandHandler{
"test1": func(e *events.ApplicationCommandInteractionCreate) error {
b.Logger.Info("Test command 1")
"test1": func(ctx *handler.CommandContext) error {
b.Logger.Info(ctx.Printer.Sprintf("commands.test1"))

return e.CreateMessage(discord.MessageCreate{
Content: "test1",
return ctx.CreateMessage(discord.MessageCreate{
Content: ctx.Printer.Sprintf("commands.test1"),
Components: []discord.ContainerComponent{
discord.ActionRowComponent{
discord.NewPrimaryButton("test1", "handler:test"),
},
},
})
},
"test/test2": func(e *events.ApplicationCommandInteractionCreate) error {
b.Logger.Info("Test command 2")
"test/test2": func(ctx *handler.CommandContext) error {
b.Logger.Info(ctx.Printer.Sprintf("commands.test2"))

return e.CreateModal(discord.ModalCreate{
return ctx.CreateModal(discord.ModalCreate{
CustomID: "handler:test",
Title: "Test Modal",
Components: []discord.ContainerComponent{
Expand All @@ -59,9 +58,9 @@ func TestCommand(b *Bot) handler.Command {
}
}

func simpleCommandCheck(b *Bot) func(e *events.ApplicationCommandInteractionCreate) bool {
return func(e *events.ApplicationCommandInteractionCreate) bool {
b.Logger.Info("Simple command check")
return e.User().ID == userID
func simpleCommandCheck(b *Bot) func(ctx *handler.CommandContext) bool {
return func(ctx *handler.CommandContext) bool {
b.Logger.Info(ctx.Printer.Sprintf("checks.command"))
return ctx.User().ID == userID
}
}
19 changes: 13 additions & 6 deletions _example/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@ package main

import (
"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/disgoorg/handler"
)

func TestComponent(b *Bot) handler.Component {
return handler.Component{
Name: "test",
Handler: func(args []string, e *events.ComponentInteractionCreate) error {
b.Logger.Info("test component")
return e.CreateMessage(discord.MessageCreate{
Content: "test button",
Name: "test",
Check: simpleComponentCheck(b),
Handler: func(ctx *handler.ComponentContext) error {
b.Logger.Info(ctx.Printer.Sprintf("components.test"))
return ctx.CreateMessage(discord.MessageCreate{
Content: ctx.Printer.Sprintf("checks.component"),
})
},
}
}

func simpleComponentCheck(b *Bot) func(ctx *handler.ComponentContext) bool {
return func(ctx *handler.ComponentContext) bool {
b.Logger.Info(ctx.Printer.Sprintf("checks.component"))
return ctx.User().ID == userID
}
}
21 changes: 21 additions & 0 deletions _example/languages/de.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"checks": {
"command": "DE: Command Check",
"autocomplete": "DE: Autocomplete Check",
"component": "DE: Component Check",
"modal": "DE: Modal Check"
},
"commands": {
"test1": "DE: Test Command 1",
"test2": "DE: Test Command 2"
},
"autocompletes": {
"test": "DE: Autocomplete Test"
},
"modals": {
"test": "DE: Modal Test"
},
"components": {
"test": "DE: Component Test"
}
}
21 changes: 21 additions & 0 deletions _example/languages/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"checks": {
"command": "EN: Command Check",
"autocomplete": "EN: Autocomplete Check",
"component": "EN: Component Check",
"modal": "EN: Modal Check"
},
"commands": {
"test1": "EN: Test Command 1",
"test2": "EN: Test Command 2"
},
"autocompletes": {
"test": "EN: Autocomplete Test"
},
"modals": {
"test": "EN: Modal Test"
},
"components": {
"test": "EN: Component Test"
}
}
10 changes: 10 additions & 0 deletions _example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"context"
"embed"
"os"
"os/signal"
"syscall"
Expand All @@ -11,13 +12,17 @@ import (
"github.com/disgoorg/handler"
"github.com/disgoorg/log"
"github.com/disgoorg/snowflake/v2"
"golang.org/x/text/language"
)

var (
token = os.Getenv("TOKEN")
userID = snowflake.GetEnv("USER_ID")
)

//go:embed languages/*.json
var languages embed.FS

type Bot struct {
Logger log.Logger
Client bot.Client
Expand All @@ -36,6 +41,11 @@ func main() {
h.AddComponents(TestComponent(testBot))
h.AddModals(TestModal(testBot))

h.InitI18n(language.English)
if err := h.I18n.LoadFromEmbedFS(languages, "languages"); err != nil {
logger.Fatal("Failed to load languages: ", err)
}

var err error
if testBot.Client, err = disgo.New(token,
bot.WithLogger(logger),
Expand Down
19 changes: 13 additions & 6 deletions _example/modals.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@ import (
"fmt"

"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events"
"github.com/disgoorg/handler"
)

func TestModal(b *Bot) handler.Modal {
return handler.Modal{
Name: "test",
Handler: func(args []string, e *events.ModalSubmitInteractionCreate) error {
b.Logger.Info("test modal")
return e.CreateMessage(discord.MessageCreate{
Content: fmt.Sprintf("test modal: %s", e.Data.Text("test-input")),
Name: "test",
Check: simpleModalCheck(b),
Handler: func(ctx *handler.ModalContext) error {
b.Logger.Info(ctx.Printer.Sprintf("modals.test"))
return ctx.CreateMessage(discord.MessageCreate{
Content: fmt.Sprintf("test modal: %s", ctx.Data.Text("test-input")),
})
},
}
}

func simpleModalCheck(b *Bot) func(ctx *handler.ModalContext) bool {
return func(ctx *handler.ModalContext) bool {
b.Logger.Info(ctx.Printer.Sprintf("checks.modal"))
return ctx.User().ID == userID
}
}
31 changes: 31 additions & 0 deletions check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package handler

type Check[T any] func(ctx T) bool

func (c Check[T]) Or(check Check[T]) Check[T] {
return func(ctx T) bool {
return c(ctx) || check(ctx)
}
}

func (c Check[T]) And(check Check[T]) Check[T] {
return func(ctx T) bool {
return c(ctx) && check(ctx)
}
}

func CheckAnyOf[T any](checks ...Check[T]) Check[T] {
var check Check[T]
for _, c := range checks {
check = check.Or(c)
}
return check
}

func CheckAllOf[T any](checks ...Check[T]) Check[T] {
var check Check[T]
for _, c := range checks {
check = check.And(c)
}
return check
}
57 changes: 21 additions & 36 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,55 +6,31 @@ import (
)

type (
CommandHandler func(e *events.ApplicationCommandInteractionCreate) error
AutocompleteHandler func(e *events.AutocompleteInteractionCreate) error
CommandHandler func(ctx *CommandContext) error
AutocompleteHandler func(ctx *AutocompleteContext) error
)

type Command struct {
Create discord.ApplicationCommandCreate
Check CommandCheck
Check Check[*CommandContext]
AutocompleteCheck Check[*AutocompleteContext]
CommandHandlers map[string]CommandHandler
AutocompleteHandlers map[string]AutocompleteHandler
}

type CommandCheck func(e *events.ApplicationCommandInteractionCreate) bool

func (c CommandCheck) Or(check CommandCheck) CommandCheck {
return func(e *events.ApplicationCommandInteractionCreate) bool {
return c(e) || check(e)
}
}

func (c CommandCheck) And(check CommandCheck) CommandCheck {
return func(e *events.ApplicationCommandInteractionCreate) bool {
return c(e) && check(e)
}
}

func CommandCheckAnyOf(checks ...CommandCheck) CommandCheck {
var check CommandCheck
for _, c := range checks {
check = check.Or(c)
}
return check
}

func CommandCheckAllOf(checks ...CommandCheck) CommandCheck {
var check CommandCheck
for _, c := range checks {
check = check.And(c)
}
return check
}

func (h *Handler) handleCommand(e *events.ApplicationCommandInteractionCreate) {
name := e.Data.CommandName()
cmd, ok := h.Commands[name]
if !ok || cmd.CommandHandlers == nil {
h.Logger.Errorf("No command or handler found for \"%s\"", name)
}

if cmd.Check != nil && !cmd.Check(e) {
ctx := &CommandContext{
ApplicationCommandInteractionCreate: e,
Printer: h.I18n.NewPrinter(e.Locale()),
}

if cmd.Check != nil && !cmd.Check(ctx) {
return
}

Expand All @@ -69,7 +45,7 @@ func (h *Handler) handleCommand(e *events.ApplicationCommandInteractionCreate) {
return
}

if err := handler(e); err != nil {
if err := handler(ctx); err != nil {
h.Logger.Errorf("Failed to handle command \"%s\" with path \"%s\": %s", name, path, err)
}
}
Expand All @@ -81,6 +57,15 @@ func (h *Handler) handleAutocomplete(e *events.AutocompleteInteractionCreate) {
h.Logger.Errorf("No command or handler found for \"%s\"", name)
}

ctx := &AutocompleteContext{
AutocompleteInteractionCreate: e,
Printer: h.I18n.NewPrinter(e.Locale()),
}

if cmd.AutocompleteCheck != nil && !cmd.AutocompleteCheck(ctx) {
return
}

path := buildCommandPath(e.Data.SubCommandName, e.Data.SubCommandGroupName)

handler, ok := cmd.AutocompleteHandlers[path]
Expand All @@ -89,7 +74,7 @@ func (h *Handler) handleAutocomplete(e *events.AutocompleteInteractionCreate) {
return
}

if err := handler(e); err != nil {
if err := handler(ctx); err != nil {
h.Logger.Errorf("Failed to handle autocomplete for command \"%s\" with path \"%s\": %s", name, path, err)
}
}
Expand Down
15 changes: 13 additions & 2 deletions component.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import (
"github.com/disgoorg/disgo/events"
)

type ComponentHandler func(args []string, e *events.ComponentInteractionCreate) error
type ComponentHandler func(ctx *ComponentContext) error

type Component struct {
Name string
Check Check[*ComponentContext]
Handler ComponentHandler
}

Expand All @@ -26,7 +27,17 @@ func (h *Handler) handleComponent(e *events.ComponentInteractionCreate) {
h.Logger.Errorf("No component handler for \"%s\" found", componentName)
}

if err := component.Handler(args[2:], e); err != nil {
ctx := &ComponentContext{
ComponentInteractionCreate: e,
Printer: h.I18n.NewPrinter(e.Locale()),
Args: args[2:],
}

if component.Check != nil && !component.Check(ctx) {
return
}

if err := component.Handler(ctx); err != nil {
h.Logger.Errorf("Failed to handle component interaction for \"%s\" : %s", componentName, err)
}
}
Loading

0 comments on commit 9f8a84a

Please sign in to comment.