From dd2da649c130b9d6407e430167342d59039851d2 Mon Sep 17 00:00:00 2001 From: Yuan Si Date: Tue, 11 Apr 2023 23:04:38 +0800 Subject: [PATCH] Multi users data [1/N] Signed-off-by: Yuan Si --- .gitignore | 2 +- assets/account.example.db | Bin 16384 -> 0 bytes assets/data.example.db | Bin 0 -> 36864 bytes assets/main.db | Bin 2351104 -> 2600960 bytes config/config.go | 23 +- handler/api.go | 932 +++++++++++++++++++++++++++++++++++++- handler/live.go | 18 +- handler/private.go | 10 +- middleware/middleware.go | 3 + model/live.go | 50 +- model/unit.go | 49 +- tools/create.go | 273 +++++++++++ tools/gen.go | 201 ++------ tools/init.go | 151 ++++++ tools/tools.go | 14 +- 15 files changed, 1501 insertions(+), 225 deletions(-) delete mode 100644 assets/account.example.db create mode 100644 assets/data.example.db create mode 100644 tools/create.go create mode 100644 tools/init.go diff --git a/.gitignore b/.gitignore index 5a93bd1..de1eac4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ publickey.pem data logs -assets/account.db +assets/data.db assets/api1.json assets/api2.json diff --git a/assets/account.example.db b/assets/account.example.db deleted file mode 100644 index d07137ce3bf33848099aa1851a9a114e893a1a36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeI#O;5rw7zglf5J^Zt6AwEPo1GvKFUFG>r)dmv44fm8)0|j!VQfH43`gR}^V9eZ zERz8e*Fe(*oK9j*i#HWH!`~jb3 zZT`|_mdB`PUD%A8*|15gr6Q$f_-N9m-@$QnA+2_l$a7>!oiJ<4EPTzTo32kNbS9oBQ^{t;uQ}40%KC ztj+JWf?*ii+tDgcv3QBlzwJ*W6n_bC^peEfq#nCl#ybjxcugisYCRTAWs-)x9+F{y zz~$zmAEBZ^NIy!R!`PSMP+hd-S7?jeTqXS|5P$##AOHafKmY;|fB*y_009W>umJM^ z9salo4FV8=00bZa0SG_<0uX=z1R$^!K>m+k0Rj+!00bZa0SG_<0uX=z1R${c0-u%p Bjh_Gj diff --git a/assets/data.example.db b/assets/data.example.db new file mode 100644 index 0000000000000000000000000000000000000000..1a380384fe9e896397568c8cc341e10475207d74 GIT binary patch literal 36864 zcmeI*O>fgM7zgkMM%xVykT~QtVajC_h=C9X#Dy{fDwOW6mDnkm#_O!+rAyMTJ&qS~ z;6ovC<;oY~8(=%_k|rtAG>Jp_SL&MDvE%3GCr*9Z{%(_pj2wEtLqqbYbfctcrDuec zN~NlJFN^o=CBHAtzKBmPalGiTTDt%A_o}F^mS2~yuU-3j?eWzo%ipWN%0EN_UJ!r) z1RziVfl;-h-`>~(vqR=Hx64dtd27$8w++&1HFi4&X|!G# z??^3fP+MKuZjoB1U5%`-u8?U3w`!!mzqPuu@%ehCqTjirePtp2U^9z#`{vN)q3I+J ztJ7(848sU>P=y~++7t+w&X*dwj&HfeR5O|rAscw65)Aa9HVQt!048!ge#Tcg#! z7mq~sm1sS!k|Xd=T<-RigPDIurgY#1Jmj8xHkhb8n~j*AS7zGW5m(CeWAR{M(~0R* zx1Vn3jaaHkc?ErL+h*RCc%b?*9Xd`m6g9T!Zb6M4bbeL9doGK`qaZ&p@iT;}4pWyA z7tSl@uE?#>v}hOyBr@XksH`&LlddvCC6byYCvjMr&xl0LMKU5k863)8^U$WfR9Nb4 zmpWqfZR1@ssWS7qAk>d1S1S7EruJnm4mEkNWp1K!PT0u?7YSZnEHiR?LVYWlpyY+| zvfgR7$%E;%({8`#dqelHXQ>oja6_egR0GL%ozL#Gb`PgFtz4=s7If$4V<7X(47r@9 z=?Wo|?8{_HCE2$pv3#`bsH;bZS8}wYnwj%o!#dYGlz~@WXG+<4a27@swadn#nJu2D zicVGc;dz&$oFz#1lT$30lGNZ9-1#cDXu-;kJW;tQh@&)uYU4A<8_9==8Fk&I1KQ=` zBsHc(I`Vw6Ys$T)7q7ejXcZNgNv!1g%kQE<^UhALv2vA?3+&Cy6@6_@JDtS2-)9q* z_~LUZC+kJ=Eaej^d9EjIqFt1Ys?Ye2+__ZN@7~o8)R=-}Th36xj)(GBN9yb4xe=x+ z*X7D_Pqf@PeXmt?UDrO{I*T)qK?axR+N+-`!9~Iw9C_~CLtsFI;KcLA6Ec1<&|&DQ zkmI6|cl#_%o+O8tfwE~3isxrfJcZKBnB1F-O+Q``fB*y_009U<00Izz00bZa0SFXW z0Q>&}PcA}(00bZa0SG_<0uX=z1Rwwb2uuaA|3@l700Izz00bZa0SG_<0uX=z1d1VI6KmY;|fB*y_009U<00Izz00fFJfc<~* z=NJ(}00Izz00bZa0SG_<0uX=z1hD@{4nP0`5P$##AOHafKmY;|fB*!FFR&s*#Q*;* c{zM}}2tWV=5P$##AOHafKmY;|_^$>20NZThhX4Qo literal 0 HcmV?d00001 diff --git a/assets/main.db b/assets/main.db index 448c456f1598fa6b219656ece2c8263b1fb1f5d0..050417d213e09ae52ac0fd5f5086ca4ee409e6e8 100644 GIT binary patch delta 276687 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 diff --git a/config/config.go b/config/config.go index 124b945..49c280f 100644 --- a/config/config.go +++ b/config/config.go @@ -4,21 +4,32 @@ package config import ( + "honoka-chan/utils" + "os" + _ "github.com/mattn/go-sqlite3" "xorm.io/xorm" ) var ( - ConfName = "config.yml" - Conf = &AppConfigs{} - MainEng *xorm.Engine - UserEng *xorm.Engine + ConfName = "config.yml" + Conf = &AppConfigs{} + ExampleDb = "assets/data.example.db" + MainDb = "assets/main.db" + UserDb = "assets/data.db" + MainEng *xorm.Engine + UserEng *xorm.Engine ) func init() { Conf = Load(ConfName) - eng, err := xorm.NewEngine("sqlite3", "assets/main.db") + _, err := os.Stat(UserDb) + if err != nil { + utils.WriteAllText(UserDb, utils.ReadAllText(ExampleDb)) + } + + eng, err := xorm.NewEngine("sqlite3", MainDb) if err != nil { panic(err) } @@ -30,7 +41,7 @@ func init() { MainEng.SetMaxOpenConns(50) MainEng.SetMaxIdleConns(10) - eng, err = xorm.NewEngine("sqlite3", "assets/account.db") + eng, err = xorm.NewEngine("sqlite3", UserDb) if err != nil { panic(err) } diff --git a/handler/api.go b/handler/api.go index 15d246b..11b118e 100644 --- a/handler/api.go +++ b/handler/api.go @@ -9,8 +9,10 @@ import ( "honoka-chan/database" "honoka-chan/encrypt" "honoka-chan/model" + "honoka-chan/tools" "honoka-chan/utils" "net/http" + "strings" "time" "github.com/gin-gonic/gin" @@ -19,6 +21,11 @@ import ( func ApiHandler(ctx *gin.Context) { reqTime := time.Now().Unix() // fmt.Println(ctx.PostForm("request_data")) + userId := ctx.Request.Header[http.CanonicalHeaderKey("User-ID")] + if len(userId) == 0 { + ctx.String(http.StatusForbidden, ErrorMsg) + return + } var formdata []model.SifApi err := json.Unmarshal([]byte(ctx.PostForm("request_data")), &formdata) if err != nil { @@ -38,120 +45,1034 @@ func ApiHandler(ctx *gin.Context) { if v.Action == "topInfo" { // fmt.Println("topInfo") key = "login_topinfo_result" + topInfoResp := model.TopInfoResp{ + // _ = model.TopInfoResp{ + Result: model.TopInfoResult{ + FriendActionCnt: 0, + FriendGreetCnt: 0, + FriendVarietyCnt: 0, + FriendNewCnt: 0, + PresentCnt: 0, + SecretBoxBadgeFlag: false, + ServerDatetime: time.Now().Format("2006-01-02 15:04:05"), + ServerTimestamp: time.Now().Unix(), + NoticeFriendDatetime: time.Now().Format("2006-01-02 15:04:05"), + NoticeMailDatetime: "2000-01-01 12:00:00", + FriendsApprovalWaitCnt: 0, + FriendsRequestCnt: 0, + IsTodayBirthday: false, + LicenseInfo: model.TopInfoLicenseInfo{ + LicenseList: []interface{}{}, + LicensedInfo: []interface{}{}, + ExpiredInfo: []interface{}{}, + BadgeFlag: false, + }, + UsingBuffInfo: []interface{}{}, + IsKlabIDTaskFlag: false, + KlabIDTaskCanSync: false, + HasUnreadAnnounce: false, + ExchangeBadgeCnt: []int{0, 0, 0}, + AdFlag: false, + HasAdReward: false, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(topInfoResp) + CheckErr(err) } else if v.Action == "topInfoOnce" { // fmt.Println("topInfoOnce") key = "login_topinfo_once_result" + topInfoOnceResp := model.TopInfoOnceResp{ + // _ = model.TopInfoOnceResp{ + Result: model.TopInfoOnceResult{ + NewAchievementCnt: 0, + UnaccomplishedAchievementCnt: 0, + LiveDailyRewardExist: false, + TrainingEnergy: 10, + TrainingEnergyMax: 10, + Notification: model.TopInfoOnceNotification{ + Push: false, + Lp: false, + UpdateInfo: false, + Campaign: false, + Live: false, + Lbonus: false, + Event: false, + Secretbox: false, + Birthday: true, + }, + OpenArena: true, + CostumeStatus: true, + OpenAccessory: true, + ArenaSiSkillUniqueCheck: true, + OpenV98: true, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(topInfoOnceResp) + CheckErr(err) } case "live": if v.Action == "liveStatus" { // fmt.Println("liveStatus") key = "live_status_result" + var liveDifficultyId int + normalLives := []model.NormalLiveStatusList{} + sql := `SELECT live_difficulty_id FROM normal_live_m ORDER BY live_difficulty_id ASC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + for rows.Next() { + err = rows.Scan(&liveDifficultyId) + CheckErr(err) + + normalLive := model.NormalLiveStatusList{ + LiveDifficultyID: liveDifficultyId, + Status: 1, + HiScore: 0, + HiComboCount: 0, + ClearCnt: 0, + AchievedGoalIDList: []int{}, + } + normalLives = append(normalLives, normalLive) + } + + specialLives := []model.SpecialLiveStatusList{} + sql = `SELECT live_difficulty_id FROM special_live_m ORDER BY live_difficulty_id ASC` + rows, err = MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + for rows.Next() { + err = rows.Scan(&liveDifficultyId) + CheckErr(err) + + specialLive := model.SpecialLiveStatusList{ + LiveDifficultyID: liveDifficultyId, + Status: 1, + HiScore: 0, + HiComboCount: 0, + ClearCnt: 0, + AchievedGoalIDList: []int{}, + } + specialLives = append(specialLives, specialLive) + } + + LiveStatusResp := model.LiveStatusResp{ + // _ = model.LiveStatusResp{ + Result: model.LiveStatusResult{ + NormalLiveStatusList: normalLives, + SpecialLiveStatusList: specialLives, + TrainingLiveStatusList: []model.TrainingLiveStatusList{}, + MarathonLiveStatusList: []interface{}{}, + FreeLiveStatusList: []interface{}{}, + CanResumeLive: false, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(LiveStatusResp) + CheckErr(err) } else if v.Action == "schedule" { // fmt.Println("schedule") key = "live_list_result" + var liveDifficultyId int + specialLives := []model.SpecialLiveStatusList{} + sql := `SELECT live_difficulty_id FROM special_live_m ORDER BY live_difficulty_id ASC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + for rows.Next() { + err = rows.Scan(&liveDifficultyId) + CheckErr(err) + + specialLive := model.SpecialLiveStatusList{ + LiveDifficultyID: liveDifficultyId, + Status: 1, + HiScore: 0, + HiComboCount: 0, + ClearCnt: 0, + AchievedGoalIDList: []int{}, + } + specialLives = append(specialLives, specialLive) + } + + livesList := []model.LiveList{} + for _, v := range specialLives { + livesList = append(livesList, model.LiveList{ + LiveDifficultyID: v.LiveDifficultyID, + StartDate: "2023-01-01 00:00:00", + EndDate: "2037-01-01 00:00:00", + IsRandom: false, + }) + } + liveListResp := model.LiveScheduleResp{ + // _ = model.LiveScheduleResp{ + Result: model.LiveScheduleResult{ + EventList: []interface{}{}, + LiveList: livesList, + LimitedBonusList: []interface{}{}, + LimitedBonusCommonList: []model.LimitedBonusCommonList{}, // 特效道具 + RandomLiveList: []model.RandomLiveList{}, // 随机歌曲 + FreeLiveList: []interface{}{}, + TrainingLiveList: []model.TrainingLiveList{}, // 挑战歌曲 + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(liveListResp) + CheckErr(err) } case "unit": switch v.Action { case "unitAll": // fmt.Println("unitAll") key = "unit_list_result" + unitsData := []model.Active{} + err = MainEng.Table("common_unit_m").Select("*").Find(&unitsData) + if err != nil { + panic(err) + } + + userUnits := []model.Active{} + err = UserEng.Table("user_unit_m").Select("*").Find(&userUnits) + if err != nil { + panic(err) + } + + unitsData = append(unitsData, userUnits...) + + unitListResp := model.UnitAllResp{ + // _ = model.UnitAllResp{ + Result: model.UnitAllResult{ + Active: unitsData, + Waiting: []model.Waiting{}, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(unitListResp) + CheckErr(err) case "deckInfo": // fmt.Println("deckInfo") key = "unit_deck_result" + userDeck := []tools.UserDeckData{} + err = UserEng.Table("user_deck_m").Where("user_id = ?", userId[0]).Asc("deck_id").Find(&userDeck) + CheckErr(err) + + unitDeckInfo := []model.UnitDeckInfo{} + for _, deck := range userDeck { + deckUnit := []tools.UnitDeckData{} + err = UserEng.Table("deck_unit_m").Where("user_deck_id = ?", deck.ID).Asc("position").Find(&deckUnit) + CheckErr(err) + + oUids := []model.UnitOwningUserIds{} + for _, unit := range deckUnit { + oUids = append(oUids, model.UnitOwningUserIds{ + Position: unit.Position, + UnitOwningUserID: unit.UnitOwningUserID, + }) + } + + mainFlag := false + if deck.MainFlag == 1 { + mainFlag = true + } + unitDeckInfo = append(unitDeckInfo, model.UnitDeckInfo{ + UnitDeckID: deck.DeckID, + MainFlag: mainFlag, + DeckName: deck.DeckName, + UnitOwningUserIds: oUids, + }) + } + unitDeckResp := model.UnitDeckInfoResp{ + // _ = model.UnitDeckInfoResp{ + Result: unitDeckInfo, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(unitDeckResp) + CheckErr(err) case "supporterAll": // fmt.Println("supporterAll") key = "unit_support_result" + unitSupportResp := model.UnitSupportResp{ + // _ = model.UnitSupportResp{ + Result: model.UnitSupportResult{ + UnitSupportList: []model.UnitSupportList{}, + }, // 练习道具 + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(unitSupportResp) + CheckErr(err) case "removableSkillInfo": // fmt.Println("removableSkillInfo") key = "owning_equip_result" + rmSkillResp := model.RemovableSkillResp{ + // _ = model.RemovableSkillResp{ + Result: model.RemovableSkillResult{ + OwningInfo: []model.OwningInfo{}, + EquipmentInfo: []interface{}{}, + }, // 宝石 + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(rmSkillResp) + CheckErr(err) case "accessoryAll": // fmt.Println("accessoryAll") key = "unit_accessory_result" + unitAccResp := model.UnitAccessoryAllResp{ + // _ = model.UnitAccessoryAllResp{ + Result: model.UnitAccessoryAllResult{ + AccessoryList: []interface{}{}, + WearingInfo: []interface{}{}, + EspecialCreateFlag: false, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(unitAccResp) + CheckErr(err) } case "costume": // fmt.Println("costumeList") key = "costume_list_result" + costumeListResp := model.CostumeListResp{ + // _ = model.CostumeListResp{ + Result: model.CostumeListResult{ + CostumeList: []model.CostumeList{}, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(costumeListResp) + CheckErr(err) case "album": // fmt.Println("albumAll") key = "album_unit_result" + albumLists := []model.AlbumResult{} + sql := `SELECT unit_id,rarity FROM unit_m ORDER BY unit_id ASC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + for rows.Next() { + albumList := model.AlbumResult{ + RankMaxFlag: true, + LoveMaxFlag: true, + RankLevelMaxFlag: true, + AllMaxFlag: true, + FavoritePoint: 1000, + } + var uid, rit int + err = rows.Scan(&uid, &rit) + CheckErr(err) + albumList.UnitID = uid + if rit != 4 { + albumList.SignFlag = false + if rit == 1 { + albumList.HighestLovePerUnit = 50 + albumList.TotalLove = 50 + } else if rit == 2 { + albumList.HighestLovePerUnit = 200 + albumList.TotalLove = 200 + } else if rit == 3 { + albumList.HighestLovePerUnit = 500 + albumList.TotalLove = 500 + } else if rit == 5 { + albumList.HighestLovePerUnit = 750 + albumList.TotalLove = 750 + } + } else { + albumList.HighestLovePerUnit = 1000 + albumList.TotalLove = 1000 + + stmt, err := MainEng.DB().Prepare("SELECT COUNT(*) AS ct FROM unit_sign_asset_m WHERE unit_id = ?") + CheckErr(err) + defer stmt.Close() + + var count int + err = stmt.QueryRow(uid).Scan(&count) + CheckErr(err) + + if count > 0 { + albumList.SignFlag = true + } else { + albumList.SignFlag = false + } + } + albumLists = append(albumLists, albumList) + } + + albumResp := model.AlbumResp{ + // _ = model.AlbumResp{ + Result: albumLists, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(albumResp) + CheckErr(err) case "scenario": // fmt.Println("scenarioStatus") key = "scenario_status_result" + sql := `SELECT scenario_id FROM scenario_m ORDER BY scenario_id ASC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + scenarioLists := []model.ScenarioStatusList{} + for rows.Next() { + var sid int + err = rows.Scan(&sid) + CheckErr(err) + scenarioLists = append(scenarioLists, model.ScenarioStatusList{ + ScenarioID: sid, + Status: 2, + }) + } + scenarioResp := model.ScenarioStatusResp{ + // _ = model.ScenarioStatusResp{ + Result: model.ScenarioStatusResult{ + ScenarioStatusList: scenarioLists, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(scenarioResp) + CheckErr(err) case "subscenario": // fmt.Println("subscenarioStatus") key = "subscenario_status_result" + sql := `SELECT subscenario_id FROM subscenario_m ORDER BY subscenario_id ASC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + subScenarioLists := []model.SubscenarioStatusList{} + for rows.Next() { + var sid int + err = rows.Scan(&sid) + CheckErr(err) + subScenarioLists = append(subScenarioLists, model.SubscenarioStatusList{ + SubscenarioID: sid, + Status: 2, + }) + } + subScenarioResp := model.SubscenarioStatusResp{ + // _ = model.SubscenarioStatusResp{ + Result: model.SubscenarioStatusResult{ + SubscenarioStatusList: subScenarioLists, + UnlockedSubscenarioIds: []interface{}{}, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(subScenarioResp) + CheckErr(err) case "eventscenario": // fmt.Println("status") key = "event_scenario_result" + eventsList := []model.EventScenarioList{} + sql := `SELECT event_id FROM event_scenario_m GROUP BY event_id ORDER BY event_id DESC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + for rows.Next() { + var eventId int + err = rows.Scan(&eventId) + CheckErr(err) + + sql = `SELECT event_scenario_id,chapter,chapter_asset,open_date FROM event_scenario_m WHERE event_id = ? ORDER BY chapter DESC` + chaps, err := MainEng.DB().Query(sql, eventId) + CheckErr(err) + defer chaps.Close() + chapsList := []model.EventScenarioChapterList{} + var open_date string + for chaps.Next() { + var event_scenario_id, chapter int + var chapter_asset interface{} + err = chaps.Scan(&event_scenario_id, &chapter, &chapter_asset, &open_date) + CheckErr(err) + chapList := model.EventScenarioChapterList{ + EventScenarioID: event_scenario_id, + Chapter: chapter, + Status: 2, + OpenFlashFlag: 0, + IsReward: false, + CostType: 1000, + ItemID: 1200, + Amount: 1, + } + if chapter_asset != nil { + chapList.ChapterAsset = chapter_asset.(string) + } + + chapsList = append(chapsList, chapList) + } + + eventList := model.EventScenarioList{ + EventID: eventId, + OpenDate: strings.ReplaceAll(open_date, "/", "-"), + ChapterList: chapsList, + } + + // HACK event_scenario_btn_asset + if eventId == 10001 { + eventList.EventScenarioBtnAsset = "assets/image/ui/eventscenario/38_se_ba_t.png" + } else if eventId == 221 { + eventList.EventScenarioBtnAsset = "assets/image/ui/eventscenario/215_se_ba_t.png" + } else { + eventList.EventScenarioBtnAsset = fmt.Sprintf("assets/image/ui/eventscenario/%d_se_ba_t.png", eventId) + } + + eventsList = append(eventsList, eventList) + } + eventScenarioResp := model.EventScenarioStatusResp{ + // _ = model.EventScenarioStatusResp{ + Result: model.EventScenarioStatusResult{ + EventScenarioList: eventsList, // + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(eventScenarioResp) + CheckErr(err) case "multiunit": // fmt.Println("multiunitscenarioStatus") key = "multi_unit_scenario_result" + sql := `SELECT multi_unit_id FROM multi_unit_scenario_m GROUP BY multi_unit_id ORDER BY multi_unit_id ASC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + var mId int + multiUnitsList := []model.MultiUnitScenarioStatusList{} + for rows.Next() { + err = rows.Scan(&mId) + CheckErr(err) + + sql = `SELECT multi_unit_scenario_btn_asset,open_date,multi_unit_scenario_id,chapter FROM multi_unit_scenario_m a LEFT JOIN multi_unit_scenario_open_m b ON a.multi_unit_id = b.multi_unit_id WHERE a.multi_unit_id = ?` + units, err := MainEng.DB().Query(sql, mId) + CheckErr(err) + defer units.Close() + var multi_unit_scenario_id, chapter int + var multi_unit_scenario_btn_asset, open_date string + for units.Next() { + err = units.Scan(&multi_unit_scenario_btn_asset, &open_date, &multi_unit_scenario_id, &chapter) + CheckErr(err) + } + + multiUnitsList = append(multiUnitsList, model.MultiUnitScenarioStatusList{ + MultiUnitID: mId, + Status: 2, + MultiUnitScenarioBtnAsset: multi_unit_scenario_btn_asset, + OpenDate: strings.ReplaceAll(open_date, "/", "-"), + ChapterList: []model.MultiUnitScenarioChapterList{ + { + MultiUnitScenarioID: multi_unit_scenario_id, + Chapter: chapter, + Status: 2, + }, + }, + }) + } + unitsResp := model.MultiUnitScenarioStatusResp{ + // _ = model.MultiUnitScenarioStatusResp{ + Result: model.MultiUnitScenarioStatusResult{ + MultiUnitScenarioStatusList: multiUnitsList, + UnlockedMultiUnitScenarioIds: []interface{}{}, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(unitsResp) + CheckErr(err) case "payment": // fmt.Println("productList") key = "product_result" + productResp := model.ProductListResp{ + // _ = model.ProductListResp{ + Result: model.ProductListResult{ + RestrictionInfo: model.RestrictionInfo{ + Restricted: false, + }, + UnderAgeInfo: model.UnderAgeInfo{ + BirthSet: false, + HasLimit: false, + LimitAmount: nil, + MonthUsed: 0, + }, + SnsProductList: []model.SnsProductList{}, + ProductList: []model.ProductList{}, + SubscriptionList: []model.SubscriptionList{}, + ShowPointShop: false, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(productResp) + CheckErr(err) case "banner": // fmt.Println("bannerList") key = "banner_result" + bannerResp := model.BannerListResp{ + // _ = model.BannerListResp{ + Result: model.BannerListResult{ + TimeLimit: "2037-12-31 23:59:59", + BannerList: []model.BannerList{ + { + BannerType: 1, + TargetID: 1743, + AssetPath: "assets/image/secretbox/icon/s_ba_1743_1.png", + FixedFlag: false, + BackSide: false, + BannerID: 101151, + StartDate: "2013-04-15 00:00:00", + EndDate: "2037-12-31 23:59:59", + AddUnitStartDate: "2022-01-01 00:00:00", + }, + { + BannerType: 2, + TargetID: 1, + AssetPath: "assets/image/webview/wv_ba_01.png", + WebviewURL: "/manga", + FixedFlag: false, + BackSide: true, + BannerID: 200001, + StartDate: "2016-10-15 15:00:00", + EndDate: "2037-12-31 23:59:59", + }, + }, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(bannerResp) + CheckErr(err) case "notice": // fmt.Println("noticeMarquee") key = "item_marquee_result" + marqueeResp := model.NoticeMarqueeResp{ + // _ = model.NoticeMarqueeResp{ + Result: model.NoticeMarqueeResult{ + ItemCount: 0, + MarqueeList: []interface{}{}, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(marqueeResp) + CheckErr(err) case "user": // fmt.Println("getNavi") key = "user_intro_result" + userIntroResp := model.UserNaviResp{ + // _ = model.UserNaviResp{ + Result: model.UserNaviResult{ + User: model.User{ + UserID: 9999999, + UnitOwningUserID: 41674, + }, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(userIntroResp) + CheckErr(err) case "navigation": // fmt.Println("specialCutin") key = "special_cutin_result" + cutinResp := model.SpecialCutinResp{ + // _ = model.SpecialCutinResp{ + Result: model.SpecialCutinResult{ + SpecialCutinList: []interface{}{}, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(cutinResp) + CheckErr(err) case "award": // fmt.Println("awardInfo") key = "award_result" + sql := `SELECT award_id FROM award_m ORDER BY award_id ASC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + awardsList := []model.AwardInfo{} + for rows.Next() { + var aId int + err = rows.Scan(&aId) + CheckErr(err) + isSet := false + if aId == 113 { // 极推穗乃果 + isSet = true + } + awardsList = append(awardsList, model.AwardInfo{ + AwardID: aId, + IsSet: isSet, + InsertDate: time.Now().Format("2006-01-02 03:04:05"), + }) + } + awardResp := model.AwardInfoResp{ + // _ = model.AwardInfoResp{ + Result: model.AwardInfoResult{ + AwardInfo: awardsList, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(awardResp) + CheckErr(err) case "background": // fmt.Println("backgroundInfo") key = "background_result" + sql := `SELECT background_id FROM background_m ORDER BY background_id ASC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + backgroundsList := []model.BackgroundInfo{} + for rows.Next() { + var bId int + err = rows.Scan(&bId) + CheckErr(err) + isSet := false + if bId == 143 { // 穗乃果的房间[情人节] + isSet = true + } + backgroundsList = append(backgroundsList, model.BackgroundInfo{ + BackgroundID: bId, + IsSet: isSet, + InsertDate: time.Now().Format("2006-01-02 03:04:05"), + }) + } + backgroundResp := model.BackgroundInfoResp{ + // _ = model.BackgroundInfoResp{ + Result: model.BackgroundInfoResult{ + BackgroundInfo: backgroundsList, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(backgroundResp) + CheckErr(err) case "stamp": // fmt.Println("stampInfo") key = "stamp_result" + stampResp := utils.ReadAllText("assets/stamp.json") + var mStampResp interface{} + err = json.Unmarshal([]byte(stampResp), &mStampResp) + CheckErr(err) + res, err = json.Marshal(mStampResp) + CheckErr(err) case "exchange": // fmt.Println("owningPoint") key = "exchange_point_result" + sql := `SELECT exchange_point_id FROM exchange_point_m ORDER BY exchange_point_id ASC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + exPointsList := []model.ExchangePointList{} + for rows.Next() { + var eId int + err = rows.Scan(&eId) + CheckErr(err) + exPointsList = append(exPointsList, model.ExchangePointList{ + Rarity: eId, + ExchangePoint: 9999, + }) + } + exPointsResp := model.ExchangePointResp{ + // _ = model.ExchangePointResp{ + Result: model.ExchangePointResult{ + ExchangePointList: exPointsList, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(exPointsResp) + CheckErr(err) case "livese": // fmt.Println("liveseInfo") key = "live_se_result" + liveSeResp := model.LiveSeInfoResp{ + // _ = model.LiveSeInfoResp{ + Result: model.LiveSeInfoResult{ + LiveSeList: []int{1, 2, 3}, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(liveSeResp) + CheckErr(err) case "liveicon": // fmt.Println("liveiconInfo") key = "live_icon_result" + liveIconResp := model.LiveIconInfoResp{ + // _ = model.LiveIconInfoResp{ + Result: model.LiveIconInfoResult{ + LiveNotesIconList: []int{1, 2, 3}, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(liveIconResp) + CheckErr(err) case "item": // fmt.Println("list") key = "item_list_result" + itemResp := utils.ReadAllText("assets/item.json") + // _ = utils.ReadAllText("assets/item.json") + var mItemResp interface{} + err = json.Unmarshal([]byte(itemResp), &mItemResp) + CheckErr(err) + res, err = json.Marshal(mItemResp) + CheckErr(err) case "marathon": // fmt.Println("marathonInfo") key = "marathon_result" + marathonResp := model.MarathonInfoResp{ + // _ = model.MarathonInfoResp{ + Result: []interface{}{}, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(marathonResp) + CheckErr(err) case "challenge": // fmt.Println("challengeInfo") key = "challenge_result" + challengeResp := model.ChallengeInfoResp{ + // _ = model.ChallengeInfoResp{ + Result: []interface{}{}, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(challengeResp) + CheckErr(err) case "museum": // fmt.Println("info") key = "museum_result" + sql := `SELECT museum_contents_id,smile_buff,pure_buff,cool_buff FROM museum_contents_m ORDER BY museum_contents_id ASC` + rows, err := MainEng.DB().Query(sql) + CheckErr(err) + defer rows.Close() + var smileBuf, pureBuf, coolBuf int + var mIds []int + for rows.Next() { + var museum_contents_id, smile_buff, pure_buff, cool_buff int + err = rows.Scan(&museum_contents_id, &smile_buff, &pure_buff, &cool_buff) + CheckErr(err) + smileBuf += smile_buff + pureBuf += pure_buff + coolBuf += cool_buff + mIds = append(mIds, museum_contents_id) + } + + museumInfoResp := model.MuseumInfoResp{ + Result: model.MuseumInfoResult{ + MuseumInfo: model.MuseumInfo{ + Parameter: model.MuseumInfoParameter{ + Smile: smileBuf, + Pure: pureBuf, + Cool: coolBuf, + }, + ContentsIDList: mIds, + }, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(museumInfoResp) + CheckErr(err) case "profile": if v.Action == "liveCnt" { // fmt.Println("liveCnt") key = "profile_livecnt_result" + difficultyResp := tools.DifficultyResp{ + // _ = DifficultyResp{ + Result: []tools.DifficultyResult{ + { + Difficulty: 1, + ClearCnt: 315, + }, + { + Difficulty: 2, + ClearCnt: 310, + }, + { + Difficulty: 3, + ClearCnt: 314, + }, + { + Difficulty: 4, + ClearCnt: 455, + }, + { + Difficulty: 6, + ClearCnt: 233, + }, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(difficultyResp) + CheckErr(err) } else if v.Action == "cardRanking" { // fmt.Println("cardRanking") key = "profile_card_ranking_result" + var result []interface{} + love := utils.ReadAllText("assets/love.json") + err := json.Unmarshal([]byte(love), &result) + CheckErr(err) + loveResp := tools.LoveResp{ + // _ = LoveResp{ + Result: result, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(loveResp) + CheckErr(err) } else if v.Action == "profileInfo" { // fmt.Println("profileInfo") key = "profile_info_result" + profileResp := tools.ProfileResp{ + Result: tools.ProfileResult{ + UserInfo: tools.UserInfo{ + UserID: 9999999, // 3241988 + Name: "\u68a6\u8def @\u65c5\u7acb\u3061\u306e\u65e5\u306b", + Level: 1028, + CostMax: 100, + UnitMax: 5000, + EnergyMax: 417, + FriendMax: 99, + UnitCnt: 3898, + InviteCode: "377385143", + ElapsedTimeFromLogin: "14\u5c0f\u65f6\u524d", + Introduction: "\u5728\u4e0d\u77e5\u4e0d\u89c9\u4e2d \u65f6\u5149\u4ece\u4e0d\u505c\u7559\\n\u5982\u4eca\u7684\u6211\u4eec \u6bd5\u4e1a\u518d\u56de\u9996\\n\u8ffd\u68a6\u7684\u670b\u53cb\u4eec\u4e00\u540c \u8e0f\u4e0a\u4e86\u65b0\u7684\u5f81\u9014\\n\u5728\u4e0d\u4e45\u7684\u4eca\u540e \u5728\u672a\u77e5\u7684\u67d0\u5904\\n \u6211\u4eec\u4e00\u5b9a\u4f1a\u518d\u4e00\u6b21\u9082\u9005\\n \u8bf7\u4e0d\u8981\u5fd8\u8bb0\u6211\u4eec \u66fe\u7ecf\u7684\u7b11\u5bb9\r", + }, + CenterUnitInfo: tools.CenterUnitInfo{ + UnitOwningUserID: 41674, + UnitID: 3927, + Exp: 79700, + NextExp: 0, + Level: 100, + LevelLimitID: 2, + MaxLevel: 100, + Rank: 2, + MaxRank: 2, + Love: 1000, + MaxLove: 1000, + UnitSkillLevel: 8, + MaxHp: 6, + FavoriteFlag: true, + DisplayRank: 2, + UnitSkillExp: 29900, + UnitRemovableSkillCapacity: 8, + Attribute: 1, + Smile: 1, + Cute: 1, + Cool: 1, + IsLoveMax: true, + IsLevelMax: true, + IsRankMax: true, + IsSigned: true, + IsSkillLevelMax: true, + SettingAwardID: 113, + RemovableSkillIds: []int{}, + AccessoryInfo: tools.AccessoryInfo{}, + Costume: tools.Costume{}, + TotalSmile: 1, + TotalCute: 1, + TotalCool: 1, + TotalHp: 6, + }, + NaviUnitInfo: tools.NaviUnitInfo{ + UnitOwningUserID: 41674, + UnitID: 3927, + Exp: 79700, + NextExp: 0, + Level: 100, + MaxLevel: 100, + LevelLimitID: 2, + Rank: 2, + MaxRank: 2, + Love: 1000, + MaxLove: 1000, + UnitSkillExp: 29900, + UnitSkillLevel: 8, + MaxHp: 6, + UnitRemovableSkillCapacity: 8, + FavoriteFlag: true, + DisplayRank: 2, + IsLoveMax: true, + IsLevelMax: true, + IsRankMax: true, + IsSigned: true, + IsSkillLevelMax: true, + IsRemovableSkillCapacityMax: true, + InsertDate: "2016-10-11 10:33:03", + TotalSmile: 1, + TotalCute: 1, + TotalCool: 1, + TotalHp: 6, + RemovableSkillIds: []int{}, + }, + IsAlliance: false, + FriendStatus: 0, + SettingAwardID: 113, + SettingBackgroundID: 143, + }, + Status: 200, + CommandNum: false, + TimeStamp: time.Now().Unix(), + } + res, err = json.Marshal(profileResp) + CheckErr(err) } default: // fmt.Println(ErrorMsg) fmt.Println(v) err = errors.New("invalid option") + CheckErr(err) } - CheckErr(err) + // fmt.Println(key) + _ = key - res, err = database.LevelDb.Get([]byte(key)) - CheckErr(err) + // if key != "login_topinfo_result" && key != "login_topinfo_once_result" { + // res, err = database.LevelDb.Get([]byte(key)) + // CheckErr(err) + // } var result interface{} err = json.Unmarshal([]byte(res), &result) @@ -176,11 +1097,6 @@ func ApiHandler(ctx *gin.Context) { ctx.String(http.StatusForbidden, ErrorMsg) return } - userId := ctx.Request.Header[http.CanonicalHeaderKey("User-ID")] - if len(userId) == 0 { - ctx.String(http.StatusForbidden, ErrorMsg) - return - } if !database.MatchTokenUid(authToken, userId[0]) { ctx.String(http.StatusForbidden, ErrorMsg) diff --git a/handler/live.go b/handler/live.go index b6d54d0..8b3482a 100644 --- a/handler/live.go +++ b/handler/live.go @@ -107,6 +107,11 @@ func PlayLiveHandler(ctx *gin.Context) { CheckErr(err) deckId := playReq.UnitDeckID + // Save Deck Id for /live/reward + key := "live_deck_" + userId[0] + err = database.LevelDb.Put([]byte(key), []byte(strconv.Itoa(deckId))) + CheckErr(err) + // Song type: normal / special // sqlite3 doesn't support FULL OUTER JOIN so use UNION ALL here. sql := `SELECT notes_setting_asset,c_rank_score,b_rank_score,a_rank_score,s_rank_score,ac_flag,swing_flag FROM live_setting_m WHERE live_setting_id IN (SELECT live_setting_id FROM normal_live_m WHERE live_difficulty_id = ? UNION ALL SELECT live_setting_id FROM special_live_m WHERE live_difficulty_id = ?)` @@ -119,7 +124,7 @@ func PlayLiveHandler(ctx *gin.Context) { // fmt.Println(c_rank_score, b_rank_score, a_rank_score, s_rank_score) notes := []model.NotesList{} - fmt.Println("./assets/notes/" + notes_setting_asset) + // fmt.Println("./assets/notes/" + notes_setting_asset) notes_list := utils.ReadAllText("./assets/notes/" + notes_setting_asset) err = json.Unmarshal([]byte(notes_list), ¬es) CheckErr(err) @@ -312,7 +317,7 @@ func PlayScoreHandler(ctx *gin.Context) { // fmt.Println(c_rank_score, b_rank_score, a_rank_score, s_rank_score) notes := []model.NotesList{} - fmt.Println("./assets/notes/" + notes_setting_asset) + // fmt.Println("./assets/notes/" + notes_setting_asset) notes_list := utils.ReadAllText("./assets/notes/" + notes_setting_asset) err = json.Unmarshal([]byte(notes_list), ¬es) CheckErr(err) @@ -434,10 +439,13 @@ func PlayRewardHandler(ctx *gin.Context) { err = MainEng.DB().QueryRow(sql, difficultyId, difficultyId).Scan(&c_rank_score, &b_rank_score, &a_rank_score, &s_rank_score, &c_rank_combo, &b_rank_combo, &a_rank_combo, &s_rank_combo, &ac_flag, &swing_flag) CheckErr(err) - unitsList := []model.PlayRewardUnitList{} - deck, err := database.LevelDb.Get([]byte("deck_info")) + key := "live_deck_" + userId[0] + deckId, err := database.LevelDb.Get([]byte(key)) CheckErr(err) - err = json.Unmarshal(deck, &unitsList) + unitsList := []model.PlayRewardUnitList{} + err = UserEng.Table("deck_unit_m").Select("*"). + Join("LEFT", "user_deck_m", "deck_unit_m.user_deck_id = user_deck_m.id"). + Where("user_id = ? AND deck_id = ?", userId[0], string(deckId)).Find(&unitsList) CheckErr(err) totalScore := playRewardReq.ScoreSmile + playRewardReq.ScoreCool + playRewardReq.ScoreCute diff --git a/handler/private.go b/handler/private.go index d8e5d5a..c550b47 100644 --- a/handler/private.go +++ b/handler/private.go @@ -6,6 +6,7 @@ import ( "fmt" "honoka-chan/database" "honoka-chan/encrypt" + "honoka-chan/tools" "honoka-chan/utils" "io" "net/http" @@ -318,8 +319,13 @@ func AccountLoginHandler(ctx *gin.Context) { defer stmt.Close() var pass, autokey, ticket, userid string - err = stmt.QueryRow(phone).Scan(&pass, &autokey, &ticket, &userid) + rows, err := stmt.Query(phone) CheckErr(err) + defer rows.Close() + for rows.Next() { + err = rows.Scan(&pass, &autokey, &ticket, &userid) + CheckErr(err) + } loginResp := LoginResp{} loginCode := 0 @@ -372,6 +378,8 @@ func AccountLoginHandler(ctx *gin.Context) { panic(err) } + tools.InitUserData(int(loginTime)) + // Login Response loginResp.Autokey = autokey loginResp.HasRealInfo = 1 diff --git a/middleware/middleware.go b/middleware/middleware.go index 89f469a..e88962f 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -18,6 +18,7 @@ func CommonMid(ctx *gin.Context) { res, _ := database.LevelDb.Get([]byte(userId[0])) if authStr != string(res) { ctx.String(http.StatusForbidden, handler.ErrorMsg) + ctx.Abort() return } } @@ -26,4 +27,6 @@ func CommonMid(ctx *gin.Context) { ctx.Header("server_version", config.Conf.Server.VersionDate) ctx.Header("version_up", config.Conf.Server.VersionUp) ctx.Header("status_code", "200") + + ctx.Next() } diff --git a/model/live.go b/model/live.go index b2b0382..824834b 100644 --- a/model/live.go +++ b/model/live.go @@ -397,22 +397,42 @@ type EffortPoint struct { Rewards []Rewards `json:"rewards"` } +// type PlayRewardUnitList struct { +// UnitOwningUserID int `json:"unit_owning_user_id"` +// UnitID int `json:"unit_id"` +// Position int `json:"position"` +// Level int `json:"level"` +// LevelLimitID int `json:"level_limit_id"` +// DisplayRank int `json:"display_rank"` +// Love int `json:"love"` +// UnitSkillLevel int `json:"unit_skill_level"` +// IsRankMax bool `json:"is_rank_max"` +// IsLoveMax bool `json:"is_love_max"` +// IsLevelMax bool `json:"is_level_max"` +// IsSigned bool `json:"is_signed"` +// BeforeLove int `json:"before_love"` +// MaxLove int `json:"max_love"` +// // Costume Costume `json:"costume,omitempty"` +// } + type PlayRewardUnitList struct { - UnitOwningUserID int `json:"unit_owning_user_id"` - UnitID int `json:"unit_id"` - Position int `json:"position"` - Level int `json:"level"` - LevelLimitID int `json:"level_limit_id"` - DisplayRank int `json:"display_rank"` - Love int `json:"love"` - UnitSkillLevel int `json:"unit_skill_level"` - IsRankMax bool `json:"is_rank_max"` - IsLoveMax bool `json:"is_love_max"` - IsLevelMax bool `json:"is_level_max"` - IsSigned bool `json:"is_signed"` - BeforeLove int `json:"before_love"` - MaxLove int `json:"max_love"` - // Costume Costume `json:"costume,omitempty"` + ID int `xorm:"id pk autoincr" json:"-"` + UserDeckID int `xorm:"user_deck_id" json:"-"` + UnitOwningUserID int `xorm:"unit_owning_user_id" json:"unit_owning_user_id"` + UnitID int `xorm:"unit_id" json:"unit_id"` + Position int `xorm:"position" json:"position"` + Level int `xorm:"level" json:"level"` + LevelLimitID int `xorm:"level_limit_id" json:"level_limit_id"` + DisplayRank int `xorm:"display_rank" json:"display_rank"` + Love int `xorm:"love" json:"love"` + UnitSkillLevel int `xorm:"unit_skill_level" json:"unit_skill_level"` + IsRankMax bool `xorm:"is_rank_max" json:"is_rank_max"` + IsLoveMax bool `xorm:"is_love_max" json:"is_love_max"` + IsLevelMax bool `xorm:"is_level_max" json:"is_level_max"` + IsSigned bool `xorm:"is_signed" json:"is_signed"` + BeforeLove int `xorm:"before_love" json:"before_love"` + MaxLove int `xorm:"max_love" json:"max_love"` + InsertData int64 `xorm:"insert_date" json:"-"` } type BeforeUserInfo struct { diff --git a/model/unit.go b/model/unit.go index 0721d62..45de4c0 100644 --- a/model/unit.go +++ b/model/unit.go @@ -21,30 +21,31 @@ type Costume struct { } type Active struct { - UnitOwningUserID int `json:"unit_owning_user_id"` - UnitID int `json:"unit_id"` - Exp int `json:"exp"` - NextExp int `json:"next_exp"` - Level int `json:"level"` - MaxLevel int `json:"max_level"` - LevelLimitID int `json:"level_limit_id"` - Rank int `json:"rank"` - MaxRank int `json:"max_rank"` - Love int `json:"love"` - MaxLove int `json:"max_love"` - UnitSkillExp int `json:"unit_skill_exp"` - UnitSkillLevel int `json:"unit_skill_level"` - MaxHp int `json:"max_hp"` - UnitRemovableSkillCapacity int `json:"unit_removable_skill_capacity"` - FavoriteFlag bool `json:"favorite_flag"` - DisplayRank int `json:"display_rank"` - IsRankMax bool `json:"is_rank_max"` - IsLoveMax bool `json:"is_love_max"` - IsLevelMax bool `json:"is_level_max"` - IsSigned bool `json:"is_signed"` - IsSkillLevelMax bool `json:"is_skill_level_max"` - IsRemovableSkillCapacityMax bool `json:"is_removable_skill_capacity_max"` - InsertDate string `json:"insert_date"` + UnitOwningUserID int `xorm:"unit_owning_user_id pk autoincr" json:"unit_owning_user_id"` + UserID int `xorm:"user_id" json:"-"` + UnitID int `xorm:"unit_id" json:"unit_id"` + Exp int `xorm:"exp" json:"exp"` + NextExp int `xorm:"next_exp" json:"next_exp"` + Level int `xorm:"level" json:"level"` + MaxLevel int `xorm:"max_level" json:"max_level"` + LevelLimitID int `xorm:"level_limit_id" json:"level_limit_id"` + Rank int `xorm:"rank" json:"rank"` + MaxRank int `xorm:"max_rank" json:"max_rank"` + Love int `xorm:"love" json:"love"` + MaxLove int `xorm:"max_love" json:"max_love"` + UnitSkillExp int `xorm:"unit_skill_exp" json:"unit_skill_exp"` + UnitSkillLevel int `xorm:"unit_skill_level" json:"unit_skill_level"` + MaxHp int `xorm:"max_hp" json:"max_hp"` + UnitRemovableSkillCapacity int `xorm:"unit_removable_skill_capacity" json:"unit_removable_skill_capacity"` + FavoriteFlag bool `xorm:"favorite_flag" json:"favorite_flag"` + DisplayRank int `xorm:"display_rank" json:"display_rank"` + IsRankMax bool `xorm:"is_rank_max" json:"is_rank_max"` + IsLoveMax bool `xorm:"is_love_max" json:"is_love_max"` + IsLevelMax bool `xorm:"is_level_max" json:"is_level_max"` + IsSigned bool `xorm:"is_signed" json:"is_signed"` + IsSkillLevelMax bool `xorm:"is_skill_level_max" json:"is_skill_level_max"` + IsRemovableSkillCapacityMax bool `xorm:"is_removable_skill_capacity_max" json:"is_removable_skill_capacity_max"` + InsertDate string `xorm:"insert_date" json:"insert_date"` // Costume Costume `json:"costume,omitempty"` } diff --git a/tools/create.go b/tools/create.go new file mode 100644 index 0000000..00c4d06 --- /dev/null +++ b/tools/create.go @@ -0,0 +1,273 @@ +package tools + +import ( + "encoding/json" + "fmt" + "honoka-chan/model" + "time" + + _ "github.com/mattn/go-sqlite3" +) + +type UnitData struct { + UnitOwningUserID int `xorm:"unit_owning_user_id pk autoincr" json:"unit_owning_user_id"` + UserID int `xorm:"user_id" json:"-"` + UnitID int `xorm:"unit_id" json:"unit_id"` + Exp int `xorm:"exp" json:"exp"` + NextExp int `xorm:"next_exp" json:"next_exp"` + Level int `xorm:"level" json:"level"` + MaxLevel int `xorm:"max_level" json:"max_level"` + LevelLimitID int `xorm:"level_limit_id" json:"level_limit_id"` + Rank int `xorm:"rank" json:"rank"` + MaxRank int `xorm:"max_rank" json:"max_rank"` + Love int `xorm:"love" json:"love"` + MaxLove int `xorm:"max_love" json:"max_love"` + UnitSkillExp int `xorm:"unit_skill_exp" json:"unit_skill_exp"` + UnitSkillLevel int `xorm:"unit_skill_level" json:"unit_skill_level"` + MaxHp int `xorm:"max_hp" json:"max_hp"` + UnitRemovableSkillCapacity int `xorm:"unit_removable_skill_capacity" json:"unit_removable_skill_capacity"` + FavoriteFlag bool `xorm:"favorite_flag" json:"favorite_flag"` + DisplayRank int `xorm:"display_rank" json:"display_rank"` + IsRankMax bool `xorm:"is_rank_max" json:"is_rank_max"` + IsLoveMax bool `xorm:"is_love_max" json:"is_love_max"` + IsLevelMax bool `xorm:"is_level_max" json:"is_level_max"` + IsSigned bool `xorm:"is_signed" json:"is_signed"` + IsSkillLevelMax bool `xorm:"is_skill_level_max" json:"is_skill_level_max"` + IsRemovableSkillCapacityMax bool `xorm:"is_removable_skill_capacity_max" json:"is_removable_skill_capacity_max"` + InsertDate string `xorm:"insert_date" json:"insert_date"` +} + +type UserDeckData struct { + ID int `xorm:"id pk autoincr"` + DeckID int `xorm:"deck_id"` + MainFlag int `xorm:"main_flag"` + DeckName string `xorm:"deck_name"` + UserID int `xorm:"user_id"` + InsertDate int64 `xorm:"insert_date"` +} + +type UnitDeckData struct { + ID int `xorm:"id pk autoincr" json:"-"` + UserDeckID int `xorm:"user_deck_id" json:"-"` + UnitOwningUserID int `xorm:"unit_owning_user_id" json:"unit_owning_user_id"` + UnitID int `xorm:"unit_id" json:"unit_id"` + Position int `xorm:"position" json:"position"` + Level int `xorm:"level" json:"level"` + LevelLimitID int `xorm:"level_limit_id" json:"level_limit_id"` + DisplayRank int `xorm:"display_rank" json:"display_rank"` + Love int `xorm:"love" json:"love"` + UnitSkillLevel int `xorm:"unit_skill_level" json:"unit_skill_level"` + IsRankMax bool `xorm:"is_rank_max" json:"is_rank_max"` + IsLoveMax bool `xorm:"is_love_max" json:"is_love_max"` + IsLevelMax bool `xorm:"is_level_max" json:"is_level_max"` + IsSigned bool `xorm:"is_signed" json:"is_signed"` + BeforeLove int `xorm:"before_love" json:"before_love"` + MaxLove int `xorm:"max_love" json:"max_love"` + InsertData int64 `xorm:"insert_date" json:"-"` +} + +type AlbumSeries struct { + UnitID int `json:"unit_id"` + AlbumSeriesID int `json:"album_series_id"` + Rarity int `json:"rarity"` + RankMin int `json:"rank_min"` + RankMax int `json:"rank_max"` + HpMax int `json:"hp_max"` + DefaultRemovableSkillCapacity int `json:"default_removable_skill_capacity"` +} + +func GenCommonUnitData2() { + sql := `SELECT unit_id,album_series_id,rarity,rank_min,rank_max,hp_max,default_removable_skill_capacity FROM unit_m WHERE unit_id NOT IN (SELECT unit_id FROM unit_m WHERE unit_type_id IN (SELECT unit_type_id FROM unit_type_m WHERE image_button_asset IS NULL AND (background_color = 'dcdbe3' AND original_attribute_id IS NULL) OR (unit_type_id IN (10,110,127,128,129) OR unit_type_id BETWEEN 131 AND 140))) ORDER BY unit_number ASC` + rows, err := MainEng.QueryInterface(sql) + CheckErr(err) + + rb, err := json.Marshal(rows) + CheckErr(err) + // fmt.Println(string(rb)) + + // 默认卡组 + userDeck := UserDeckData{ + DeckID: 1, + MainFlag: 1, + DeckName: "Default deck", + UserID: 1, + InsertDate: time.Now().Unix(), + } + _, err = UserEng.Table("user_deck_m").Insert(&userDeck) + CheckErr(err) + userDeckId := userDeck.ID + fmt.Println("userDeckId:", userDeckId) + + position := 1 + + albums := []AlbumSeries{} + if err = json.Unmarshal(rb, &albums); err != nil { + panic(err) + } + + startTime := time.Now().Add(-time.Hour * 24 * 30) + for _, v := range albums { + unitData := UnitData{} + startTime = startTime.Add(time.Second * 3) + + unitData.UnitID = v.UnitID + unitData.NextExp = 0 + unitData.Rank = v.RankMin + unitData.MaxRank = v.RankMax + unitData.MaxHp = v.HpMax + unitData.DisplayRank = 2 + unitData.UnitSkillLevel = 8 + unitData.FavoriteFlag = true + unitData.IsRankMax = true + unitData.IsLevelMax = true + unitData.IsLoveMax = true + unitData.IsSkillLevelMax = true + unitData.IsRemovableSkillCapacityMax = true + unitData.InsertDate = startTime.Local().Format("2006-01-02 03:04:05") + if v.Rarity != 4 { + unitData.LevelLimitID = 0 + unitData.UnitRemovableSkillCapacity = v.DefaultRemovableSkillCapacity + unitData.IsSigned = false + switch v.Rarity { + case 1: + // N + unitData.Exp = 8000 + unitData.Level = 40 + unitData.MaxLevel = 40 + unitData.Love = 50 + unitData.MaxLove = 50 + unitData.UnitSkillExp = 0 + unitData.UnitSkillLevel = 0 + unitData.FavoriteFlag = false + unitData.IsRankMax = false + unitData.IsLevelMax = false + unitData.IsLoveMax = false + unitData.IsSkillLevelMax = false + unitData.IsRemovableSkillCapacityMax = false + case 2: + // R + unitData.Exp = 13500 + unitData.Level = 60 + unitData.MaxLevel = 60 + unitData.Love = 200 + unitData.MaxLove = 200 + unitData.UnitSkillExp = 490 + case 3: + // SR + unitData.Exp = 36800 + unitData.Level = 80 + unitData.MaxLevel = 80 + unitData.Love = 500 + unitData.MaxLove = 500 + unitData.UnitSkillExp = 4900 + case 5: + // SSR + unitData.Exp = 56657 + unitData.Level = 90 + unitData.MaxLevel = 90 + unitData.Love = 750 + unitData.MaxLove = 750 + unitData.UnitSkillExp = 12700 + } + } else { + // UR + unitData.Exp = 79700 + unitData.Level = 100 + unitData.MaxLevel = 100 + unitData.LevelLimitID = 2 + unitData.Love = 1000 + unitData.MaxLove = 1000 + unitData.UnitSkillExp = 29900 + unitData.UnitRemovableSkillCapacity = 8 + + stmt, err := MainEng.DB().Prepare("SELECT COUNT(*) AS ct FROM unit_sign_asset_m WHERE unit_id = ?") + CheckErr(err) + defer stmt.Close() + + var ct int + err = stmt.QueryRow(v.UnitID).Scan(&ct) + CheckErr(err) + + if ct > 0 { + unitData.IsSigned = true + } else { + unitData.IsSigned = false + } + } + + _, err = MainEng.Table("common_unit_m").Insert(&unitData) + CheckErr(err) + // fmt.Println("Inserted ID:", unitData.UnitOwningUserID) + + // 默认卡组 + if v.AlbumSeriesID == 615 { // 仆光套 + unitDeckData := UnitDeckData{ + UserDeckID: userDeckId, + UnitOwningUserID: unitData.UnitOwningUserID, + UnitID: v.UnitID, + Position: position, + Level: 100, + LevelLimitID: 2, + DisplayRank: 2, + Love: 1000, + UnitSkillLevel: 8, + IsRankMax: true, + IsLoveMax: true, + IsLevelMax: true, + IsSigned: unitData.IsSigned, + BeforeLove: 1000, + MaxLove: 1000, + InsertData: time.Now().Unix(), + } + + // 入库 + _, err = UserEng.Table("deck_unit_m").Insert(&unitDeckData) + CheckErr(err) + deckUnitId := unitDeckData.ID + fmt.Println("deckUnitId:", deckUnitId) + + // + position++ + } + } +} + +func GenCommonUnitData3() { + uId := 1681205441 // Hardcode for now + userDeck := []UserDeckData{} + err := UserEng.Table("user_deck_m").Where("user_id = ?", uId).Asc("deck_id").Find(&userDeck) + CheckErr(err) + + unitDeckInfo := []model.UnitDeckInfo{} + for _, deck := range userDeck { + deckUnit := []UnitDeckData{} + err = UserEng.Table("deck_unit_m").Where("user_deck_id = ?", deck.ID).Asc("position").Find(&deckUnit) + CheckErr(err) + + oUids := []model.UnitOwningUserIds{} + for _, unit := range deckUnit { + oUids = append(oUids, model.UnitOwningUserIds{ + Position: unit.Position, + UnitOwningUserID: unit.UnitOwningUserID, + }) + } + + mainFlag := false + if deck.MainFlag == 1 { + mainFlag = true + } + unitDeckInfo = append(unitDeckInfo, model.UnitDeckInfo{ + UnitDeckID: deck.DeckID, + MainFlag: mainFlag, + DeckName: deck.DeckName, + UnitOwningUserIds: oUids, + }) + } + + b, err := json.Marshal(unitDeckInfo) + CheckErr(err) + fmt.Println(string(b)) +} + +func GenCommonUnitData() { +} diff --git a/tools/gen.go b/tools/gen.go index c731577..0587116 100644 --- a/tools/gen.go +++ b/tools/gen.go @@ -3,7 +3,6 @@ package tools import ( "encoding/json" "fmt" - "honoka-chan/database" "honoka-chan/model" "honoka-chan/utils" "strings" @@ -149,7 +148,7 @@ type ProfileResp struct { } var ( - CenterId int + CenterId = 41674 ) func GenApi1Data() { @@ -242,144 +241,20 @@ func GenApi1Data() { respAll = append(respAll, liveListResp) // unit_list_result - sql = `SELECT unit_id,album_series_id,rarity,rank_min,rank_max,hp_max,default_removable_skill_capacity FROM unit_m WHERE unit_id NOT IN (SELECT unit_id FROM unit_m WHERE unit_type_id IN (SELECT unit_type_id FROM unit_type_m WHERE image_button_asset IS NULL AND (background_color = 'dcdbe3' AND original_attribute_id IS NULL) OR (unit_type_id IN (10,110,127,128,129) OR unit_type_id BETWEEN 131 AND 140))) ORDER BY unit_number ASC;` - rows, err = MainEng.DB().Query(sql) - CheckErr(err) - unitsData := []model.Active{} - oId := 3000000000 // 起始卡片 ID,随意设置 - sdt := time.Now().Add(-time.Hour * 24 * 30) - - defaultDeckUnitList := []model.PlayRewardUnitList{} - - for rows.Next() { - unitData := model.Active{} - var uid, rit, rank, max_rank, hp_max, skill_capacity int - var album_series_id interface{} - err = rows.Scan(&uid, &album_series_id, &rit, &rank, &max_rank, &hp_max, &skill_capacity) - if err != nil { - fmt.Println(err) - continue - } - oId++ - sdt = sdt.Add(time.Second * 3) - - unitData.UnitOwningUserID = oId - unitData.UnitID = uid - unitData.NextExp = 0 - unitData.Rank = rank - unitData.MaxRank = max_rank - unitData.MaxHp = hp_max - unitData.DisplayRank = 2 - unitData.UnitSkillLevel = 8 - unitData.FavoriteFlag = true - unitData.IsRankMax = true - unitData.IsLevelMax = true - unitData.IsLoveMax = true - unitData.IsSkillLevelMax = true - unitData.IsRemovableSkillCapacityMax = true - unitData.InsertDate = sdt.Local().Format("2006-01-02 03:04:05") - if rit != 4 { - unitData.LevelLimitID = 0 - unitData.UnitRemovableSkillCapacity = skill_capacity - unitData.IsSigned = false - switch rit { - case 1: - // N - unitData.Exp = 8000 - unitData.Level = 40 - unitData.MaxLevel = 40 - unitData.Love = 50 - unitData.MaxLove = 50 - unitData.UnitSkillExp = 0 - unitData.UnitSkillLevel = 0 - unitData.FavoriteFlag = false - unitData.IsRankMax = false - unitData.IsLevelMax = false - unitData.IsLoveMax = false - unitData.IsSkillLevelMax = false - unitData.IsRemovableSkillCapacityMax = false - case 2: - // R - unitData.Exp = 13500 - unitData.Level = 60 - unitData.MaxLevel = 60 - unitData.Love = 200 - unitData.MaxLove = 200 - unitData.UnitSkillExp = 490 - case 3: - // SR - unitData.Exp = 36800 - unitData.Level = 80 - unitData.MaxLevel = 80 - unitData.Love = 500 - unitData.MaxLove = 500 - unitData.UnitSkillExp = 4900 - case 5: - // SSR - unitData.Exp = 56657 - unitData.Level = 90 - unitData.MaxLevel = 90 - unitData.Love = 750 - unitData.MaxLove = 750 - unitData.UnitSkillExp = 12700 - } - } else { - // UR - unitData.Exp = 79700 - unitData.Level = 100 - unitData.MaxLevel = 100 - unitData.LevelLimitID = 2 - unitData.Love = 1000 - unitData.MaxLove = 1000 - unitData.UnitSkillExp = 29900 - unitData.UnitRemovableSkillCapacity = 8 - - stmt, err := MainEng.DB().Prepare("SELECT COUNT(*) AS ct FROM unit_sign_asset_m WHERE unit_id = ?") - CheckErr(err) - defer stmt.Close() - - var count int - err = stmt.QueryRow(uid).Scan(&count) - CheckErr(err) - - if count > 0 { - unitData.IsSigned = true - } else { - unitData.IsSigned = false - } - } - - unitsData = append(unitsData, unitData) - - // 中心位成员 - if uid == 3927 { // AC15 果 - CenterId = oId - } - - switch album_series_id := album_series_id.(type) { - case int64: - if album_series_id == 615 { - // 仆光套 - defaultDeckUnitList = append(defaultDeckUnitList, model.PlayRewardUnitList{ - UnitOwningUserID: oId, - UnitID: uid, - Level: 100, - LevelLimitID: 2, - DisplayRank: 2, - Love: 1000, - UnitSkillLevel: 8, - IsRankMax: true, - IsLoveMax: true, - IsLevelMax: true, - IsSigned: unitData.IsSigned, - BeforeLove: 1000, - MaxLove: 1000, - }) - } - } + err = MainEng.Table("common_unit_m").Select("*").Find(&unitsData) + if err != nil { + panic(err) } + userUnits := []model.Active{} + err = UserEng.Table("user_unit_m").Select("*").Find(&userUnits) + if err != nil { + panic(err) + } + + unitsData = append(unitsData, userUnits...) + unitListResp := model.UnitAllResp{ // _ = model.UnitAllResp{ Result: model.UnitAllResult{ @@ -393,37 +268,45 @@ func GenApi1Data() { respAll = append(respAll, unitListResp) // unit_deck_result - oUids := []model.UnitOwningUserIds{} - for k, v := range defaultDeckUnitList[0:9] { - position := k + 1 - defaultDeckUnitList[k].Position = position - oUids = append(oUids, model.UnitOwningUserIds{ - Position: position, - UnitOwningUserID: v.UnitOwningUserID, + uId := 1681205441 // Hardcode for now + userDeck := []UserDeckData{} + err = UserEng.Table("user_deck_m").Where("user_id = ?", uId).Asc("deck_id").Find(&userDeck) + CheckErr(err) + + unitDeckInfo := []model.UnitDeckInfo{} + for _, deck := range userDeck { + deckUnit := []UnitDeckData{} + err = UserEng.Table("deck_unit_m").Where("user_deck_id = ?", deck.ID).Asc("position").Find(&deckUnit) + CheckErr(err) + + oUids := []model.UnitOwningUserIds{} + for _, unit := range deckUnit { + oUids = append(oUids, model.UnitOwningUserIds{ + Position: unit.Position, + UnitOwningUserID: unit.UnitOwningUserID, + }) + } + + mainFlag := false + if deck.MainFlag == 1 { + mainFlag = true + } + unitDeckInfo = append(unitDeckInfo, model.UnitDeckInfo{ + UnitDeckID: deck.DeckID, + MainFlag: mainFlag, + DeckName: deck.DeckName, + UnitOwningUserIds: oUids, }) } unitDeckResp := model.UnitDeckInfoResp{ // _ = model.UnitDeckInfoResp{ - Result: []model.UnitDeckInfo{ - { - UnitDeckID: 1, - MainFlag: true, - DeckName: "Future style", - UnitOwningUserIds: oUids, - }, - }, + Result: unitDeckInfo, Status: 200, CommandNum: false, TimeStamp: time.Now().Unix(), } respAll = append(respAll, unitDeckResp) - // HACK 保存卡组信息 - deck, err := json.Marshal(defaultDeckUnitList) - CheckErr(err) - err = database.LevelDb.Put([]byte("deck_info"), deck) - CheckErr(err) - // unit_support_result unitSupportResp := model.UnitSupportResp{ // _ = model.UnitSupportResp{ @@ -969,7 +852,7 @@ func GenApi2Data() { FriendVarietyCnt: 0, FriendNewCnt: 0, PresentCnt: 0, - SecretBoxBadgeFlag: true, + SecretBoxBadgeFlag: false, ServerDatetime: time.Now().Format("2006-01-02 15:04:05"), ServerTimestamp: time.Now().Unix(), NoticeFriendDatetime: time.Now().Format("2006-01-02 15:04:05"), diff --git a/tools/init.go b/tools/init.go new file mode 100644 index 0000000..a6f0f3d --- /dev/null +++ b/tools/init.go @@ -0,0 +1,151 @@ +package tools + +import ( + "fmt" + "time" +) + +type UserData struct { + ID int `xorm:"id pk autoincr"` + Phone string `xorm:"phone"` + Password string `xorm:"password"` + Autokey string `xorm:"autokey"` + Ticket string `xorm:"ticket"` + UserID int `xorm:"userid"` + LastLoginTime int64 `xorm:"last_login_time"` +} + +type UserPref struct { + ID int `xorm:"id pk autoincr"` + UserID int `xorm:"user_id"` + AwardID int `xorm:"award_id"` + BackgroundID int `xorm:"background_id"` + UnitOwningUserID int `xorm:"unit_owning_user_id"` + UserName string `xorm:"user_name"` + UserLevel int `xorm:"user_level"` + UserDesc string `xorm:"user_desc"` + UpdateTime int64 `xorm:"update_time"` +} + +func InitUserData(userId int) { + userList := []UserData{} + if userId != 0 { + err := UserEng.Table("users").Where("userid = ?", userId).Find(&userList) + CheckErr(err) + } else { + err := UserEng.Table("users").Asc("id").Find(&userList) + CheckErr(err) + } + + session := UserEng.NewSession() + defer session.Close() + + for _, user := range userList { + // 检查用户配置 + exists, err := UserEng.Table("user_preference_m").Where("user_id = ?", user.UserID).Exist() + CheckErr(err) + + if !exists { + // 默认中心成员() + var oId int + _, err = MainEng.Table("common_unit_m").Cols("unit_owning_user_id").Where("unit_id = ?", 31).Get(&oId) + CheckErr(err) + fmt.Println("Center UnitOwningUserID:", oId) + userPref := UserPref{ + UserID: user.UserID, + AwardID: 1, // 音乃木坂学生 + BackgroundID: 1, // 初始背景 + UnitOwningUserID: oId, + UserName: "音乃木坂学生", + UserLevel: 1, + UserDesc: "你好。", + UpdateTime: time.Now().Unix(), + } + _, err = UserEng.Table("user_preference_m").Insert(&userPref) + CheckErr(err) + fmt.Println("UserPref ID", userPref.ID) + } else { + userPref := UserPref{} + _, err = UserEng.Table("user_preference_m").Where("user_id = ?", user.UserID).Get(&userPref) + CheckErr(err) + } + + // 检查用户卡组配置 + exists, err = UserEng.Table("user_deck_m").Where("user_id = ?", user.UserID).Asc("deck_id").Exist() + CheckErr(err) + fmt.Println("UserDeck exists:", exists) + + if !exists { + userDeck := UserDeckData{ + DeckID: 1, + MainFlag: 1, + DeckName: "队伍A", + UserID: user.UserID, + InsertDate: time.Now().Unix(), + } + + if err = session.Begin(); err != nil { + panic(err) + } + + // 默认队伍 + _, err = session.Table("user_deck_m").Insert(&userDeck) + if err != nil { + session.Rollback() + panic(err) + } + userDeckId := userDeck.ID + fmt.Println("New UserDeck:", userDeckId) + + // 默认卡组 + unitIds := []int{} + err = MainEng.Table("unit_m").Cols("unit_id").Where("album_series_id = ?", 615).Find(&unitIds) + if err != nil { + session.Rollback() + panic(err) + } + + unitData := []UnitData{} + err = MainEng.Table("common_unit_m").In("unit_id", unitIds).Find(&unitData) + if err != nil { + session.Rollback() + panic(err) + } + // fmt.Println(unitData) + + position := 1 + for _, unit := range unitData { + unitDeckData := UnitDeckData{ + UserDeckID: userDeckId, + UnitOwningUserID: unit.UnitOwningUserID, + UnitID: unit.UnitID, + Position: position, + Level: 100, + LevelLimitID: 2, + DisplayRank: 2, + Love: 1000, + UnitSkillLevel: 8, + IsRankMax: true, + IsLoveMax: true, + IsLevelMax: true, + IsSigned: unit.IsSigned, + BeforeLove: 1000, + MaxLove: 1000, + InsertData: time.Now().Unix(), + } + _, err = session.Table("deck_unit_m").Insert(&unitDeckData) + if err != nil { + session.Rollback() + panic(err) + } + fmt.Println("New DeckUnit:", unitDeckData.ID) + + position++ + } + + if err = session.Commit(); err != nil { + panic(err) + } + } + } +} diff --git a/tools/tools.go b/tools/tools.go index e9b4e25..56877f4 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -15,15 +15,17 @@ func init() { MainEng = config.MainEng UserEng = config.UserEng - GenApi1Data() - GenApi2Data() - GenApi3Data() - LoadApi1Data("assets/api1.json") - LoadApi2Data("assets/api2.json") - LoadApi3Data("assets/api3.json") + // GenApi1Data() + // GenApi2Data() + // GenApi3Data() + // LoadApi1Data("assets/api1.json") + // LoadApi2Data("assets/api2.json") + // LoadApi3Data("assets/api3.json") // ListUnitData() // go SyncNotesList() // GenDownloadDb() + // GenCommonUnitData() + InitUserData(0) } func CheckErr(err error) {