diff --git a/main.go b/main.go index d6b4f50..20a8878 100644 --- a/main.go +++ b/main.go @@ -15,8 +15,7 @@ import ( "git.wh64.net/muffin/goMuffin/configs" "git.wh64.net/muffin/goMuffin/databases" "git.wh64.net/muffin/goMuffin/handler" - dbmigrate "git.wh64.net/muffin/goMuffin/scripts/dbMigrate" - deleteallcommands "git.wh64.net/muffin/goMuffin/scripts/deleteAllCommands" + "git.wh64.net/muffin/goMuffin/scripts" "github.com/bwmarrin/discordgo" ) @@ -26,11 +25,11 @@ func main() { if len(os.Args) > 1 { switch strings.ToLower(os.Args[1]) { case "dbmigrate": - dbmigrate.DBMigrate() + scripts.DBMigrate() case "deleteallcommands": - deleteallcommands.DeleteAllCommands() + scripts.DeleteAllCommands() default: - panic(fmt.Errorf("[goMuffin] 명령어 인자에는 dbmigrate나 deleteallcommands만 올 수 있어요.")) + log.Fatalln(fmt.Errorf("[goMuffin] 명령어 인자에는 dbmigrate나 deleteallcommands만 올 수 있어요")) } return } @@ -54,6 +53,7 @@ func main() { go dg.AddHandler(handler.InteractionCreate) dg.Open() + defer dg.Close() go func() { for { @@ -77,10 +77,7 @@ func main() { go dg.ApplicationCommandCreate(dg.State.User.ID, "", cmd.ApplicationCommand) } - defer func() { - dg.Close() - databases.Client.Disconnect(context.TODO()) - }() + defer databases.Client.Disconnect(context.TODO()) log.Println("[goMuffin] 봇이 실행되고 있어요. 버전:", configs.MUFFIN_VERSION) sc := make(chan os.Signal, 1) diff --git a/scripts/dbMigrate.go b/scripts/dbMigrate.go new file mode 100644 index 0000000..22fde88 --- /dev/null +++ b/scripts/dbMigrate.go @@ -0,0 +1,192 @@ +package scripts + +import ( + "context" + "database/sql" + "fmt" + "os" + "sync" + "time" + + "git.wh64.net/muffin/goMuffin/configs" + + _ "github.com/go-sql-driver/mysql" + "go.mongodb.org/mongo-driver/v2/bson" + "go.mongodb.org/mongo-driver/v2/mongo" + "go.mongodb.org/mongo-driver/v2/mongo/options" +) + +var wg sync.WaitGroup + +// 이 스크립트는 MariaDB -> MongoDB로의 전환을 위해 만들었음. +func DBMigrate() { + mariaURL := os.Getenv("PREVIOUS_DATABASE_URL") + mongoURL := configs.Config.DatabaseURL + dbName := configs.Config.DBName + + dbConnectionQuery := "?parseTime=true" + + wg.Add(3) + + // statement -> text + go func() { + defer wg.Done() + + newDataList := []any{} + mariaDB, err := sql.Open("mysql", mariaURL+dbConnectionQuery) + if err != nil { + panic(err) + } + + mongoDB, err := mongo.Connect(options.Client().ApplyURI(mongoURL)) + if err != nil { + panic(err) + } + + defer mongoDB.Disconnect(context.TODO()) + defer mariaDB.Close() + rows, err := mariaDB.Query("select text, persona, created_at from statement;") + if err != nil { + panic(err) + } + + defer rows.Close() + + i := 1 + + for rows.Next() { + var text, persona string + var createdAt time.Time + + fmt.Printf("statement %d\n", i) + err = rows.Scan(&text, &persona, &createdAt) + if err != nil { + panic(err) + } + + if text == "" { + text = "살ㄹ려주세요" + } + + newDataList = append(newDataList, bson.M{ + "text": text, + "persona": persona, + "created_at": createdAt, + }) + i++ + } + _, err = mongoDB.Database(dbName).Collection("text").InsertMany(context.TODO(), newDataList) + if err != nil { + panic(err) + } + }() + + // nsfw_content -> text + go func() { + defer wg.Done() + + newDataList := []any{} + mariaDB, err := sql.Open("mysql", mariaURL+dbConnectionQuery) + if err != nil { + panic(err) + } + + mongoDB, err := mongo.Connect(options.Client().ApplyURI(mongoURL)) + if err != nil { + panic(err) + } + + defer mongoDB.Disconnect(context.TODO()) + defer mariaDB.Close() + rows, err := mariaDB.Query("select text, persona, created_at from nsfw_content;") + if err != nil { + panic(err) + } + + defer rows.Close() + + i := 1 + + for rows.Next() { + var text, persona string + var createdAt time.Time + + fmt.Printf("nsfw_content %d\n", i) + err = rows.Scan(&text, &persona, &createdAt) + if err != nil { + panic(err) + } + + if text == "" { + text = "살ㄹ려주세요" + } + + newDataList = append(newDataList, bson.M{ + "text": text, + "persona": persona, + "created_at": createdAt, + }) + i++ + } + + _, err = mongoDB.Database(dbName).Collection("text").InsertMany(context.TODO(), newDataList) + if err != nil { + panic(err) + } + }() + + // learn -> learn + go func() { + defer wg.Done() + + newDataList := []any{} + mariaDB, err := sql.Open("mysql", mariaURL+dbConnectionQuery) + if err != nil { + panic(err) + } + + mongoDB, err := mongo.Connect(options.Client().ApplyURI(mongoURL)) + if err != nil { + panic(err) + } + + defer mongoDB.Disconnect(context.TODO()) + defer mariaDB.Close() + rows, err := mariaDB.Query("select command, result, user_id, created_at from learn;") + if err != nil { + panic(err) + } + + defer rows.Close() + + i := 1 + + for rows.Next() { + var command, result, userId string + var createdAt time.Time + + fmt.Printf("learn %d\n", i) + err = rows.Scan(&command, &result, &userId, &createdAt) + if err != nil { + panic(err) + } + + newDataList = append(newDataList, bson.M{ + "command": command, + "result": result, + "user_id": userId, + "created_at": createdAt, + }) + i++ + } + + _, err = mongoDB.Database(dbName).Collection("learn").InsertMany(context.TODO(), newDataList) + if err != nil { + panic(err) + } + }() + + // 모든 고루틴이 끝날 떄 까지 대기 + wg.Wait() + fmt.Println("데이터 마이그레이션이 끝났어요.") +} diff --git a/scripts/deleteAllCommands.go b/scripts/deleteAllCommands.go new file mode 100644 index 0000000..5614974 --- /dev/null +++ b/scripts/deleteAllCommands.go @@ -0,0 +1,49 @@ +package scripts + +import ( + "flag" + "fmt" + "io" + "net/http" + "os" + "strings" + + "git.wh64.net/muffin/goMuffin/configs" + "github.com/bwmarrin/discordgo" +) + +func DeleteAllCommands() { + var answer string + id := flag.String("id", "", "디스코드 봇의 토큰") + + flag.Parse() + + fmt.Printf("정말로 모든 명령어를 삭제하시겠어요? [y/N]: ") + fmt.Scanf("%s", &answer) + if strings.ToLower(answer) != "y" && strings.ToLower(answer) != "yes" { + os.Exit(1) + } + + if *id == "" { + panic(fmt.Errorf("--id 플래그의 값이 필요해요.")) + } + + c := http.Client{} + req, err := http.NewRequest("PUT", discordgo.EndpointApplicationGlobalCommands(*id), nil) + if err != nil { + panic(err) + } + + req.Header.Add("Authorization", "Bot "+configs.Config.Bot.Token) + + resp, err := c.Do(req) + if err != nil { + panic(err) + } + + bytes, err := io.ReadAll(resp.Body) + if err != nil { + panic(err) + } + fmt.Println(string(bytes)) +}