package commands import ( "context" "fmt" "log" "strings" "git.wh64.net/muffin/goMuffin/chatbot" "git.wh64.net/muffin/goMuffin/configs" "git.wh64.net/muffin/goMuffin/databases" "git.wh64.net/muffin/goMuffin/utils" "github.com/bwmarrin/discordgo" ) type chatCommandType string var ( chatCommandChatting chatCommandType = "하기" chatCommandList chatCommandType = "목록" chatCommandCreate chatCommandType = "생성" ) var ChatCommand *Command = &Command{ ApplicationCommand: &discordgo.ApplicationCommand{ Name: "대화", Description: "이 봇이랑 대화해요.", Options: []*discordgo.ApplicationCommandOption{ { Type: discordgo.ApplicationCommandOptionSubCommand, Name: string(chatCommandList), Description: "채팅 목록을 나열해요.", }, { Type: discordgo.ApplicationCommandOptionSubCommand, Name: string(chatCommandCreate), Description: "새로운 채팅을 생성해요.", Options: []*discordgo.ApplicationCommandOption{ { Type: discordgo.ApplicationCommandOptionString, Name: "이름", Description: "채팅의 이름을 정해요. (25자 이내)", MaxLength: 25, Required: true, }, }, }, { Type: discordgo.ApplicationCommandOptionSubCommand, Name: string(chatCommandChatting), Description: "이 봇이랑 대화해요.", Options: []*discordgo.ApplicationCommandOption{ { Type: discordgo.ApplicationCommandOptionString, Name: "내용", Description: "대화할 내용", Required: true, }, }, }, }, }, Aliases: []string{"채팅"}, DetailedDescription: &DetailedDescription{ Usage: fmt.Sprintf("%s대화 (목록/생성) [채팅 이름]", configs.Config.Bot.Prefix), Examples: []string{ fmt.Sprintf("%s대화 목록", configs.Config.Bot.Prefix), fmt.Sprintf("%s대화 생성 머핀 냠냠", configs.Config.Bot.Prefix), }, }, Category: Chatting, RegisterApplicationCommand: true, RegisterMessageCommand: true, Flags: CommandFlagsIsRegistered | CommandFlagsIsBlocked, ChatInputRun: func(ctx *ChatInputContext) error { ctx.Inter.DeferReply(nil) var cType chatCommandType var str string if opt, ok := ctx.Inter.Options[string(chatCommandChatting)]; ok { cType = chatCommandChatting str = opt.Options[0].StringValue() } else if opt, ok := ctx.Inter.Options[string(chatCommandCreate)]; ok { cType = chatCommandCreate str = opt.Options[0].StringValue() } else if _, ok := ctx.Inter.Options[string(chatCommandList)]; ok { cType = chatCommandList } return chatCommandRun(cType, ctx.Inter, ctx.Inter.User, str) }, MessageRun: func(ctx *MsgContext) error { if len((*ctx.Args)) < 1 { goto RequiredValue } switch (*ctx.Args)[0] { case string(chatCommandCreate): if len((*ctx.Args)) < 2 { return utils.NewMessageSender(ctx.Msg). AddComponents(utils.GetErrorContainer(discordgo.TextDisplay{Content: "채팅방의 이름을 정해야해요."})). SetComponentsV2(true). SetReply(true). Send() } return chatCommandRun(chatCommandCreate, ctx.Msg, ctx.Msg.Author, string([]rune(strings.Join((*ctx.Args)[1:], " "))[:25])) case string(chatCommandList): return chatCommandRun(chatCommandList, ctx.Msg, ctx.Msg.Author, "") default: goto RequiredValue } RequiredValue: return utils.NewMessageSender(ctx.Msg). AddComponents(utils.GetErrorContainer(discordgo.TextDisplay{Content: "명령어의 첫번째 인자는 `생성`, `목록`중에 하나여야 해요."})). SetComponentsV2(true). SetReply(true). Send() }, } func chatCommandRun(cType chatCommandType, m any, user *discordgo.User, contentOrName string) error { switch cType { // 채팅하기는 슬래시 커맨드만 가능 case chatCommandChatting: i := m.(*utils.InteractionCreate) str, err := chatbot.ChatBot.GetResponse(user, contentOrName) if err != nil { log.Println(err) i.EditReply(&utils.InteractionEdit{ Content: &str, }) return nil } result := chatbot.ParseResult(str, i.Session, i) return i.EditReply(&utils.InteractionEdit{ Content: &result, }) case chatCommandCreate: _, err := databases.CreateChat(user.ID, contentOrName) if err != nil { return err } return utils.NewMessageSender(m). AddComponents(utils.GetSuccessContainer(discordgo.TextDisplay{Content: fmt.Sprintf("%s를 생성했어요. 이제 현재 채팅은 %s에요.", contentOrName, contentOrName)})). SetComponentsV2(true). SetReply(true). Send() case chatCommandList: var data []databases.Chat var sections []discordgo.Section var containers []*discordgo.Container cur, err := databases.Database.Chats.Find(context.TODO(), databases.Chat{UserId: user.ID}) if err != nil { return err } err = cur.All(context.TODO(), &data) if err != nil { return err } if len(data) == 0 { return utils.NewMessageSender(m). AddComponents(utils.GetErrorContainer(discordgo.TextDisplay{Content: "채팅이 단 하나도 없어요. 새로운 채팅을 만들거나, 대화를 시작해 채팅을 만들어주세요."})). SetComponentsV2(true). SetReply(true). SetEphemeral(true). Send() } for i, data := range data { sections = append(sections, discordgo.Section{ Accessory: discordgo.Button{ Label: "선택", Style: discordgo.SuccessButton, CustomID: utils.MakeSelectChat(data.Id.Hex(), i+1, user.ID), }, Components: []discordgo.MessageComponent{ discordgo.TextDisplay{ Content: fmt.Sprintf("%d. %s\n", i+1, data.Name), }, }, }) } textDisplay := discordgo.TextDisplay{Content: fmt.Sprintf("### %s님의 채팅목록", user.GlobalName)} container := &discordgo.Container{Components: []discordgo.MessageComponent{textDisplay}} for i, section := range sections { container.Components = append(container.Components, section, discordgo.Separator{}) if (i+1)%10 == 0 { containers = append(containers, container) container = &discordgo.Container{Components: []discordgo.MessageComponent{textDisplay}} continue } } if len(container.Components) > 1 { containers = append(containers, container) } return utils.PaginationEmbedBuilder(m). AddContainers(containers...). Start() } return nil }