feat!: change to PaginationEmbed embed to ComponentsV2's container

This commit is contained in:
Siwoo Jeon 2025-05-23 23:32:34 +09:00
parent 218c019989
commit b6ac950f2e
Signed by: migan
GPG key ID: 036E9A8C5E8E48DA
8 changed files with 140 additions and 110 deletions

View file

@ -62,13 +62,4 @@ func informationRun(s *discordgo.Session, m any) {
}). }).
SetReply(true). SetReply(true).
Send() Send()
// switch m := m.(type) {
// case *discordgo.MessageCreate:
// s.ChannelMessageSendEmbedReply(m.ChannelID, embed, m.Reference())
// case *utils.InteractionCreate:
// m.Reply(&discordgo.InteractionResponseData{
// Embeds: []*discordgo.MessageEmbed{embed},
// })
// }
} }

View file

@ -121,7 +121,7 @@ var LearnedDataListCommand *Command = &Command{
return return
} }
} }
learnedDataListRun(ctx.Msg.Session, ctx.Msg, ctx.Msg.Author.GlobalName, ctx.Msg.Author.AvatarURL("512"), filter, length) learnedDataListRun(ctx.Msg, ctx.Msg.Author.GlobalName, ctx.Msg.Author.AvatarURL("512"), filter, length)
}, },
ChatInputRun: func(ctx *ChatInputContext) { ChatInputRun: func(ctx *ChatInputContext) {
ctx.Inter.DeferReply(&discordgo.InteractionResponseData{ ctx.Inter.DeferReply(&discordgo.InteractionResponseData{
@ -153,7 +153,7 @@ var LearnedDataListCommand *Command = &Command{
if opt, ok := ctx.Inter.Options["개수"]; ok { if opt, ok := ctx.Inter.Options["개수"]; ok {
length = int(opt.IntValue()) length = int(opt.IntValue())
} }
learnedDataListRun(ctx.Inter.Session, ctx.Inter, ctx.Inter.Member.User.GlobalName, ctx.Inter.Member.User.AvatarURL("512"), filter, length) learnedDataListRun(ctx.Inter, ctx.Inter.Member.User.GlobalName, ctx.Inter.Member.User.AvatarURL("512"), filter, length)
}, },
} }
@ -197,7 +197,36 @@ func getDescriptions(data *[]databases.Learn, length int) (descriptions []string
return return
} }
func learnedDataListRun(s *discordgo.Session, m any, globalName, avatarUrl string, filter bson.D, length int) { func getSections(accessory *discordgo.Thumbnail, defaultDesc string, data *[]databases.Learn, length int) []discordgo.MessageComponent {
var sections []discordgo.MessageComponent
descriptions := getDescriptions(data, length)
if len(descriptions) <= 0 {
sections = append(sections, discordgo.Section{
Accessory: accessory,
Components: []discordgo.MessageComponent{
discordgo.TextDisplay{
Content: utils.MakeDesc(defaultDesc, "없음"),
},
},
})
}
for _, desc := range descriptions {
sections = append(sections, discordgo.Section{
Accessory: accessory,
Components: []discordgo.MessageComponent{
discordgo.TextDisplay{
Content: utils.MakeDesc(defaultDesc, desc),
},
},
})
}
return sections
}
func learnedDataListRun(m any, globalName, avatarUrl string, filter bson.D, length int) {
var data []databases.Learn var data []databases.Learn
cur, err := databases.Database.Learns.Find(context.TODO(), filter) cur, err := databases.Database.Learns.Find(context.TODO(), filter)
@ -231,14 +260,14 @@ func learnedDataListRun(s *discordgo.Session, m any, globalName, avatarUrl strin
cur.All(context.TODO(), &data) cur.All(context.TODO(), &data)
utils.NewPaginationEmbedBuilder(m, getDescriptions(&data, length)). sections := getSections(&discordgo.Thumbnail{
SetEmbed(&discordgo.MessageEmbed{ Media: discordgo.UnfurledMediaItem{
Title: fmt.Sprintf("%s님이 알려주신 지식", globalName),
Color: utils.EmbedDefault,
Thumbnail: &discordgo.MessageEmbedThumbnail{
URL: avatarUrl, URL: avatarUrl,
}, },
}). }, fmt.Sprintf("### %s님이 알려주신 지식\n%s", globalName, utils.CodeBlock("md", fmt.Sprintf("# 총 %d개에요.\n", len(data))+"%s")), &data, length)
SetDefaultDesc(utils.CodeBlock("md", fmt.Sprintf("# 총 %d개에요.\n", len(data))+"%s")).
utils.NewPaginationEmbedBuilder(m).
SetContainer(discordgo.Container{}).
AddComponents(sections...).
Start() Start()
} }

View file

@ -7,7 +7,7 @@ import (
"git.wh64.net/muffin/goMuffin/utils" "git.wh64.net/muffin/goMuffin/utils"
) )
const MUFFIN_VERSION = "0.0.0-souffle_canary.250517a-fix_the_spaghetti" const MUFFIN_VERSION = "0.0.0-souffle_canary.250523a-componentsv2"
var updatedString string = utils.RegexpDecimals.FindAllStringSubmatch(MUFFIN_VERSION, -1)[3][0] var updatedString string = utils.RegexpDecimals.FindAllStringSubmatch(MUFFIN_VERSION, -1)[3][0]

2
go.mod
View file

@ -4,7 +4,7 @@ go 1.24.1
require ( require (
github.com/LoperLee/golang-hangul-toolkit v1.1.0 github.com/LoperLee/golang-hangul-toolkit v1.1.0
github.com/bwmarrin/discordgo v0.28.1 github.com/bwmarrin/discordgo v0.28.2-0.20250520184322-b9883c495955
github.com/devproje/commando v0.1.0-alpha.1 github.com/devproje/commando v0.1.0-alpha.1
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
go.mongodb.org/mongo-driver/v2 v2.1.0 go.mongodb.org/mongo-driver/v2 v2.1.0

2
go.sum
View file

@ -2,6 +2,8 @@ github.com/LoperLee/golang-hangul-toolkit v1.1.0 h1:JEyLpLyA2hDQwWY9oCprHClnKIdk
github.com/LoperLee/golang-hangul-toolkit v1.1.0/go.mod h1:CDbZ23/IL4v2ovWIOb7xDEiFcSc0pIIbbYTpg+gP+Sk= github.com/LoperLee/golang-hangul-toolkit v1.1.0/go.mod h1:CDbZ23/IL4v2ovWIOb7xDEiFcSc0pIIbbYTpg+gP+Sk=
github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd1aG4= github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd1aG4=
github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/bwmarrin/discordgo v0.28.2-0.20250520184322-b9883c495955 h1:ReUA/wL53HdO2jlzwwl5kVa2UJInBtHzqrvf3eVTEvk=
github.com/bwmarrin/discordgo v0.28.2-0.20250520184322-b9883c495955/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/devproje/commando v0.1.0-alpha.1 h1:JU6CKIdt1otjUKh+asCJC0yTzwVj+4Yh8KoTdzaKAkU= github.com/devproje/commando v0.1.0-alpha.1 h1:JU6CKIdt1otjUKh+asCJC0yTzwVj+4Yh8KoTdzaKAkU=

View file

@ -1,12 +1,6 @@
package utils package utils
import ( import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
) )
@ -36,13 +30,17 @@ type InteractionCreate struct {
} }
// Reply to this interaction. // Reply to this interaction.
func (i *InteractionCreate) Reply(data *discordgo.InteractionResponseData) { func (i *InteractionCreate) Reply(data *discordgo.InteractionResponseData) error {
i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ err := i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource, Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: data, Data: data,
}) })
if err != nil {
return err
}
i.Replied = true i.Replied = true
return nil
} }
// GetInteractionOptions to this interaction. // GetInteractionOptions to this interaction.
@ -70,12 +68,16 @@ func (i *InteractionCreate) DeferReply(data *discordgo.InteractionResponseData)
} }
// DeferUpdate to this interaction. // DeferUpdate to this interaction.
func (i *InteractionCreate) DeferUpdate() { func (i *InteractionCreate) DeferUpdate() error {
i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ err := i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseDeferredMessageUpdate, Type: discordgo.InteractionResponseDeferredMessageUpdate,
}) })
if err != nil {
return err
}
i.Deferred = true i.Deferred = true
return err
} }
// EditReply to this interaction. // EditReply to this interaction.
@ -89,13 +91,17 @@ func (i *InteractionCreate) EditReply(data *InteractionEdit) error {
} }
// Update to this interaction. // Update to this interaction.
func (i *InteractionCreate) Update(data *discordgo.InteractionResponseData) { func (i *InteractionCreate) Update(data *discordgo.InteractionResponseData) error {
i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ err := i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseUpdateMessage, Type: discordgo.InteractionResponseUpdateMessage,
Data: data, Data: data,
}) })
if err != nil {
return err
}
i.Replied = true i.Replied = true
return err
} }
func (i *InteractionCreate) ShowModal(data *ModalData) error { func (i *InteractionCreate) ShowModal(data *ModalData) error {

View file

@ -1,6 +1,8 @@
package utils package utils
import "github.com/bwmarrin/discordgo" import (
"github.com/bwmarrin/discordgo"
)
type MessageCreate struct { type MessageCreate struct {
*discordgo.MessageCreate *discordgo.MessageCreate
@ -13,6 +15,7 @@ type MessageSender struct {
Components []discordgo.MessageComponent Components []discordgo.MessageComponent
Ephemeral bool Ephemeral bool
Reply bool Reply bool
ComponentsV2 bool
AllowedMentions *discordgo.MessageAllowedMentions AllowedMentions *discordgo.MessageAllowedMentions
m any m any
} }
@ -51,7 +54,18 @@ func (s *MessageSender) SetAllowedMentions(allowedMentions discordgo.MessageAllo
return s return s
} }
func (s *MessageSender) Send() { func (s *MessageSender) SetComponentsV2(componentsV2 bool) *MessageSender {
s.ComponentsV2 = componentsV2
return s
}
func (s *MessageSender) Send() error {
var flags discordgo.MessageFlags
if s.ComponentsV2 {
flags = flags | discordgo.MessageFlagsIsComponentsV2
}
switch m := s.m.(type) { switch m := s.m.(type) {
case *MessageCreate: case *MessageCreate:
var reference *discordgo.MessageReference = nil var reference *discordgo.MessageReference = nil
@ -60,19 +74,18 @@ func (s *MessageSender) Send() {
reference = m.Reference() reference = m.Reference()
} }
m.Session.ChannelMessageSendComplex(m.ChannelID, &discordgo.MessageSend{ _, err := m.Session.ChannelMessageSendComplex(m.ChannelID, &discordgo.MessageSend{
Content: s.Content, Content: s.Content,
Embeds: s.Embeds, Embeds: s.Embeds,
Components: s.Components, Components: s.Components,
AllowedMentions: s.AllowedMentions, AllowedMentions: s.AllowedMentions,
Flags: flags,
Reference: reference, Reference: reference,
}) })
return return err
case *InteractionCreate: case *InteractionCreate:
var flags discordgo.MessageFlags
if s.Ephemeral { if s.Ephemeral {
flags = discordgo.MessageFlagsEphemeral flags = flags | discordgo.MessageFlagsEphemeral
} }
if m.Replied || m.Deferred { if m.Replied || m.Deferred {
@ -80,16 +93,18 @@ func (s *MessageSender) Send() {
Content: &s.Content, Content: &s.Content,
Embeds: &s.Embeds, Embeds: &s.Embeds,
Components: &s.Components, Components: &s.Components,
Flags: &flags,
}) })
return return err
} }
m.Reply(&discordgo.InteractionResponseData{ err := m.Reply(&discordgo.InteractionResponseData{
Content: s.Content, Content: s.Content,
Embeds: s.Embeds, Embeds: s.Embeds,
Components: s.Components, Components: s.Components,
Flags: flags, Flags: flags,
}) })
return return err
} }
return nil
} }

