feat: Add register command

This commit is contained in:
Siwoo Jeon 2025-06-19 21:12:07 +09:00
parent 71fa0b506a
commit 05f7bd07b7
Signed by: migan
GPG key ID: 036E9A8C5E8E48DA
9 changed files with 206 additions and 9 deletions

View file

@ -12,16 +12,18 @@ DATABASE_AUTH_SOURCE= # 기본 값: admin
## 필수 값
DATABASE_NAME=
## 데이터베이스 마이그레이션용
PREVIOUS_DATABASE_URL=
# 봇
BOT_TOKEN=
BOT_PREFIX=
BOT_OWNER_ID=
# 서비스
SERVICE_PRIVACY_POLICY_URL=
SERVICE_TERM_OF_SERVICE_URL=
# 챗봇
CHATBOT_GEMINI_TOKEN=
CHATBOT_GEMINI_PROMPT_PATH=
CHATBOT_GEMINI_MODEL= # 기본 값은 gemini-2.5-flash
CHATBOT_TRAIN_USER_ID= # 필수 아님
CHATBOT_TRAIN_USER_ID= # 필수 아님

View file

@ -187,12 +187,15 @@ func (d *DiscommandStruct) ChatInputRun(name string, s *discordgo.Session, inter
}
}
func (d *DiscommandStruct) ComponentRun(s *discordgo.Session, i *discordgo.InteractionCreate) {
func (d *DiscommandStruct) ComponentRun(s *discordgo.Session, inter *discordgo.InteractionCreate) {
i := &utils.InteractionCreate{
InteractionCreate: inter,
Session: s,
}
i.InteractionCreate.User = utils.GetInteractionUser(inter)
data := &ComponentContext{
Inter: &utils.InteractionCreate{
InteractionCreate: i,
Session: s,
},
Inter: i,
}
for _, c := range d.Components {

70
commands/register.go Normal file
View file

@ -0,0 +1,70 @@
package commands
import (
"fmt"
"git.wh64.net/muffin/goMuffin/configs"
"git.wh64.net/muffin/goMuffin/databases"
"git.wh64.net/muffin/goMuffin/utils"
"github.com/bwmarrin/discordgo"
)
var RegisterCommand *Command = &Command{
ApplicationCommand: &discordgo.ApplicationCommand{
Name: "가입",
Description: "이 봇에 가입해요.",
},
DetailedDescription: &DetailedDescription{
Usage: fmt.Sprintf("%s가입", configs.Config.Bot.Prefix),
},
Category: General,
RegisterMessageCommand: true,
RegisterApplicationCommand: true,
MessageRun: func(ctx *MsgContext) {
registerRun(ctx.Msg, ctx.Msg.Author.ID, ctx.Msg.Session.State.User.Username)
},
ChatInputRun: func(ctx *ChatInputContext) {
registerRun(ctx.Inter, ctx.Inter.User.ID, ctx.Inter.Session.State.User.Username)
},
}
func registerRun(m any, userId, botName string) {
if databases.Database.IsUser(userId) {
utils.NewMessageSender(m).
AddComponents(utils.GetErrorContainer(discordgo.TextDisplay{Content: fmt.Sprintf("당신은 이미 가입되어있어요. 만약 탈퇴를 원하시면 %s탈퇴를 이용해주세요.", configs.Config.Bot.Prefix)})).
SetComponentsV2(true).
SetReply(true).
Send()
return
}
utils.NewMessageSender(m).
AddComponents(discordgo.Container{
Components: []discordgo.MessageComponent{
discordgo.TextDisplay{
Content: fmt.Sprintf("### %s 가입\n해당 서비스에 가입하실려면 [개인정보처리방침](%s)과 [서비스 이용약관](%s)에 동의해야해요.",
botName,
configs.Config.Service.PrivacyPolicyURL,
configs.Config.Service.TermOfServiceURL,
),
},
discordgo.ActionsRow{
Components: []discordgo.MessageComponent{
discordgo.Button{
CustomID: utils.MakeServiceAgree(userId),
Label: "동의 후 가입",
Style: discordgo.SuccessButton,
},
discordgo.Button{
CustomID: utils.MakeServiceDisagree(userId),
Label: "취소",
Style: discordgo.DangerButton,
},
},
},
},
}).
SetComponentsV2(true).
SetReply(true).
Send()
}

73
components/register.go Normal file
View file

@ -0,0 +1,73 @@
package components
import (
"context"
"fmt"
"log"
"strings"
"time"
"git.wh64.net/muffin/goMuffin/commands"
"git.wh64.net/muffin/goMuffin/databases"
"git.wh64.net/muffin/goMuffin/utils"
"github.com/bwmarrin/discordgo"
)
var RegisterComponent *commands.Component = &commands.Component{
Parse: func(ctx *commands.ComponentContext) bool {
customId := ctx.Inter.MessageComponentData().CustomID
if !strings.HasPrefix(customId, utils.ServiceAgree) && !strings.HasPrefix(customId, utils.ServiceDisagree) {
return false
}
if ctx.Inter.User.ID != utils.GetServicesUserId(customId) {
return false
}
return true
},
Run: func(ctx *commands.ComponentContext) {
ctx.Inter.DeferUpdate()
customId := ctx.Inter.MessageComponentData().CustomID
flags := discordgo.MessageFlagsIsComponentsV2
switch {
case strings.HasPrefix(customId, utils.ServiceAgree):
_, err := databases.Database.Users.InsertOne(context.TODO(), databases.InsertUser{
UserId: ctx.Inter.User.ID,
CreatedAt: time.Now(),
})
if err != nil {
log.Println(err)
ctx.Inter.EditReply(&utils.InteractionEdit{
Flags: &flags,
Components: &[]discordgo.MessageComponent{
utils.GetErrorContainer(discordgo.TextDisplay{
Content: "가입을 하다가 오류가 생겼어요.",
}),
},
})
return
}
ctx.Inter.EditReply(&utils.InteractionEdit{
Flags: &flags,
Components: &[]discordgo.MessageComponent{
utils.GetSuccessContainer(discordgo.TextDisplay{
Content: fmt.Sprintf("가입을 했어요. 이제 %s의 모든 기능을 사용할 수 있어요.", ctx.Inter.Session.State.User.Username),
}),
},
})
return
case strings.HasPrefix(customId, utils.ServiceDisagree):
ctx.Inter.EditReply(&utils.InteractionEdit{
Flags: &flags,
Components: &[]discordgo.MessageComponent{
utils.GetDeclineContainer(discordgo.TextDisplay{
Content: "가입을 거부했어요.",
}),
},
})
return
}
},
}

View file

@ -40,11 +40,17 @@ type databaseConfig struct {
Port int
}
type serviceConfig struct {
PrivacyPolicyURL string
TermOfServiceURL string
}
// MuffinConfig for Muffin bot
type MuffinConfig struct {
Bot botConfig
Database databaseConfig
Chatbot chatbotConfig
Service serviceConfig
// Deprecated: Use Chatbot.Train
Train trainConfig
@ -111,4 +117,9 @@ func setConfig(config *MuffinConfig) {
}
config.Train = config.Chatbot.Train
config.Service = serviceConfig{
PrivacyPolicyURL: getRequiredValue("SERVICE_PRIVACY_POLICY_URL"),
TermOfServiceURL: getRequiredValue("SERVICE_TERM_OF_SERVICE_URL"),
}
}

View file

@ -32,9 +32,11 @@ func init() {
go commands.Discommand.LoadCommand(commands.ReloadPromptCommand)
go commands.Discommand.LoadCommand(commands.SwitchModeCommand)
go commands.Discommand.LoadCommand(commands.ChatCommand)
go commands.Discommand.LoadCommand(commands.RegisterCommand)
go commands.Discommand.LoadComponent(components.DeleteLearnedDataComponent)
go commands.Discommand.LoadComponent(components.PaginationEmbedComponent)
go commands.Discommand.LoadComponent(components.RegisterComponent)
go commands.Discommand.LoadModal(modals.PaginationEmbedModal)
}

View file

@ -16,6 +16,9 @@ const (
PaginationEmbedNext = "#muffin-pages/next$"
PaginationEmbedModal = "#muffin-pages/modal$"
PaginationEmbedSetPage = "#muffin-pages/modal/set$"
ServiceAgree = "#muffin/serviceAgree@"
ServiceDisagree = "#muffin/serviceDisagree@"
)
func MakeDeleteLearnedData(id string, number int, userId string) string {
@ -73,3 +76,22 @@ func GetPaginationEmbedId(customId string) string {
func GetPaginationEmbedUserId(id string) string {
return RegexpPaginationEmbedId.FindAllStringSubmatch(id, 1)[0][1]
}
func MakeServiceAgree(userId string) string {
return fmt.Sprintf("%s%s", ServiceAgree, userId)
}
func MakeServiceDisagree(userId string) string {
return fmt.Sprintf("%s%s", ServiceDisagree, userId)
}
func GetServicesUserId(customId string) string {
switch {
case strings.HasPrefix(customId, ServiceAgree):
return customId[len(ServiceAgree):]
case strings.HasPrefix(customId, ServiceDisagree):
return customId[len(ServiceDisagree):]
default:
return customId
}
}

View file

@ -25,6 +25,19 @@ func GetErrorContainer(components ...discordgo.MessageComponent) *discordgo.Cont
return c
}
func GetDeclineContainer(components ...discordgo.MessageComponent) *discordgo.Container {
c := &discordgo.Container{
Components: []discordgo.MessageComponent{
discordgo.TextDisplay{
Content: "### ❌ 거부",
},
},
}
c.Components = append(c.Components, components...)
return c
}
func GetSuccessContainer(components ...discordgo.MessageComponent) *discordgo.Container {
c := &discordgo.Container{
Components: []discordgo.MessageComponent{

View file

@ -53,6 +53,7 @@ func GetInteractionOptions(i *discordgo.InteractionCreate) map[string]*discordgo
return optsMap
}
// NOTE: It's only can ApplicationCommand
func GetInteractionUser(i *discordgo.InteractionCreate) *discordgo.User {
if i.Member != nil {
return i.Member.User