Skip to content

Commit

Permalink
buttons, show them off in moderate-myself/
Browse files Browse the repository at this point in the history
  • Loading branch information
Karitham committed Dec 24, 2021
1 parent 7121298 commit e917c27
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 25 deletions.
114 changes: 101 additions & 13 deletions _example/moderate-myself/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"log"
"os"
"strings"
"sync"

"github.com/Karitham/corde"
)
Expand Down Expand Up @@ -51,9 +51,14 @@ func main() {

g := corde.GuildOpt(corde.SnowflakeFromString(os.Getenv("DISCORD_GUILD_ID")))

mu := &sync.Mutex{}
selectedID := 0

m := corde.NewMux(pk, appID, token)
m.SetRoute(corde.SlashCommand("cmd/list"), list(m, g))
m.SetRoute(corde.SlashCommand("cmd/remove"), rm(m, g))
m.SetRoute(corde.ButtonInteraction("btn-cmd/list/next"), btnNext(m, g, mu, &selectedID))
m.SetRoute(corde.ButtonInteraction("btn-cmd/list/remove"), btnRemove(m, g, mu, &selectedID))

if err := m.RegisterCommand(command, g); err != nil {
log.Fatalln("error registering command: ", err)
Expand All @@ -66,19 +71,23 @@ func main() {

func list(m *corde.Mux, g func(*corde.CommandsOpt)) func(corde.ResponseWriter, *corde.Interaction) {
return func(w corde.ResponseWriter, i *corde.Interaction) {
c, _ := m.GetCommands(g)

w.WithSource(&corde.InteractionRespData{
Content: func() string {
s := &strings.Builder{}
s.WriteString("```\n")
for _, c := range c {
s.WriteString(fmt.Sprintf("%s: %s\n", c.Name, c.Description))
}
s.WriteString("```")
return s.String()
}(),
Flags: corde.RESPONSE_FLAGS_EPHEMERAL,
Components: []corde.Component{
{
Type: corde.COMPONENT_ACTION_ROW,
Components: []corde.Component{
{
Type: corde.COMPONENT_BUTTON,
CustomID: "btn-cmd/list/next",
Style: corde.BUTTON_SECONDARY,
Label: "next",
Emoji: &corde.Emoji{Name: "➡️"},
},
},
},
},
Content: fmt.Sprintf("Click on the buttons to move between existing commands and or delete them."),
Flags: corde.RESPONSE_FLAGS_EPHEMERAL,
})
}
}
Expand Down Expand Up @@ -113,3 +122,82 @@ func rm(m *corde.Mux, g func(*corde.CommandsOpt)) func(corde.ResponseWriter, *co
})
}
}

func btnNext(m *corde.Mux, g func(*corde.CommandsOpt), mu *sync.Mutex, selectedID *int) func(corde.ResponseWriter, *corde.Interaction) {
return func(w corde.ResponseWriter, i *corde.Interaction) {
mu.Lock()
defer mu.Unlock()
commands, _ := m.GetCommands(g)
if len(commands) == 0 {
w.UpdateMessage(&corde.InteractionRespData{
Content: "No commands found.",
Flags: corde.RESPONSE_FLAGS_EPHEMERAL,
})
return
}
*selectedID = *selectedID + 1%(len(commands))

w.UpdateMessage(&corde.InteractionRespData{
Content: fmt.Sprintf("%s - %s", commands[*selectedID].Name, commands[*selectedID].Description),
Components: []corde.Component{
{
Type: corde.COMPONENT_ACTION_ROW,
Components: []corde.Component{
{
Type: corde.COMPONENT_BUTTON,
CustomID: "btn-cmd/list/next",
Style: corde.BUTTON_SECONDARY,
Label: "next",
Emoji: &corde.Emoji{Name: "➡️"},
},
{
Type: corde.COMPONENT_BUTTON,
CustomID: "btn-cmd/list/remove",
Style: corde.BUTTON_DANGER,
Label: "remove",
Emoji: &corde.Emoji{Name: "🗑️"},
},
},
},
},
Flags: corde.RESPONSE_FLAGS_EPHEMERAL,
})
}
}