View file

@ -9,47 +9,47 @@ import (
// PaginationEmbed is embed with page // PaginationEmbed is embed with page
type PaginationEmbed struct { type PaginationEmbed struct {
Embed *discordgo.MessageEmbed Container *discordgo.Container
Data []string Components []discordgo.MessageComponent
Current int Current int
Total int Total int
id string Id string
desc string
}
type PaginationEmbedBuilder struct {
Embed *discordgo.MessageEmbed
Data []string
DefaultDesc string
m any m any
} }
var PaginationEmbeds = make(map[string]*PaginationEmbed) var PaginationEmbeds = make(map[string]*PaginationEmbed)
func NewPaginationEmbedBuilder(m any, data []string) *PaginationEmbedBuilder { func NewPaginationEmbedBuilder(m any) *PaginationEmbed {
return &PaginationEmbedBuilder{ var userId string
m: m,
Data: data,
}
}
func (b *PaginationEmbedBuilder) SetEmbed(embed *discordgo.MessageEmbed) *PaginationEmbedBuilder { switch m := m.(type) {
b.Embed = embed
return b
}
func (b *PaginationEmbedBuilder) SetDefaultDesc(desc string) *PaginationEmbedBuilder {
b.DefaultDesc = desc
return b
}
func (b *PaginationEmbedBuilder) Start() {
switch m := b.m.(type) {
case *MessageCreate: case *MessageCreate:
startPaginationEmbed(m, m.Author.ID, b.Embed, b.Data, b.DefaultDesc) userId = m.Author.ID
case *InteractionCreate: case *InteractionCreate:
startPaginationEmbed(m, m.Member.User.ID, b.Embed, b.Data, b.DefaultDesc) userId = m.Member.User.ID
} }
id := fmt.Sprintf("%s/%d", userId, rand.Intn(100))
return &PaginationEmbed{
Current: 1,
Id: id,
m: m,
}
}
func (p *PaginationEmbed) SetContainer(container discordgo.Container) *PaginationEmbed {
p.Container = &container
return p
}
func (p *PaginationEmbed) AddComponents(components ...discordgo.MessageComponent) *PaginationEmbed {
p.Total += len(components)
p.Components = append(p.Components, components...)
return p
}
func (p *PaginationEmbed) Start() {
startPaginationEmbed(p)
} }
func makeComponents(id string, current, total int) *discordgo.ActionsRow { func makeComponents(id string, current, total int) *discordgo.ActionsRow {
@ -83,7 +83,7 @@ func makeComponents(id string, current, total int) *discordgo.ActionsRow {
} }
} }
func makeDesc(desc, item string) string { func MakeDesc(desc, item string) string {
var newDesc string var newDesc string
if desc == "" { if desc == "" {
@ -94,32 +94,18 @@ func makeDesc(desc, item string) string {
return newDesc return newDesc
} }
func startPaginationEmbed(m any, userId string, e *discordgo.MessageEmbed, data []string, defaultDesc string) { func startPaginationEmbed(p *PaginationEmbed) error {
id := fmt.Sprintf("%s/%d", userId, rand.Intn(100)) p.Container.Components = append(p.Container.Components, p.Components[0], makeComponents(p.Id, p.Current, p.Total))
p := &PaginationEmbed{
Embed: e,
Data: data,
Current: 1,
Total: len(data),
id: id,
desc: defaultDesc,
}
if len(data) <= 0 { PaginationEmbeds[p.Id] = p
p.Embed.Description = makeDesc(p.desc, "없음")
p.Total = 1
} else {
p.Embed.Description = makeDesc(p.desc, data[0])
}
NewMessageSender(m). err := NewMessageSender(p.m).
AddEmbeds(e). AddComponents(p.Container).
AddComponents(makeComponents(id, p.Current, p.Total)).
SetReply(true). SetReply(true).
SetEphemeral(true). SetEphemeral(true).
SetComponentsV2(true).
Send() Send()
return err
PaginationEmbeds[id] = p
} }
func GetPaginationEmbed(id string) *PaginationEmbed { func GetPaginationEmbed(id string) *PaginationEmbed {
@ -169,7 +155,7 @@ func (p *PaginationEmbed) Next(i *InteractionCreate) {
p.Set(i, p.Current) p.Set(i, p.Current)
} }
func (p *PaginationEmbed) Set(i *InteractionCreate, page int) { func (p *PaginationEmbed) Set(i *InteractionCreate, page int) error {
if page <= 0 { if page <= 0 {
i.Reply(&discordgo.InteractionResponseData{ i.Reply(&discordgo.InteractionResponseData{
Embeds: []*discordgo.MessageEmbed{ Embeds: []*discordgo.MessageEmbed{
@ -181,10 +167,10 @@ func (p *PaginationEmbed) Set(i *InteractionCreate, page int) {
}, },
Flags: discordgo.MessageFlagsEphemeral, Flags: discordgo.MessageFlagsEphemeral,
}) })
return return nil
} }
if page >= p.Total { if page > p.Total {
i.Reply(&discordgo.InteractionResponseData{ i.Reply(&discordgo.InteractionResponseData{
Embeds: []*discordgo.MessageEmbed{ Embeds: []*discordgo.MessageEmbed{
{ {
@ -195,28 +181,29 @@ func (p *PaginationEmbed) Set(i *InteractionCreate, page int) {
}, },
Flags: discordgo.MessageFlagsEphemeral, Flags: discordgo.MessageFlagsEphemeral,
}) })
return return nil
} }
p.Current = page p.Current = page
p.Embed.Description = makeDesc(p.desc, p.Data[p.Current-1]) p.Container.Components = []discordgo.MessageComponent{p.Components[p.Current-1], makeComponents(p.Id, p.Current, p.Total)}
i.Update(&discordgo.InteractionResponseData{ err := i.Update(&discordgo.InteractionResponseData{
Embeds: []*discordgo.MessageEmbed{p.Embed}, Flags: discordgo.MessageFlagsIsComponentsV2,
Components: []discordgo.MessageComponent{makeComponents(p.id, p.Current, p.Total)}, Components: []discordgo.MessageComponent{p.Container},
}) })
return err
} }
func (p *PaginationEmbed) ShowModal(i *InteractionCreate) { func (p *PaginationEmbed) ShowModal(i *InteractionCreate) {
i.ShowModal(&ModalData{ i.ShowModal(&ModalData{
CustomId: MakePaginationEmbedModal(p.id), CustomId: MakePaginationEmbedModal(p.Id),
Title: fmt.Sprintf("%s의 리스트", i.Session.State.User.Username), Title: fmt.Sprintf("%s의 리스트", i.Session.State.User.Username),
Components: []discordgo.MessageComponent{ Components: []discordgo.MessageComponent{
discordgo.ActionsRow{ discordgo.ActionsRow{
Components: []discordgo.MessageComponent{ Components: []discordgo.MessageComponent{
discordgo.TextInput{ discordgo.TextInput{
CustomID: MakePaginationEmbedSetPage(p.id), CustomID: MakePaginationEmbedSetPage(p.Id),
Label: "페이지", Label: "페이지",
Style: discordgo.TextInputShort, Style: discordgo.TextInputShort,
Placeholder: "이동할 페이지를 여기에 적어주세요.", Placeholder: "이동할 페이지를 여기에 적어주세요.",