Discord Components & Role Selection (#5)

This commit is contained in:
2023-04-01 01:23:37 -04:00
committed by GitHub
parent 5e6a433b92
commit e1038a15cd
25 changed files with 696 additions and 31 deletions

29
discord/component.go Normal file
View File

@ -0,0 +1,29 @@
package discord
import (
"log"
"github.com/bwmarrin/discordgo"
)
// Component is an object that can be formatted as a discord component
type Component interface {
toMessageComponent() discordgo.MessageComponent
}
// CreateMessageComponent creates a discord component
func (discord *Discord) CreateMessageComponent(channelID string, content string, components []Component) {
dComponents := make([]discordgo.MessageComponent, len(components))
for i, v := range components {
dComponents[i] = v.toMessageComponent()
}
if _, err := discord.session.ChannelMessageSendComplex(channelID, &discordgo.MessageSend{
Components: dComponents,
Content: content,
}); err != nil {
log.Print(err)
}
}

View File

@ -0,0 +1,38 @@
package discord
import "github.com/bwmarrin/discordgo"
type ActionRow struct {
components []Component
}
// NewActionRow creates an empty action row component
func (discord *Discord) NewActionRow() *ActionRow {
return &ActionRow{
components: []Component{},
}
}
// NewActionRowWith creates an action row with a set of components
func (discord *Discord) NewActionRowWith(comp []Component) *ActionRow {
return &ActionRow{
components: comp,
}
}
// AddComponent adds a component to the action row
func (row *ActionRow) AddComponent(comp Component) {
row.components = append(row.components, comp)
}
func (row *ActionRow) toMessageComponent() discordgo.MessageComponent {
comps := make([]discordgo.MessageComponent, len(row.components))
for i, v := range row.components {
comps[i] = v.toMessageComponent()
}
return discordgo.ActionsRow{
Components: comps,
}
}

View File

@ -0,0 +1,45 @@
package discord
import (
"github.com/bwmarrin/discordgo"
"github.com/yeslayla/birdbot/common"
)
type Button struct {
Label string
ID string
discord *Discord
}
// NewButton creates a new button component
func (discord *Discord) NewButton(id string, label string) *Button {
return &Button{
discord: discord,
ID: id,
Label: label,
}
}
// OnClick registers an event when the button is clicked
func (button *Button) OnClick(action func(user common.User)) {
button.discord.session.AddHandler(func(s *discordgo.Session, r *discordgo.InteractionCreate) {
if r.MessageComponentData().CustomID == button.ID {
action(NewUser(r.Member.User))
s.InteractionRespond(r.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
})
}
})
}
func (button *Button) toMessageComponent() discordgo.MessageComponent {
return discordgo.Button{
Label: button.Label,
CustomID: button.ID,
Style: discordgo.PrimaryButton,
}
}

View File

@ -39,6 +39,7 @@ func NewEvent(guildEvent *discordgo.GuildScheduledEvent) common.Event {
return event
}
// CreateEvent creates a new discord event
func (discord *Discord) CreateEvent(event common.Event) error {
params := &discordgo.GuildScheduledEventParams{

72
discord/role.go Normal file
View File

@ -0,0 +1,72 @@
package discord
import (
"image/color"
"log"
"github.com/bwmarrin/discordgo"
"github.com/yeslayla/birdbot/core"
)
type Role struct {
discord *Discord
ID string
Name string
Color color.Color
}
// GetRole returns a role that exists on Discord
func (discord *Discord) GetRole(name string) *Role {
roles, err := discord.session.GuildRoles(discord.guildID)
if err != nil {
log.Printf("Error occured listing roles: %s", err)
return nil
}
for _, role := range roles {
if role.Managed {
continue
}
if role.Name == name {
return &Role{
Name: role.Name,
Color: core.IntToColor(role.Color),
discord: discord,
ID: role.ID,
}
}
}
return nil
}
// GetRoleAndCreate gets a role and creates it if it doesn't exist
func (discord *Discord) GetRoleAndCreate(name string) *Role {
role := discord.GetRole(name)
if role != nil {
return role
}
if _, err := discord.session.GuildRoleCreate(discord.guildID, &discordgo.RoleParams{
Name: name,
Color: core.Int(0),
}); err != nil {
log.Printf("Failed to create role: %s", err)
return nil
}
return discord.GetRole(name)
}
// Save updates the role on Discord
func (role *Role) Save() {
if _, err := role.discord.session.GuildRoleEdit(role.discord.guildID, role.ID, &discordgo.RoleParams{
Name: role.Name,
Color: core.Int(core.ColorToInt(role.Color)),
}); err != nil {
log.Printf("Failed to save role: %s", err)
}
}

View File

@ -9,6 +9,7 @@ import (
// NewUser creates a new user object from a discordgo.User object
func NewUser(user *discordgo.User) common.User {
if user == nil {
log.Print("Cannot user object, user is nil!")
return common.User{
@ -20,3 +21,38 @@ func NewUser(user *discordgo.User) common.User {
ID: user.ID,
}
}
// AssignRole adds a role to a user
func (discord *Discord) AssignRole(user common.User, role *Role) error {
return discord.session.GuildMemberRoleAdd(discord.guildID, user.ID, role.ID)
}
// UnassignRole removes a role from a user
func (discord *Discord) UnassignRole(user common.User, role *Role) error {
return discord.session.GuildMemberRoleRemove(discord.guildID, user.ID, role.ID)
}
// HasRole returns true when a user has a given role
func (discord *Discord) HasRole(user common.User, role *Role) bool {
return discord.HasAtLeastOneRole(user, []*Role{role})
}
// HasAtLeastOneRole returns true when a user has at one role from a given array
func (discord *Discord) HasAtLeastOneRole(user common.User, roles []*Role) bool {
member, err := discord.session.GuildMember(discord.guildID, user.ID)
if err != nil {
log.Printf("Failed to get member: %s", err)
return false
}
for _, v := range member.Roles {
for _, targetRole := range roles {
if v == targetRole.ID {
return true
}
}
}
return false
}