diff --git a/commands/information.go b/commands/information.go index f1928ee..b7cedee 100644 --- a/commands/information.go +++ b/commands/information.go @@ -62,13 +62,4 @@ func informationRun(s *discordgo.Session, m any) { }). SetReply(true). 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}, - // }) - // } } diff --git a/commands/learnedDataList.go b/commands/learnedDataList.go index 298e4c7..8d60832 100644 --- a/commands/learnedDataList.go +++ b/commands/learnedDataList.go @@ -121,7 +121,7 @@ var LearnedDataListCommand *Command = &Command{ 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) { ctx.Inter.DeferReply(&discordgo.InteractionResponseData{ @@ -153,7 +153,7 @@ var LearnedDataListCommand *Command = &Command{ if opt, ok := ctx.Inter.Options["개수"]; ok { 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 } -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 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) - utils.NewPaginationEmbedBuilder(m, getDescriptions(&data, length)). - SetEmbed(&discordgo.MessageEmbed{ - Title: fmt.Sprintf("%s님이 알려주신 지식", globalName), - Color: utils.EmbedDefault, - Thumbnail: &discordgo.MessageEmbedThumbnail{ - URL: avatarUrl, - }, - }). - SetDefaultDesc(utils.CodeBlock("md", fmt.Sprintf("# 총 %d개에요.\n", len(data))+"%s")). + sections := getSections(&discordgo.Thumbnail{ + Media: discordgo.UnfurledMediaItem{ + URL: avatarUrl, + }, + }, fmt.Sprintf("### %s님이 알려주신 지식\n%s", globalName, utils.CodeBlock("md", fmt.Sprintf("# 총 %d개에요.\n", len(data))+"%s")), &data, length) + + utils.NewPaginationEmbedBuilder(m). + SetContainer(discordgo.Container{}). + AddComponents(sections...). Start() } diff --git a/configs/version.go b/configs/version.go index 2a1b104..c543835 100644 --- a/configs/version.go +++ b/configs/version.go @@ -7,7 +7,7 @@ import ( "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] diff --git a/go.mod b/go.mod index dda1b75..82db85d 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.24.1 require ( 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/joho/godotenv v1.5.1 go.mongodb.org/mongo-driver/v2 v2.1.0 diff --git a/go.sum b/go.sum index fee636b..56e6647 100644 --- a/go.sum +++ b/go.sum @@ -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/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.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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/devproje/commando v0.1.0-alpha.1 h1:JU6CKIdt1otjUKh+asCJC0yTzwVj+4Yh8KoTdzaKAkU= diff --git a/utils/interactions.go b/utils/interactions.go index b59b0ed..0cc4461 100644 --- a/utils/interactions.go +++ b/utils/interactions.go @@ -1,12 +1,6 @@ package utils import ( - "bytes" - "encoding/json" - "fmt" - "io" - "net/http" - "github.com/bwmarrin/discordgo" ) @@ -36,13 +30,17 @@ type InteractionCreate struct { } // Reply to this interaction. -func (i *InteractionCreate) Reply(data *discordgo.InteractionResponseData) { - i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ +func (i *InteractionCreate) Reply(data *discordgo.InteractionResponseData) error { + err := i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: data, }) + if err != nil { + return err + } i.Replied = true + return nil } // GetInteractionOptions to this interaction. @@ -70,12 +68,16 @@ func (i *InteractionCreate) DeferReply(data *discordgo.InteractionResponseData) } // DeferUpdate to this interaction. -func (i *InteractionCreate) DeferUpdate() { - i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ +func (i *InteractionCreate) DeferUpdate() error { + err := i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseDeferredMessageUpdate, }) + if err != nil { + return err + } i.Deferred = true + return err } // EditReply to this interaction. @@ -89,13 +91,17 @@ func (i *InteractionCreate) EditReply(data *InteractionEdit) error { } // Update to this interaction. -func (i *InteractionCreate) Update(data *discordgo.InteractionResponseData) { - i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ +func (i *InteractionCreate) Update(data *discordgo.InteractionResponseData) error { + err := i.Session.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseUpdateMessage, Data: data, }) + if err != nil { + return err + } i.Replied = true + return err } func (i *InteractionCreate) ShowModal(data *ModalData) error { diff --git a/utils/messageBuilder.go b/utils/messageBuilder.go index 4e1d0ea..612a1ce 100644 --- a/utils/messageBuilder.go +++ b/utils/messageBuilder.go @@ -1,6 +1,8 @@ package utils -import "github.com/bwmarrin/discordgo" +import ( + "github.com/bwmarrin/discordgo" +) type MessageCreate struct { *discordgo.MessageCreate @@ -13,6 +15,7 @@ type MessageSender struct { Components []discordgo.MessageComponent Ephemeral bool Reply bool + ComponentsV2 bool AllowedMentions *discordgo.MessageAllowedMentions m any } @@ -51,7 +54,18 @@ func (s *MessageSender) SetAllowedMentions(allowedMentions discordgo.MessageAllo 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) { case *MessageCreate: var reference *discordgo.MessageReference = nil @@ -60,19 +74,18 @@ func (s *MessageSender) Send() { reference = m.Reference() } - m.Session.ChannelMessageSendComplex(m.ChannelID, &discordgo.MessageSend{ + _, err := m.Session.ChannelMessageSendComplex(m.ChannelID, &discordgo.MessageSend{ Content: s.Content, Embeds: s.Embeds, Components: s.Components, AllowedMentions: s.AllowedMentions, + Flags: flags, Reference: reference, }) - return + return err case *InteractionCreate: - var flags discordgo.MessageFlags - if s.Ephemeral { - flags = discordgo.MessageFlagsEphemeral + flags = flags | discordgo.MessageFlagsEphemeral } if m.Replied || m.Deferred { @@ -80,16 +93,18 @@ func (s *MessageSender) Send() { Content: &s.Content, Embeds: &s.Embeds, Components: &s.Components, + Flags: &flags, }) - return + return err } - m.Reply(&discordgo.InteractionResponseData{ + err := m.Reply(&discordgo.InteractionResponseData{ Content: s.Content, Embeds: s.Embeds, Components: s.Components, Flags: flags, }) - return + return err } + return nil } diff --git a/utils/paginationEmbed.go b/utils/paginationEmbed.go index e0a0f4a..3dfde51 100644 --- a/utils/paginationEmbed.go +++ b/utils/paginationEmbed.go @@ -9,47 +9,47 @@ import ( // PaginationEmbed is embed with page type PaginationEmbed struct { - Embed *discordgo.MessageEmbed - Data []string - Current int - Total int - id string - desc string -} - -type PaginationEmbedBuilder struct { - Embed *discordgo.MessageEmbed - Data []string - DefaultDesc string - m any + Container *discordgo.Container + Components []discordgo.MessageComponent + Current int + Total int + Id string + m any } var PaginationEmbeds = make(map[string]*PaginationEmbed) -func NewPaginationEmbedBuilder(m any, data []string) *PaginationEmbedBuilder { - return &PaginationEmbedBuilder{ - m: m, - Data: data, - } -} +func NewPaginationEmbedBuilder(m any) *PaginationEmbed { + var userId string -func (b *PaginationEmbedBuilder) SetEmbed(embed *discordgo.MessageEmbed) *PaginationEmbedBuilder { - 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) { + switch m := m.(type) { case *MessageCreate: - startPaginationEmbed(m, m.Author.ID, b.Embed, b.Data, b.DefaultDesc) + userId = m.Author.ID 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 { @@ -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 if desc == "" { @@ -94,32 +94,18 @@ func makeDesc(desc, item string) string { return newDesc } -func startPaginationEmbed(m any, userId string, e *discordgo.MessageEmbed, data []string, defaultDesc string) { - id := fmt.Sprintf("%s/%d", userId, rand.Intn(100)) - p := &PaginationEmbed{ - Embed: e, - Data: data, - Current: 1, - Total: len(data), - id: id, - desc: defaultDesc, - } +func startPaginationEmbed(p *PaginationEmbed) error { + p.Container.Components = append(p.Container.Components, p.Components[0], makeComponents(p.Id, p.Current, p.Total)) - if len(data) <= 0 { - p.Embed.Description = makeDesc(p.desc, "없음") - p.Total = 1 - } else { - p.Embed.Description = makeDesc(p.desc, data[0]) - } + PaginationEmbeds[p.Id] = p - NewMessageSender(m). - AddEmbeds(e). - AddComponents(makeComponents(id, p.Current, p.Total)). + err := NewMessageSender(p.m). + AddComponents(p.Container). SetReply(true). SetEphemeral(true). + SetComponentsV2(true). Send() - - PaginationEmbeds[id] = p + return err } func GetPaginationEmbed(id string) *PaginationEmbed { @@ -169,7 +155,7 @@ func (p *PaginationEmbed) Next(i *InteractionCreate) { 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 { i.Reply(&discordgo.InteractionResponseData{ Embeds: []*discordgo.MessageEmbed{ @@ -181,10 +167,10 @@ func (p *PaginationEmbed) Set(i *InteractionCreate, page int) { }, Flags: discordgo.MessageFlagsEphemeral, }) - return + return nil } - if page >= p.Total { + if page > p.Total { i.Reply(&discordgo.InteractionResponseData{ Embeds: []*discordgo.MessageEmbed{ { @@ -195,28 +181,29 @@ func (p *PaginationEmbed) Set(i *InteractionCreate, page int) { }, Flags: discordgo.MessageFlagsEphemeral, }) - return + return nil } 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{ - Embeds: []*discordgo.MessageEmbed{p.Embed}, - Components: []discordgo.MessageComponent{makeComponents(p.id, p.Current, p.Total)}, + err := i.Update(&discordgo.InteractionResponseData{ + Flags: discordgo.MessageFlagsIsComponentsV2, + Components: []discordgo.MessageComponent{p.Container}, }) + return err } func (p *PaginationEmbed) ShowModal(i *InteractionCreate) { i.ShowModal(&ModalData{ - CustomId: MakePaginationEmbedModal(p.id), + CustomId: MakePaginationEmbedModal(p.Id), Title: fmt.Sprintf("%s의 리스트", i.Session.State.User.Username), Components: []discordgo.MessageComponent{ discordgo.ActionsRow{ Components: []discordgo.MessageComponent{ discordgo.TextInput{ - CustomID: MakePaginationEmbedSetPage(p.id), + CustomID: MakePaginationEmbedSetPage(p.Id), Label: "페이지", Style: discordgo.TextInputShort, Placeholder: "이동할 페이지를 여기에 적어주세요.",