func btnRemove(m *corde.Mux, g func(*corde.CommandsOpt), mu *sync.Mutex, selectedID *int) func(corde.ResponseWriter, *corde.Interaction) {
return func(w corde.ResponseWriter, i *corde.Interaction) {
mu.Lock()
defer mu.Unlock()
commands, _ := m.GetCommands(g)
c := commands[*selectedID]

m.DeleteCommand(c.ID, g)

w.UpdateMessage(&corde.InteractionRespData{
Content: fmt.Sprintf("%s - %s", commands[*selectedID].Name, commands[*selectedID].Description),
Components: []corde.Component{
{
Type: corde.COMPONENT_ACTION_ROW,
Components: []corde.Component{
{
Type: corde.COMPONENT_BUTTON,
CustomID: "btn-cmd/list/next",
Style: corde.BUTTON_SECONDARY,
Label: "next",
Emoji: &corde.Emoji{Name: "➡️"},
},
{
Type: corde.COMPONENT_BUTTON,
CustomID: "btn-cmd/list/remove",
Style: corde.BUTTON_DANGER,
Label: "remove",
Emoji: &corde.Emoji{Name: "🗑️"},
},
},
},
},
Flags: corde.RESPONSE_FLAGS_EPHEMERAL,
})
}
}
65 changes: 65 additions & 0 deletions components.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package corde

type ButtonStyle int

const (
BUTTON_PRIMARY ButtonStyle = iota + 1
BUTTON_SECONDARY
BUTTON_SUCCESS
BUTTON_DANGER
BUTTON_LINK
)

// ComponentType
// https://discord.com/developers/docs/interactions/message-components#button-object
type ComponentType int

const (
COMPONENT_ACTION_ROW ComponentType = iota + 1
COMPONENT_BUTTON
COMPONENT_SELECT_MENU
)

// Component
// https://discord.com/developers/docs/interactions/message-components#component-object-component-types
type Component struct {
Type ComponentType `json:"type"`
CustomID string `json:"custom_id,omitempty"`
Style ButtonStyle `json:"style,omitempty"`
Disabled bool `json:"disabled,omitempty"`
Label string `json:"label,omitempty"`
Emoji *Emoji `json:"emoji,omitempty"`
URL string `json:"url,omitempty"`
Placeholder string `json:"placeholder,omitempty"`
MinValues int `json:"min_values,omitempty"`
MaxValues int `json:"max_values,omitempty"`
Options []Option `json:"options,omitempty"`
Components []Component `json:"components,omitempty"`
}

// SelectOption
// https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-option-structure
type SelectOption struct {
Label string `json:"label"`
Value string `json:"value"`
Description string `json:"description,omitempty"`
Emoji *Emoji `json:"emoji,omitempty"`
Default bool `json:"default,omitempty"`
}

// Button
// https://discord.com/developers/docs/interactions/message-components#button-object
type Button struct {
Type ComponentType `json:"type"`
Style ButtonStyle `json:"style"`
Label string `json:"label,omitempty"`
Emoji Emoji `json:"emoji,omitempty"`
CustomID string `json:"custom_id,omitempty"`
URL string `json:"url,omitempty"`
Disabled bool `json:"disabled,omitempty"`
}

type Emoji struct {
ID Snowflake `json:"id"`
Name string `json:"name"`
}
7 changes: 1 addition & 6 deletions interaction-responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type InteractionRespData struct {
Embeds []Embed `json:"embeds,omitempty"`
AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"`
Flags IntResponseFlags `json:"flags,omitempty"`
Components []Component `json:"components,omitempty"`
Attachements []Attachment `json:"attachments,omitempty"`
}

Expand Down Expand Up @@ -84,12 +85,6 @@ type MessageReference struct {
MessageID string `json:"message_id"`
}

type Attachments struct {
ID int `json:"id"`
Description string `json:"description"`
Filename string `json:"filename"`
}

