Improved role selection
This commit is contained in:
parent
ee1bb762fb
commit
abd373916e
@ -39,8 +39,9 @@ type StatusPortal struct {
|
||||
}
|
||||
|
||||
type RoleSelectionConfig struct {
|
||||
Title string `yaml:"title"`
|
||||
Description string `yaml:"description"`
|
||||
Title string `yaml:"title"`
|
||||
Description string `yaml:"description"`
|
||||
GenerateColorEmoji Feature `yaml:"generate_color_emoji"`
|
||||
|
||||
SelectionChannel string `yaml:"discord_channel"`
|
||||
Roles []RoleConfig `yaml:"roles"`
|
||||
|
33
core/image.go
Normal file
33
core/image.go
Normal file
@ -0,0 +1,33 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/jpeg"
|
||||
"log"
|
||||
)
|
||||
|
||||
func ImageToBase64(img image.Image) string {
|
||||
data := &bytes.Buffer{}
|
||||
if err := jpeg.Encode(data, img, nil); err != nil {
|
||||
log.Println("Error encoding avatar: ", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
return fmt.Sprintf("data:image/png;base64,%s", base64.StdEncoding.EncodeToString(data.Bytes()))
|
||||
}
|
||||
|
||||
// ColorToImage creates a 16x16 image filled with the specified color.
|
||||
func ColorToImage(c color.Color) image.Image {
|
||||
// Create a new rectangle with the desired dimensions.
|
||||
rect := image.Rect(0, 0, 16, 16)
|
||||
// Create a new RGBA image with the specified rectangle.
|
||||
img := image.NewRGBA(rect)
|
||||
// Use the draw.Draw function to fill the image with the specified color.
|
||||
draw.Draw(img, img.Bounds(), &image.Uniform{C: c}, image.Point{}, draw.Src)
|
||||
return img
|
||||
}
|
@ -30,3 +30,27 @@ func (discord *Discord) CreateMessageComponent(channelID string, content string,
|
||||
|
||||
return result.ID
|
||||
}
|
||||
|
||||
// UpdateMessageComponent updates a discord component
|
||||
func (discord *Discord) UpdateMessageComponent(messageID string, channelID string, content string, components []Component) string {
|
||||
dComponents := make([]discordgo.MessageComponent, len(components))
|
||||
for i, v := range components {
|
||||
dComponents[i] = v.toMessageComponent()
|
||||
}
|
||||
|
||||
result, err := discord.session.ChannelMessageEditComplex(&discordgo.MessageEdit{
|
||||
Components: dComponents,
|
||||
Content: &content,
|
||||
Channel: channelID,
|
||||
ID: messageID,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Error updating message component: %s", err)
|
||||
}
|
||||
|
||||
if result != nil {
|
||||
return result.ID
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ type Button struct {
|
||||
Label string
|
||||
ID string
|
||||
|
||||
Emoji *Emoji
|
||||
discord *Discord
|
||||
}
|
||||
|
||||
@ -18,6 +19,17 @@ func (discord *Discord) NewButton(id string, label string) *Button {
|
||||
discord: discord,
|
||||
ID: id,
|
||||
Label: label,
|
||||
Emoji: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// NewButtonWithEmoji creates a new button component with a emoji
|
||||
func (discord *Discord) NewButtonWithEmoji(id string, label string, emoji *Emoji) *Button {
|
||||
return &Button{
|
||||
discord: discord,
|
||||
ID: id,
|
||||
Label: label,
|
||||
Emoji: emoji,
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,9 +53,16 @@ func (button *Button) OnClick(action func(user common.User)) {
|
||||
}
|
||||
|
||||
func (button *Button) toMessageComponent() discordgo.MessageComponent {
|
||||
return discordgo.Button{
|
||||
cmp := discordgo.Button{
|
||||
Label: button.Label,
|
||||
CustomID: button.ID,
|
||||
Style: discordgo.PrimaryButton,
|
||||
}
|
||||
if button.Emoji != nil {
|
||||
cmp.Emoji = &discordgo.ComponentEmoji{
|
||||
Name: button.Emoji.Name,
|
||||
ID: button.Emoji.ID,
|
||||
}
|
||||
}
|
||||
return cmp
|
||||
}
|
||||
|
78
discord/emoji.go
Normal file
78
discord/emoji.go
Normal file
@ -0,0 +1,78 @@
|
||||
package discord
|
||||
|
||||
import (
|
||||
"image"
|
||||
"log"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/yeslayla/birdbot/core"
|
||||
)
|
||||
|
||||
type Emoji struct {
|
||||
discord *Discord
|
||||
ID string
|
||||
|
||||
Name string
|
||||
Roles []string
|
||||
}
|
||||
|
||||
// GetEmoji returns a emoji that exists on Discord
|
||||
func (discord *Discord) GetEmoji(name string) *Emoji {
|
||||
|
||||
emojis, err := discord.session.GuildEmojis(discord.guildID)
|
||||
if err != nil {
|
||||
log.Printf("Error occured listing roles: %s", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, emoji := range emojis {
|
||||
if emoji.Managed {
|
||||
continue
|
||||
}
|
||||
if emoji.Name == name {
|
||||
|
||||
return &Emoji{
|
||||
ID: emoji.ID,
|
||||
discord: discord,
|
||||
Name: emoji.Name,
|
||||
Roles: emoji.Roles,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateEmoji creates a new emoji on Discord
|
||||
func (discord *Discord) CreateEmoji(name string, image image.Image) *Emoji {
|
||||
result, err := discord.session.GuildEmojiCreate(discord.guildID, &discordgo.EmojiParams{
|
||||
Name: name,
|
||||
Image: core.ImageToBase64(image),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to create emoji: %s", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
log.Print("Failed to create emoji: result is nil")
|
||||
return nil
|
||||
}
|
||||
|
||||
return &Emoji{
|
||||
ID: result.ID,
|
||||
Name: result.Name,
|
||||
Roles: result.Roles,
|
||||
discord: discord,
|
||||
}
|
||||
}
|
||||
|
||||
// Save updates the emoji on Discord
|
||||
func (emoji *Emoji) Save() {
|
||||
if _, err := emoji.discord.session.GuildEmojiEdit(emoji.discord.guildID, emoji.ID, &discordgo.EmojiParams{
|
||||
Name: emoji.Name,
|
||||
Roles: emoji.Roles,
|
||||
}); err != nil {
|
||||
log.Printf("Failed to save role: %s", err)
|
||||
}
|
||||
}
|
@ -1,15 +1,12 @@
|
||||
package discord
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/jpeg"
|
||||
"log"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/yeslayla/birdbot-common/common"
|
||||
"github.com/yeslayla/birdbot/core"
|
||||
)
|
||||
|
||||
// NewUser creates a new user object from a discordgo.User object
|
||||
@ -49,13 +46,7 @@ func (discord *Discord) GetAvatar(user common.User) image.Image {
|
||||
func (discord *Discord) GetAvatarBase64(user common.User) string {
|
||||
avatar := discord.GetAvatar(user)
|
||||
|
||||
fmtAvatar := &bytes.Buffer{}
|
||||
if err := jpeg.Encode(fmtAvatar, avatar, nil); err != nil {
|
||||
log.Println("Error encoding avatar: ", err)
|
||||
return ""
|
||||
}
|
||||
|
||||
return fmt.Sprintf("data:image/png;base64,%s", base64.StdEncoding.EncodeToString(fmtAvatar.Bytes()))
|
||||
return core.ImageToBase64(avatar)
|
||||
}
|
||||
|
||||
// AssignRole adds a role to a user
|
||||
|
@ -40,13 +40,43 @@ func (c *roleSelectionModule) Initialize(birdbot common.ModuleManager) error {
|
||||
role := c.session.GetRoleAndCreate(roleConfig.RoleName)
|
||||
configColor, _ := core.HexToColor(roleConfig.Color)
|
||||
|
||||
var emoji *discord.Emoji = nil
|
||||
if c.cfg.GenerateColorEmoji.IsEnabledByDefault() {
|
||||
emoji = c.session.GetEmoji(roleConfig.RoleName)
|
||||
if emoji == nil {
|
||||
emoji = c.session.CreateEmoji(roleConfig.RoleName, core.ColorToImage(configColor))
|
||||
if emoji == nil {
|
||||
log.Printf("Failed to create emoji for role: %s", roleConfig.RoleName)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// If role.ID in emoji.Roles
|
||||
var found bool
|
||||
for _, r := range emoji.Roles {
|
||||
if r == role.ID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
emoji.Roles = append(emoji.Roles, role.ID)
|
||||
emoji.Save()
|
||||
}
|
||||
}
|
||||
|
||||
if role.Color != configColor {
|
||||
role.Color = configColor
|
||||
role.Save()
|
||||
}
|
||||
|
||||
// Create button
|
||||
btn := c.session.NewButton(fmt.Sprint(c.cfg.Title, role.Name), role.Name)
|
||||
var btn *discord.Button
|
||||
if emoji != nil {
|
||||
btn = c.session.NewButtonWithEmoji(fmt.Sprint(c.cfg.Title, roleConfig.RoleName), roleConfig.RoleName, emoji)
|
||||
} else {
|
||||
btn = c.session.NewButton(fmt.Sprint(c.cfg.Title, role.Name), role.Name)
|
||||
}
|
||||
btn.OnClick(func(user common.User) {
|
||||
|
||||
// Assign the roles asynchronously to avoid Discord's response timeout
|
||||
@ -97,10 +127,16 @@ func (c *roleSelectionModule) Initialize(birdbot common.ModuleManager) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if messageID == "" {
|
||||
messageID = c.session.CreateMessageComponent(c.cfg.SelectionChannel, fmt.Sprintf("**%s**\n%s", c.cfg.Title, c.cfg.Description), components)
|
||||
return c.db.SetDiscordMessage(localID, messageID)
|
||||
// Update message
|
||||
if messageID != "" {
|
||||
resultID := c.session.UpdateMessageComponent(messageID, c.cfg.SelectionChannel, fmt.Sprintf("**%s**\n%s", c.cfg.Title, c.cfg.Description), components)
|
||||
if resultID != "" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
// Create new message
|
||||
messageID = c.session.CreateMessageComponent(c.cfg.SelectionChannel, fmt.Sprintf("**%s**\n%s", c.cfg.Title, c.cfg.Description), components)
|
||||
return c.db.SetDiscordMessage(localID, messageID)
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user