From 581990a52fdebca4ab6eba1a1562cc1123283fcf Mon Sep 17 00:00:00 2001 From: Sean Du Date: Tue, 28 Apr 2026 19:25:20 +0800 Subject: [PATCH] Refactor user bootstrap Signed-off-by: Sean Du --- internal/handler/ghome/account/login.go | 209 ++++++++++++++++-------- internal/handler/webui/upload.go | 1 - internal/model/user/userunitdata.go | 1 - internal/startup/database.go | 1 - internal/startup/defaultuser.go | 26 +++ internal/startup/startup.go | 1 + 6 files changed, 169 insertions(+), 70 deletions(-) create mode 100644 internal/startup/defaultuser.go diff --git a/internal/handler/ghome/account/login.go b/internal/handler/ghome/account/login.go index d76a7f0..cf68a2c 100644 --- a/internal/handler/ghome/account/login.go +++ b/internal/handler/ghome/account/login.go @@ -11,6 +11,7 @@ import ( unitapischema "honoka-chan/internal/schema/api/unit" ghomeschema "honoka-chan/internal/schema/ghome" "honoka-chan/internal/session" + "honoka-chan/pkg/db" "honoka-chan/pkg/utils" "net/url" "strconv" @@ -21,6 +22,15 @@ import ( "github.com/go-think/openssl" ) +const ( + defaultUserID = 377385143 + defaultAwardID = 113 // 极推穗乃果 + defaultBackgroundID = 65 // 穗乃果的房间 + defaultUnitID = 338 // 高坂穂乃果 直到那天来临 + defaultUserName = "梦路" + defaultUserDesc = "你好。" +) + func login(ctx *gin.Context) { ss := session.New(ctx) defer ss.Finalize() @@ -58,24 +68,74 @@ func login(ctx *gin.Context) { return } - var userID int - var pass, autoKey, ticket string - _, err = ss.UserEng.Table("users").Cols("password,autokey,ticket,user_id"). - Where("phone = ?", phone).Get(&pass, &autoKey, &ticket, &userID) + loginData, loginCode, loginMsg, _, err := AddUser(phone, password, false) if ss.CheckErr(err) { return } + data, err = json.Marshal(loginData) + if ss.CheckErr(err) { + return + } + encryptedData, err := openssl.Des3ECBEncrypt([]byte(data), randKey, openssl.PKCS7_PADDING) + if ss.CheckErr(err) { + return + } + + ss.Respond(ghomeschema.LoginResp{ + Code: loginCode, + Msg: loginMsg, + Data: base64.StdEncoding.EncodeToString(encryptedData), + }) +} + +func AddUser(phone, password string, isDefault bool) (ghomeschema.LoginData, int, string, bool, error) { loginData := ghomeschema.LoginData{} loginCode := 0 loginMsg := "ok" loginTime := time.Now().Unix() + created := false + + var userID int + var pass, autoKey, ticket string + + session := db.UserEng.NewSession() + defer session.Close() + + if err := session.Begin(); err != nil { + return loginData, loginCode, loginMsg, created, err + } + + _, err := session.Table("users").Cols("password,autokey,ticket,user_id"). + Where("phone = ?", phone).Get(&pass, &autoKey, &ticket, &userID) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err + } + if pass == "" { // 未注册 - 自动注册 - // 检查是否 userID 已经注册 - userID, err = getAvailableUserID(ss, int(loginTime)) - if ss.CheckErr(err) { - return + awardID := 1 // 音乃木坂学生 + backgroundID := 1 // 初始背景 + unitID := 31 // 初始高坂穂乃果 + userName := "音乃木坂学生" + userDesc := "你好。" + // 是否初始化 + if isDefault { + // 初始化默认用户 + userID = defaultUserID + awardID = defaultAwardID + backgroundID = defaultBackgroundID + unitID = defaultUnitID + userName = defaultUserName + userDesc = defaultUserDesc + } else { + // 检查是否 userID 已经注册 + userID, err = getAvailableUserID(int(loginTime)) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err + } } pass = openssl.Md5ToString(password) @@ -90,10 +150,12 @@ func login(ctx *gin.Context) { UserID: userID, LastLoginTime: loginTime, } - _, err = ss.UserEng.Table("users").Insert(&userData) - if ss.CheckErr(err) { - return + _, err = session.Table("users").Insert(&userData) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } + created = true // 方便起见初始化 userid 和 key 一样 // 注意:user_key 表中的 key 是上文生成的用于登录的 userid,而 userid 则是用于 Authorize Token 生成用的 @@ -101,23 +163,26 @@ func login(ctx *gin.Context) { UserID: userID, Key: userID, } - _, err = ss.UserEng.Table("user_key").Insert(&userKey) - if ss.CheckErr(err) { - return + _, err = session.Table("user_key").Insert(&userKey) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } // 检查用户配置 - exists, err := ss.UserEng.Table("user_pref").Where("user_id = ?", userID).Exist() - if ss.CheckErr(err) { - return + exists, err := session.Table("user_pref").Where("user_id = ?", userID).Exist() + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } if !exists { // 生成用于卡片 var unitData []unitmodel.CommonUnitData - err = ss.UserEng.Table(new(unitmodel.CommonUnitData)).Find(&unitData) - if ss.CheckErr(err) { - return + err = session.Table(new(unitmodel.CommonUnitData)).Find(&unitData) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } checked := false @@ -128,58 +193,65 @@ func login(ctx *gin.Context) { DisplayRank: u.MaxRank, UserID: userID, InsertDate: time.Now().Unix(), - UpdateDate: time.Now().Unix(), } // 检查表里是否已经有数据 if !checked { - ct, err := ss.UserEng.Table(new(usermodel.UserUnitData)).Count() - if ss.CheckErr(err) { - return + ct, err := session.Table(new(usermodel.UserUnitData)).Count() + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } if ct == 0 { userUnit.UnitOwningUserID = 38383 } - - checked = true } - _, err = ss.UserEng.Table(new(usermodel.UserUnitData)).Insert(&userUnit) - if ss.CheckErr(err) { - return + _, err = session.Table(new(usermodel.UserUnitData)).Insert(&userUnit) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } + + checked = true } // 默认中心成员 var unitOwningUserID int - _, err = ss.UserEng.Table(new(usermodel.UserUnitData)). - Cols("unit_owning_user_id").Where("unit_id = ?", 31).Get(&unitOwningUserID) - if ss.CheckErr(err) { - return + _, err = session.Table(new(usermodel.UserUnitData)). + Cols("unit_owning_user_id"). + Where("user_id = ?", userID). + Where("unit_id = ?", unitID). + Get(&unitOwningUserID) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } userPref := usermodel.UserPref{ UserID: userID, - AwardID: 1, // 音乃木坂学生 - BackgroundID: 1, // 初始背景 + AwardID: awardID, + BackgroundID: backgroundID, UnitOwningUserID: unitOwningUserID, - UserName: "音乃木坂学生", + UserName: userName, UserLevel: 1028, - UserDesc: "你好。", + UserDesc: userDesc, InviteCode: strconv.Itoa(userID), UpdateTime: time.Now().Unix(), } - _, err = ss.UserEng.Table("user_pref").Insert(&userPref) - if ss.CheckErr(err) { - return + _, err = session.Table("user_pref").Insert(&userPref) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } } // 检查用户卡组配置 - exists, err = ss.UserEng.Table("user_deck").Where("user_id = ?", userID).Exist() - if ss.CheckErr(err) { - return + exists, err = session.Table("user_deck").Where("user_id = ?", userID).Exist() + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } if !exists { @@ -191,15 +263,24 @@ func login(ctx *gin.Context) { UserID: userID, InsertDate: time.Now().Unix(), } - _, err = ss.UserEng.Table("user_deck").Insert(&userDeck) + _, err = session.Table("user_deck").Insert(&userDeck) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err + } userDeckID := userDeck.ID // 默认卡组 - 仆光 unitID := []int{3465, 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473} var unitData []unitmodel.UnitDataMap - err = ss.GetBasicUnitInfo().In("a.unit_id", unitID).Find(&unitData) - if ss.CheckErr(err) { - return + err = session.Table("user_unit_data").Alias("a"). + Join("LEFT", "common_unit_data", "a.unit_id = common_unit_data.unit_id"). + Cols(`a.unit_owning_user_id,a.favorite_flag,a.display_rank,common_unit_data.*`). + Where("a.user_id = ?", userID). + In("a.unit_id", unitID).Find(&unitData) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } for i, u := range unitData { @@ -222,9 +303,10 @@ func login(ctx *gin.Context) { UserID: userID, InsertDate: time.Now().Unix(), } - _, err = ss.UserEng.Table("user_deck_unit").Insert(&unitDeckData) - if ss.CheckErr(err) { - return + _, err = session.Table("user_deck_unit").Insert(&unitDeckData) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } } } @@ -247,9 +329,10 @@ func login(ctx *gin.Context) { Ticket: ticket, LastLoginTime: loginTime, } - _, err = ss.UserEng.Table("users").Where("user_id = ?", userID).Update(&userData) - if ss.CheckErr(err) { - return + _, err = session.Table("users").Where("user_id = ?", userID).Update(&userData) + if err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } loginData.Autokey = autoKey // 注意:更换设备(deviceId 发生变化)应重新生成 autokey @@ -262,28 +345,20 @@ func login(ctx *gin.Context) { } } - data, err = json.Marshal(loginData) - if ss.CheckErr(err) { - return - } - encryptedData, err := openssl.Des3ECBEncrypt([]byte(data), randKey, openssl.PKCS7_PADDING) - if ss.CheckErr(err) { - return + if err := session.Commit(); err != nil { + session.Rollback() + return loginData, loginCode, loginMsg, created, err } - ss.Respond(ghomeschema.LoginResp{ - Code: loginCode, - Msg: loginMsg, - Data: base64.StdEncoding.EncodeToString(encryptedData), - }) + return loginData, loginCode, loginMsg, created, nil } -func getAvailableUserID(ss *session.Session, seed int) (int, error) { +func getAvailableUserID(seed int) (int, error) { const maxAttempts = 16 userID := seed for attempt := range maxAttempts { - exist, err := ss.UserEng.Table("users").Where("user_id = ?", userID).Exist() + exist, err := db.UserEng.Table("users").Where("user_id = ?", userID).Exist() if err != nil { return 0, err } diff --git a/internal/handler/webui/upload.go b/internal/handler/webui/upload.go index aa02259..80c3897 100644 --- a/internal/handler/webui/upload.go +++ b/internal/handler/webui/upload.go @@ -94,7 +94,6 @@ func upload(ctx *gin.Context) { DisplayRank: uData.MaxRank, UserID: ctx.GetInt("userid"), InsertDate: time.Now().Unix(), - UpdateDate: time.Now().Unix(), } _, err = session.Table(new(usermodel.UserUnitData)).Insert(&unitData) diff --git a/internal/model/user/userunitdata.go b/internal/model/user/userunitdata.go index f32419c..aad8458 100644 --- a/internal/model/user/userunitdata.go +++ b/internal/model/user/userunitdata.go @@ -7,5 +7,4 @@ type UserUnitData struct { DisplayRank int `xorm:"display_rank"` UserID int `xorm:"user_id"` InsertDate int64 `xorm:"insert_date"` - UpdateDate int64 `xorm:"update_date"` } diff --git a/internal/startup/database.go b/internal/startup/database.go index cf3b3b8..0544ab9 100644 --- a/internal/startup/database.go +++ b/internal/startup/database.go @@ -193,7 +193,6 @@ func LoadUnitData() { DisplayRank: u.RankMax, UserID: id, InsertDate: time.Now().Unix(), - UpdateDate: time.Now().Unix(), } // 检查表里是否已经有数据 diff --git a/internal/startup/defaultuser.go b/internal/startup/defaultuser.go new file mode 100644 index 0000000..97518cb --- /dev/null +++ b/internal/startup/defaultuser.go @@ -0,0 +1,26 @@ +package startup + +import ( + "honoka-chan/internal/handler/ghome/account" + "log" +) + +const ( + defaultPhone = "86-1" + defaultPassword = "klsbgames" +) + +func CreateDefaultUser() { + _, code, msg, created, err := account.AddUser(defaultPhone, defaultPassword, true) + if err != nil { + log.Fatalln("默认用户创建失败:", err.Error()) + } + if code != 0 { + log.Fatalf("默认用户创建失败: code=%d msg=%s", code, msg) + } + if created { + log.Printf("默认用户创建成功, 账号: %s, 密码: %s\n", defaultPhone, defaultPassword) + return + } + log.Printf("默认用户已存在, 账号: %s\n", defaultPhone) +} diff --git a/internal/startup/startup.go b/internal/startup/startup.go index d270f06..3f44882 100644 --- a/internal/startup/startup.go +++ b/internal/startup/startup.go @@ -3,4 +3,5 @@ package startup func StartUp() { CreateTables() LoadUnitData() + CreateDefaultUser() }