// Opt returns a ptr to the type
func Opt[T any](t T) *T {
return &t
Expand Down
31 changes: 28 additions & 3 deletions interactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ type Interaction struct {
GuildID Snowflake `json:"guild_id"`
ChannelID Snowflake `json:"channel_id"`
Member Member `json:"member"`
Message string `json:"message"`
Message Message `json:"message"`
ApplicationID Snowflake `json:"application_id"`
ID Snowflake `json:"id"`
Token string `json:"token"`
Expand All @@ -68,14 +68,39 @@ type Interaction struct {
Version int `json:"version"`
}

type Message struct {
Type int `json:"type"`
Tts bool `json:"tts"`
Timestamp time.Time `json:"timestamp"`
Pinned bool `json:"pinned"`
MentionEveryone bool `json:"mention_everyone"`
ID string `json:"id"`
Flags int `json:"flags"`
Embeds []Embed `json:"embeds"`
EditedTimestamp *time.Time `json:"edited_timestamp"`
Content string `json:"content"`
Components []Component `json:"components"`
ChannelID string `json:"channel_id"`
Author Author `json:"author"`
Attachments []Attachment `json:"attachments"`
}

type MessageAuthor struct {
Username string `json:"username"`
PublicFlags int `json:"public_flags"`
ID string `json:"id"`
Discriminator string `json:"discriminator"`
Avatar string `json:"avatar"`
}

type InteractionData struct {
ID Snowflake `json:"id"`
Name string `json:"name"`
Type int `json:"type"`
Resolved any `json:"resolved"` // ?
Options OptionsInteractions `json:"options"`
CustomID Snowflake `json:"custom_id"`
ComponentType int `json:"component_type"`
CustomID string `json:"custom_id"`
ComponentType ComponentType `json:"component_type"`
Values []any `json:"values"` // ?
TagetID Snowflake `json:"target_id"`
}
Expand Down
27 changes: 24 additions & 3 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ func SlashCommand(route string) InteractionCommand {
return InteractionCommand{Type: APPLICATION_COMMAND, Route: route}
}

func ButtonInteraction(customID string) InteractionCommand {
return InteractionCommand{Type: MESSAGE_COMPONENT, Route: customID}
}

// Mux is a discord gateway muxer, which handles the routing
type Mux struct {
rMu *sync.RWMutex
Expand Down Expand Up @@ -87,13 +91,13 @@ type ResponseWriter interface {
func (m *Mux) ListenAndServe(addr string) error {
validator := Validate(m.PublicKey)
r := http.NewServeMux()
r.Handle(m.BasePath, validator(http.HandlerFunc(m.Route)))
r.Handle(m.BasePath, validator(http.HandlerFunc(m.route)))

return http.ListenAndServe(addr, r)
}

// Route handles routing the requests
func (m *Mux) Route(w http.ResponseWriter, r *http.Request) {
// route handles routing the requests
func (m *Mux) route(w http.ResponseWriter, r *http.Request) {
i := &Interaction{}
if err := json.NewDecoder(r.Body).Decode(i); err != nil {
log.Println("Errors unmarshalling json: ", err)
Expand All @@ -111,6 +115,23 @@ func (m *Mux) routeReq(r ResponseWriter, i *Interaction) {
switch i.Type {
case PING:
r.pong()
case MESSAGE_COMPONENT:
if h, ok := m.routes[InteractionCommand{Type: i.Type, Route: i.Data.CustomID}]; ok {
h(r, i)
return
}

for optName := range i.Data.Options {
nr := InteractionCommand{Type: i.Type, Route: i.Data.Name + "/" + i.Data.CustomID}

if handler, ok := m.routes[nr]; ok {
i.Data.Name += "/" + optName
handler(r, i)
return
}
}

m.OnNotFound(r, i)
case APPLICATION_COMMAND:
fallthrough
case APPLICATION_COMMAND_AUTOCOMPLETE:
Expand Down

0 comments on commit e917c27

Please sign in to comment.