Discord Components & Role Selection (#5)
This commit is contained in:
		
							
								
								
									
										29
									
								
								discord/component.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								discord/component.go
									
									
									
									
									
										Normal 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)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								discord/component_action_row.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								discord/component_action_row.go
									
									
									
									
									
										Normal 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,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								discord/component_button.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								discord/component_button.go
									
									
									
									
									
										Normal 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,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -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
									
								
							
							
						
						
									
										72
									
								
								discord/role.go
									
									
									
									
									
										Normal 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)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user