The server for Open Course World

util/generate_super_wagon_world_db/by_super_world.go

mm2srv 3fae37fa 8c55a4d3

+286 -1
+4
.gitignore
··· 19 19 env/ 20 20 21 21 *.bin 22 + 23 + .DS_Store 24 + 25 + util/generate_super_wagon_world_db/tmp/
+142
db/dump/super_world.go
··· 1 + package dump 2 + 3 + import ( 4 + "encoding/json" 5 + "fmt" 6 + "reflect" 7 + "strconv" 8 + "strings" 9 + 10 + "github.com/jmoiron/sqlx" 11 + ) 12 + 13 + type SuperWorld struct { 14 + Pid string `db:"pid" json:"pid"` 15 + Id string `db:"world_id" json:"id"` 16 + Worlds int `db:"worlds" json:"worlds"` 17 + Levels int `db:"levels" json:"levels"` 18 + PlanetType int `db:"planet_type" json:"planet_type"` 19 + Created int `db:"created" json:"created"` 20 + Unk1 []byte `db:"unk1" json:"unk1"` 21 + Unk5 int `db:"unk5" json:"unk5"` 22 + Unk6 int `db:"unk6" json:"unk6"` 23 + Unk7 int `db:"unk7" json:"unk7"` 24 + Thumbnail []byte `db:"thumbnail" json:"thumbnail"` 25 + ThumbnailUrl string `db:"thumbnail_url"` 26 + ThumbnailSize int `db:"thumbnail_size"` 27 + ThumbnailFilename string `db:"thumbnail_filename"` 28 + } 29 + 30 + func (s SuperWorld) Save(db *sqlx.DB) error { 31 + var pid string 32 + db.QueryRowx("SELECT pid FROM world WHERE pid = ?", s.Pid).Scan(&pid) 33 + 34 + if pid == "" { 35 + return s.Create(db) 36 + } 37 + 38 + return s.Update(db) 39 + } 40 + 41 + func (s SuperWorld) Create(db *sqlx.DB) error { 42 + v := reflect.ValueOf(s) 43 + fields := []string{} 44 + values_placeholder := []string{} 45 + values := []any{} 46 + for i := 0; i < v.NumField(); i++ { 47 + field := v.Type().Field(i).Tag.Get("db") 48 + if field != "" { 49 + fields = append(fields, field) 50 + values_placeholder = append(values_placeholder, "?") 51 + values = append(values, v.Field(i).Interface()) 52 + } 53 + } 54 + 55 + stmt := fmt.Sprintf("INSERT INTO world (%s) VALUES (%s)", strings.Join(fields, ", "), strings.Join(values_placeholder, ", ")) 56 + 57 + _, err := db.Exec(stmt, values...) 58 + if err != nil { 59 + return err 60 + } 61 + 62 + return nil 63 + } 64 + 65 + func (s SuperWorld) Update(db *sqlx.DB) error { 66 + v := reflect.ValueOf(s) 67 + fields := []string{} 68 + values := []any{} 69 + for i := 0; i < v.NumField(); i++ { 70 + field := v.Type().Field(i).Tag.Get("db") 71 + if field != "" { 72 + fields = append(fields, fmt.Sprintf("%s = ?", field)) 73 + values = append(values, v.Field(i).Interface()) 74 + } 75 + } 76 + 77 + values = append(values, s.Pid) 78 + 79 + stmt := fmt.Sprintf("UPDATE world SET %s WHERE pid = ?", strings.Join(fields, ", ")) 80 + 81 + _, err := db.Exec(stmt, values...) 82 + if err != nil { 83 + return err 84 + } 85 + 86 + return nil 87 + } 88 + 89 + func SuperWorldFromJson(buf []byte) (SuperWorld, []CourseInfo, []UserInfo, error) { 90 + var data map[string]any 91 + 92 + err := json.Unmarshal(buf, &data) 93 + if err != nil { 94 + return SuperWorld{}, []CourseInfo{}, []UserInfo{}, err 95 + } 96 + 97 + delete(data, "thumbnail") 98 + 99 + if vv, ok := data["uploader"]; ok { 100 + if v, ok := vv.(map[string]any)["pid"]; ok { 101 + data["pid"] = strconv.FormatUint(uint64(v.(float64)), 10) 102 + } 103 + } 104 + 105 + buf, _ = json.Marshal(data) 106 + 107 + var superWorld SuperWorld 108 + err = json.Unmarshal(buf, &superWorld) 109 + if err != nil { 110 + return SuperWorld{}, []CourseInfo{}, []UserInfo{}, err 111 + } 112 + 113 + users := []UserInfo{} 114 + courses := []CourseInfo{} 115 + 116 + if vv, ok := data["courses"]; ok { 117 + for _, course := range vv.([]any) { 118 + buf, _ = json.Marshal(course) 119 + courseInfo, userInfos, err := FromJson(buf) 120 + if err != nil { 121 + return SuperWorld{}, []CourseInfo{}, []UserInfo{}, err 122 + } 123 + courses = append(courses, courseInfo) 124 + 125 + for _, u := range userInfos { 126 + found := false 127 + for _, uu := range users { 128 + if uu.Pid == u.Pid { 129 + found = true 130 + } 131 + } 132 + if !found { 133 + users = append(users, u) 134 + } 135 + } 136 + 137 + //users = append(users, userInfos...) 138 + } 139 + } 140 + 141 + return superWorld, courses, users, nil 142 + }
+1 -1
db/dump/thumbnail_encryption.go
··· 23 23 } 24 24 25 25 out := &bytes.Buffer{} 26 - err = jpeg.Encode(out, img, &jpeg.Options{Quality: 85}) 26 + err = jpeg.Encode(out, img, &jpeg.Options{Quality: 65}) 27 27 if err != nil { 28 28 return nil, err 29 29 }
+139
util/generate_super_wagon_world_db/by_super_world.go
··· 1 + package main 2 + 3 + import ( 4 + "fmt" 5 + "io/ioutil" 6 + "log" 7 + "net/http" 8 + "os" 9 + "smm2_gameserver/db/dump" 10 + ) 11 + 12 + func GetData(url string) ([]byte, error) { 13 + resp, err := http.Get(url) 14 + if err != nil { 15 + return []byte{}, err 16 + } 17 + buf, err := ioutil.ReadAll(resp.Body) 18 + if err != nil { 19 + return []byte{}, err 20 + } 21 + return buf, nil 22 + } 23 + 24 + func GetDataCached(url, file string) ([]byte, error) { 25 + if _, err := os.Stat(file); err == nil { 26 + return ioutil.ReadFile(file) 27 + } 28 + fmt.Println("fetch", url) 29 + buf, err := GetData(url) 30 + if err != nil { 31 + return []byte{}, err 32 + } 33 + 34 + err = ioutil.WriteFile(file, buf, 0644) 35 + return buf, err 36 + } 37 + 38 + func main() { 39 + superWorldId := "2383f7c2cb5c5ce0_20230303172233043040" 40 + 41 + filename := "Super_Wagon_World_05.03.2023.db" 42 + db, err := dump.InitDump(filename) 43 + if err != nil { 44 + log.Fatal(err) 45 + } 46 + fmt.Println(db) 47 + 48 + buf, err := GetDataCached(fmt.Sprintf("https://smm2.wizul.us/mm2/super_world/%s", superWorldId), fmt.Sprintf("world_%s.json", superWorldId)) 49 + if err != nil { 50 + log.Fatal(err) 51 + } 52 + 53 + world, courses, users, err := dump.SuperWorldFromJson(buf) 54 + 55 + if err := world.Save(db); err != nil { 56 + log.Fatal(err) 57 + } 58 + 59 + for _, course := range courses { 60 + var check string 61 + db.QueryRowx("SELECT pid FROM world_levels WHERE pid = ? AND data_id = ?", world.Pid, course.DataId).Scan(&check) 62 + if check == "" { 63 + _, err := db.Exec("INSERT INTO world_levels (pid, data_id, ninjis) VALUES (?, ?, ?)", world.Pid, course.DataId, 0) 64 + if err != nil { 65 + log.Fatal(err) 66 + } 67 + } 68 + 69 + // add thumb 70 + buf, err := GetDataCached(fmt.Sprintf("https://smm2.wizul.us/mm2/level_thumbnail/%s", course.CourseId), fmt.Sprintf("thumb_%s.jpg", course.CourseId)) 71 + if err != nil { 72 + log.Fatal(err) 73 + } 74 + unpacked, err := dump.UnpackJpegThumbnail(buf) 75 + if err != nil { 76 + log.Fatal(err) 77 + } 78 + course.OneScreenThumbnail = unpacked 79 + 80 + // add entire_thumb 81 + buf, err = GetDataCached(fmt.Sprintf("https://smm2.wizul.us/mm2/level_entire_thumbnail/%s", course.CourseId), fmt.Sprintf("thumb_entire_%s.jpg", course.CourseId)) 82 + if err != nil { 83 + log.Fatal(err) 84 + } 85 + course.EntireThumbnail = buf 86 + 87 + // add level_data 88 + buf, err = GetDataCached(fmt.Sprintf("https://smm2.wizul.us/mm2/level_data/%s", course.CourseId), fmt.Sprintf("level_%s.bcd", course.CourseId)) 89 + if err != nil { 90 + log.Fatal(err) 91 + } 92 + decrypted, err := dump.DecryptLevel(buf) 93 + if err != nil { 94 + log.Fatal(err) 95 + } 96 + 97 + buf, err = dump.Compress(decrypted) 98 + if err != nil { 99 + log.Fatal(err) 100 + } 101 + course.LevelData = buf 102 + 103 + // reset stats 104 + course.WorldRecord = 0 105 + course.NumComments = 0 106 + course.Clears = 0 107 + course.Attempts = 0 108 + course.Plays = 0 109 + course.VersusMatches = 0 110 + course.CoopMatches = 0 111 + course.Likes = 0 112 + course.Boos = 0 113 + course.UniquePlayersAndVersus = 0 114 + course.WeeklyLikes = 0 115 + course.WeeklyPlays = 0 116 + course.FirstCompleterPid = "" 117 + course.RecordHolderPid = "" 118 + 119 + if err := course.Save(db); err != nil { 120 + log.Fatal(err) 121 + } 122 + } 123 + 124 + for _, user := range users { 125 + if user.Pid == world.Pid { 126 + user.Name = "Wagon" 127 + if err := user.Save(db); err != nil { 128 + log.Fatal(err) 129 + } 130 + } 131 + } 132 + 133 + /* 134 + spew.Dump(world) 135 + spew.Dump(len(courses)) 136 + spew.Dump(len(users)) 137 + fmt.Println(err) 138 + */ 139 + }
util/generate_super_wagon_world_db/main.go util/generate_super_wagon_world_db/by_levels.go