feat: set page in list
This commit is contained in:
parent
c3955f213b
commit
2e90e14116
10 changed files with 281 additions and 29 deletions
|
@ -7,9 +7,12 @@ import (
|
|||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
type modalRun func(ctx *ModalContext)
|
||||
type messageRun func(ctx *MsgContext)
|
||||
type chatInputRun func(ctx *ChatInputContext)
|
||||
type componentRun func(ctx *ComponentContext)
|
||||
|
||||
type modalParse func(ctx *ModalContext) bool
|
||||
type componentParse func(ctx *ComponentContext) bool
|
||||
|
||||
type Category string
|
||||
|
@ -32,6 +35,7 @@ type DiscommandStruct struct {
|
|||
Commands map[string]*Command
|
||||
Components []*Component
|
||||
Aliases map[string]string
|
||||
Modals []*Modal
|
||||
}
|
||||
|
||||
type MsgContext struct {
|
||||
|
@ -53,24 +57,38 @@ type ComponentContext struct {
|
|||
Component *Component
|
||||
}
|
||||
|
||||
type ModalContext struct {
|
||||
Inter *utils.InteractionCreate
|
||||
Modal *Modal
|
||||
}
|
||||
|
||||
type Component struct {
|
||||
Parse componentParse
|
||||
Run componentRun
|
||||
}
|
||||
|
||||
type Modal struct {
|
||||
Parse modalParse
|
||||
Run modalRun
|
||||
}
|
||||
|
||||
const (
|
||||
Chatting Category = "채팅"
|
||||
General Category = "일반"
|
||||
)
|
||||
|
||||
var commandMutex sync.Mutex
|
||||
var componentMutex sync.Mutex
|
||||
var (
|
||||
commandMutex sync.Mutex
|
||||
componentMutex sync.Mutex
|
||||
modalMutex sync.Mutex
|
||||
)
|
||||
|
||||
func new() *DiscommandStruct {
|
||||
discommand := DiscommandStruct{
|
||||
Commands: map[string]*Command{},
|
||||
Aliases: map[string]string{},
|
||||
Components: []*Component{},
|
||||
Modals: []*Modal{},
|
||||
}
|
||||
return &discommand
|
||||
}
|
||||
|
@ -92,6 +110,12 @@ func (d *DiscommandStruct) LoadComponent(c *Component) {
|
|||
d.Components = append(d.Components, c)
|
||||
}
|
||||
|
||||
func (d *DiscommandStruct) LoadModal(m *Modal) {
|
||||
defer modalMutex.Unlock()
|
||||
modalMutex.Lock()
|
||||
d.Modals = append(d.Modals, m)
|
||||
}
|
||||
|
||||
func (d *DiscommandStruct) MessageRun(name string, s *discordgo.Session, m *discordgo.MessageCreate, args []string) {
|
||||
if command, ok := d.Commands[name]; ok {
|
||||
command.MessageRun(&MsgContext{s, m, &args, command})
|
||||
|
@ -109,18 +133,42 @@ func (d *DiscommandStruct) ChatInputRun(name string, s *discordgo.Session, i *di
|
|||
}
|
||||
|
||||
func (d *DiscommandStruct) ComponentRun(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
for _, c := range d.Components {
|
||||
if (!c.Parse(&ComponentContext{s, &utils.InteractionCreate{
|
||||
data := &ComponentContext{
|
||||
Session: s,
|
||||
Inter: &utils.InteractionCreate{
|
||||
InteractionCreate: i,
|
||||
Session: s,
|
||||
}, c})) {
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range d.Components {
|
||||
data.Component = c
|
||||
|
||||
if !c.Parse(data) {
|
||||
continue
|
||||
}
|
||||
|
||||
c.Run(&ComponentContext{s, &utils.InteractionCreate{
|
||||
c.Run(data)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DiscommandStruct) ModalRun(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
data := &ModalContext{
|
||||
Inter: &utils.InteractionCreate{
|
||||
InteractionCreate: i,
|
||||
Session: s,
|
||||
}, c})
|
||||
},
|
||||
}
|
||||
|
||||
for _, m := range d.Modals {
|
||||
data.Modal = m
|
||||
|
||||
if !m.Parse(data) {
|
||||
continue
|
||||
}
|
||||
|
||||
m.Run(data)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,7 +129,6 @@ func learnedDataListRun(s *discordgo.Session, m any, args *[]string) {
|
|||
}
|
||||
|
||||
if match := utils.RegexpLearnQueryResult.FindStringSubmatch(query); match != nil {
|
||||
fmt.Println(match[1])
|
||||
filter = append(filter, bson.E{
|
||||
Key: "result",
|
||||
Value: bson.M{
|
||||
|
@ -139,7 +138,6 @@ func learnedDataListRun(s *discordgo.Session, m any, args *[]string) {
|
|||
}
|
||||
|
||||
if match := utils.RegexpLearnQueryLength.FindStringSubmatch(query); match != nil {
|
||||
fmt.Println(1)
|
||||
var err error
|
||||
length, err = strconv.Atoi(match[1])
|
||||
fmt.Printf("err: %v\n", err)
|
||||
|
|
|
@ -15,13 +15,12 @@ var PaginationEmbedComponent *commands.Component = &commands.Component{
|
|||
if i.MessageComponentData().ComponentType == discordgo.ButtonComponent {
|
||||
customId := i.MessageComponentData().CustomID
|
||||
|
||||
if !strings.HasPrefix(customId, utils.PaginationEmbedPrev) && !strings.HasPrefix(customId, utils.PaginationEmbedNext) {
|
||||
if !strings.HasPrefix(customId, utils.PaginationEmbedPrev) && !strings.HasPrefix(customId, utils.PaginationEmbedNext) && !strings.HasPrefix(customId, utils.PaginationEmbedPages) {
|
||||
return false
|
||||
}
|
||||
|
||||
id := utils.GetPaginationEmbedId(customId)
|
||||
userId := utils.GetPaginationEmbedUserId(id)
|
||||
|
||||
if i.Member.User.ID != userId {
|
||||
return false
|
||||
}
|
||||
|
@ -41,8 +40,10 @@ var PaginationEmbedComponent *commands.Component = &commands.Component{
|
|||
|
||||
if strings.HasPrefix(customId, utils.PaginationEmbedPrev) {
|
||||
p.Prev(ctx.Inter)
|
||||
} else {
|
||||
} else if strings.HasPrefix(customId, utils.PaginationEmbedNext) {
|
||||
p.Next(ctx.Inter)
|
||||
} else {
|
||||
p.ShowModal(ctx.Inter)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"git.wh64.net/muffin/goMuffin/utils"
|
||||
)
|
||||
|
||||
const MUFFIN_VERSION = "5.1.0-gopher_dev.250516a"
|
||||
const MUFFIN_VERSION = "5.1.0-gopher_dev.250517a"
|
||||
|
||||
var updatedString string = utils.RegexpDecimals.FindAllStringSubmatch(MUFFIN_VERSION, -1)[3][0]
|
||||
|
||||
|
|
|
@ -11,5 +11,7 @@ func InteractionCreate(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|||
return
|
||||
} else if i.Type == discordgo.InteractionMessageComponent {
|
||||
commands.Discommand.ComponentRun(s, i)
|
||||
} else if i.Type == discordgo.InteractionModalSubmit {
|
||||
commands.Discommand.ModalRun(s, i)
|
||||
}
|
||||
}
|
||||
|
|
3
main.go
3
main.go
|
@ -14,6 +14,7 @@ import (
|
|||
"git.wh64.net/muffin/goMuffin/configs"
|
||||
"git.wh64.net/muffin/goMuffin/databases"
|
||||
"git.wh64.net/muffin/goMuffin/handler"
|
||||
"git.wh64.net/muffin/goMuffin/modals"
|
||||
"git.wh64.net/muffin/goMuffin/scripts"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
"github.com/devproje/commando"
|
||||
|
@ -77,6 +78,8 @@ func main() {
|
|||
go commands.Discommand.LoadComponent(components.DeleteLearnedDataComponent)
|
||||
go commands.Discommand.LoadComponent(components.PaginationEmbedComponent)
|
||||
|
||||
go commands.Discommand.LoadModal(modals.PaginationEmbedModal)
|
||||
|
||||
go dg.AddHandler(handler.MessageCreate)
|
||||
go dg.AddHandler(handler.InteractionCreate)
|
||||
|
||||
|
|
66
modals/paginationEmbed.go
Normal file
66
modals/paginationEmbed.go
Normal file
|
@ -0,0 +1,66 @@
|
|||
package modals
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.wh64.net/muffin/goMuffin/commands"
|
||||
"git.wh64.net/muffin/goMuffin/utils"
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
var PaginationEmbedModal *commands.Modal = &commands.Modal{
|
||||
Parse: func(ctx *commands.ModalContext) bool {
|
||||
i := ctx.Inter
|
||||
data := i.ModalSubmitData()
|
||||
customId := data.CustomID
|
||||
|
||||
if data.Components[0].Type() != discordgo.ActionsRowComponent {
|
||||
return false
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(customId, utils.PaginationEmbedModal) {
|
||||
return false
|
||||
}
|
||||
|
||||
id := utils.GetPaginationEmbedId(customId)
|
||||
userId := utils.GetPaginationEmbedUserId(id)
|
||||
|
||||
if i.Member.User.ID != userId {
|
||||
return false
|
||||
}
|
||||
|
||||
if utils.GetPaginationEmbed(id) == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
cmp := data.Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput)
|
||||
|
||||
if _, err := strconv.Atoi(cmp.Value); err != nil {
|
||||
i.Reply(&discordgo.InteractionResponseData{
|
||||
Embeds: []*discordgo.MessageEmbed{
|
||||
{
|
||||
Title: "❌ 오류",
|
||||
Description: "해당 값은 숫자여야해요.",
|
||||
Color: utils.EmbedFail,
|
||||
},
|
||||
},
|
||||
Flags: discordgo.MessageFlagsEphemeral,
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
Run: func(ctx *commands.ModalContext) {
|
||||
data := ctx.Inter.ModalSubmitData()
|
||||
customId := data.CustomID
|
||||
id := utils.GetPaginationEmbedId(customId)
|
||||
p := utils.GetPaginationEmbed(id)
|
||||
cmp := data.Components[0].(*discordgo.ActionsRow).Components[0].(*discordgo.TextInput)
|
||||
|
||||
page, _ := strconv.Atoi(cmp.Value)
|
||||
|
||||
p.Set(ctx.Inter, page)
|
||||
},
|
||||
}
|
|
@ -13,9 +13,11 @@ const (
|
|||
DeleteLearnedDataUserId = "#muffin/deleteLearnedData@"
|
||||
DeleteLearnedDataCancel = "#muffin/deleteLearnedData/cancel@"
|
||||
|
||||
PaginationEmbedPrev = "#muffin-pages/prev$"
|
||||
PaginationEmbedPages = "#muffin-pages/pages$"
|
||||
PaginationEmbedNext = "#muffin-pages/next$"
|
||||
PaginationEmbedPrev = "#muffin-pages/prev$"
|
||||
PaginationEmbedPages = "#muffin-pages/pages$"
|
||||
PaginationEmbedNext = "#muffin-pages/next$"
|
||||
PaginationEmbedModal = "#muffin-pages/modal$"
|
||||
PaginationEmbedSetPage = "#muffin-pages/modal/set$"
|
||||
)
|
||||
|
||||
func MakeDeleteLearnedData(id string, number int) string {
|
||||
|
@ -49,21 +51,36 @@ func MakePaginationEmbedPrev(id string) string {
|
|||
return fmt.Sprintf("%s%s", PaginationEmbedPrev, id)
|
||||
}
|
||||
|
||||
func MakePaginationEmbedPages(id string, total, current int) string {
|
||||
return fmt.Sprintf("%s%s/%d/%d", PaginationEmbedPages, id, total, current)
|
||||
func MakePaginationEmbedPages(id string) string {
|
||||
return fmt.Sprintf("%s%s", PaginationEmbedPages, id)
|
||||
}
|
||||
|
||||
func MakePaginationEmbedNext(id string) string {
|
||||
return fmt.Sprintf("%s%s", PaginationEmbedNext, id)
|
||||
}
|
||||
|
||||
func MakePaginationEmbedModal(id string) string {
|
||||
return fmt.Sprintf("%s%s", PaginationEmbedModal, id)
|
||||
}
|
||||
|
||||
func MakePaginationEmbedSetPage(id string) string {
|
||||
return fmt.Sprintf("%s%s", PaginationEmbedSetPage, id)
|
||||
}
|
||||
|
||||
func GetPaginationEmbedId(customId string) string {
|
||||
if strings.HasPrefix(customId, PaginationEmbedPrev) {
|
||||
switch {
|
||||
case strings.HasPrefix(customId, PaginationEmbedPrev):
|
||||
return customId[len(PaginationEmbedPrev):]
|
||||
} else if strings.HasPrefix(customId, PaginationEmbedPages) {
|
||||
case strings.HasPrefix(customId, PaginationEmbedPages):
|
||||
return customId[len(PaginationEmbedPages):]
|
||||
} else {
|
||||
case strings.HasPrefix(customId, PaginationEmbedNext):
|
||||
return customId[len(PaginationEmbedNext):]
|
||||
case strings.HasPrefix(customId, PaginationEmbedModal):
|
||||
return customId[len(PaginationEmbedModal):]
|
||||
case strings.HasPrefix(customId, PaginationEmbedSetPage):
|
||||
return customId[len(PaginationEmbedSetPage):]
|
||||
default:
|
||||
return customId
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
package utils
|
||||
|
||||
import "github.com/bwmarrin/discordgo"
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
type ModalData struct {
|
||||
CustomId string `json:"custom_id"`
|
||||
Title string `json:"title"`
|
||||
Components []discordgo.MessageComponent `json:"components"`
|
||||
}
|
||||
|
||||
// InteractionCreate custom data of discordgo.InteractionCreate
|
||||
type InteractionCreate struct {
|
||||
|
@ -62,3 +76,44 @@ func (i *InteractionCreate) Update(data *discordgo.InteractionResponseData) {
|
|||
Data: data,
|
||||
})
|
||||
}
|
||||
|
||||
func (i *InteractionCreate) ShowModal(data *ModalData) error {
|
||||
var reqData struct {
|
||||
Type discordgo.InteractionResponseType `json:"type"`
|
||||
Data ModalData `json:"data"`
|
||||
}
|
||||
|
||||
reqData.Type = discordgo.InteractionResponseModal
|
||||
reqData.Data = *data
|
||||
bin, err := json.Marshal(reqData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(bin)
|
||||
|
||||
req, err := http.NewRequest("POST", discordgo.EndpointInteractionResponse(i.ID, i.Token), buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Add("Authorization", i.Session.Identify.Token)
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
|
||||
resp, err := i.Session.Client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
respBin, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("%s", string(respBin))
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,13 +14,18 @@ type PaginationEmbed struct {
|
|||
Current int
|
||||
Total int
|
||||
id string
|
||||
s *discordgo.Session
|
||||
desc string
|
||||
}
|
||||
|
||||
var PaginationEmbeds = make(map[string]*PaginationEmbed)
|
||||
|
||||
func makeComponents(id string, current, total int) *[]discordgo.MessageComponent {
|
||||
disabled := false
|
||||
|
||||
if total == 1 {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
return &[]discordgo.MessageComponent{
|
||||
discordgo.ActionsRow{
|
||||
Components: []discordgo.MessageComponent{
|
||||
|
@ -28,19 +33,19 @@ func makeComponents(id string, current, total int) *[]discordgo.MessageComponent
|
|||
Style: discordgo.PrimaryButton,
|
||||
Label: "이전",
|
||||
CustomID: MakePaginationEmbedPrev(id),
|
||||
Disabled: false,
|
||||
Disabled: disabled,
|
||||
},
|
||||
discordgo.Button{
|
||||
Style: discordgo.SecondaryButton,
|
||||
Label: fmt.Sprintf("(%d/%d)", current, total),
|
||||
CustomID: MakePaginationEmbedPages(id, current, total),
|
||||
Disabled: true,
|
||||
CustomID: MakePaginationEmbedPages(id),
|
||||
Disabled: disabled,
|
||||
},
|
||||
discordgo.Button{
|
||||
Style: discordgo.PrimaryButton,
|
||||
Label: "다음",
|
||||
CustomID: MakePaginationEmbedNext(id),
|
||||
Disabled: false,
|
||||
Disabled: disabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -76,8 +81,6 @@ func StartPaginationEmbed(s *discordgo.Session, m any, e *discordgo.MessageEmbed
|
|||
Current: 1,
|
||||
Total: len(data),
|
||||
id: id,
|
||||
s: s,
|
||||
desc: defaultDesc,
|
||||
}
|
||||
|
||||
if len(data) <= 0 {
|
||||
|
@ -160,3 +163,62 @@ func (p *PaginationEmbed) Next(i *InteractionCreate) {
|
|||
Components: *makeComponents(p.id, p.Current, p.Total),
|
||||
})
|
||||
}
|
||||
|
||||
func (p *PaginationEmbed) Set(i *InteractionCreate, page int) {
|
||||
if page <= 0 {
|
||||
i.Reply(&discordgo.InteractionResponseData{
|
||||
Embeds: []*discordgo.MessageEmbed{
|
||||
{
|
||||
Title: "❌ 오류",
|
||||
Description: "해당 값은 0보다 커야해요.",
|
||||
Color: EmbedFail,
|
||||
},
|
||||
},
|
||||
Flags: discordgo.MessageFlagsEphemeral,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if page >= p.Total {
|
||||
i.Reply(&discordgo.InteractionResponseData{
|
||||
Embeds: []*discordgo.MessageEmbed{
|
||||
{
|
||||
Title: "❌ 오류",
|
||||
Description: "해당 값은 총 페이지의 수보다 작아야해요.",
|
||||
Color: EmbedFail,
|
||||
},
|
||||
},
|
||||
Flags: discordgo.MessageFlagsEphemeral,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
p.Current = page
|
||||
|
||||
p.Embed.Description = makeDesc(p.desc, p.Data[p.Current-1])
|
||||
|
||||
i.Update(&discordgo.InteractionResponseData{
|
||||
Embeds: []*discordgo.MessageEmbed{p.Embed},
|
||||
Components: *makeComponents(p.id, p.Current, p.Total),
|
||||
})
|
||||
}
|
||||
|
||||
func (p *PaginationEmbed) ShowModal(i *InteractionCreate) {
|
||||
i.ShowModal(&ModalData{
|
||||
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),
|
||||
Label: "페이지",
|
||||
Style: discordgo.TextInputShort,
|
||||
Placeholder: "이동할 페이지를 여기에 적어주세요.",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue