diff --git a/README.md b/README.md index d4b3c9c1..e9f1532f 100644 --- a/README.md +++ b/README.md @@ -243,6 +243,9 @@ print("run[CQ:image,file="+j["img"]+"]") - **每日运势** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin/fortune` - [x] 运势 | 抽签 - [x] 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师 赛马娘 东方归言录] +- **原神抽卡** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin/genshin` + - [x] 切换原神卡池 + - [x] 原神十连 - **睡眠管理** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin/sleep_manage` - [x] 早安 | 晚安 - **浅草寺求签** `import _ github.com/FloatTech/ZeroBot-Plugin/plugin/omikuji` diff --git a/data b/data index d09b5677..c6f5b6ed 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit d09b56779cc1611af484b39dfc9940213ab3f1a6 +Subproject commit c6f5b6ed318cc0cb8e729812e9dc58275f8438a6 diff --git a/go.mod b/go.mod index cf09cc41..4303c83f 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/fumiama/gofastTEA v0.0.10 github.com/fumiama/gotracemoe v0.0.3 github.com/fumiama/sqlite3 v1.14.6 + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/jinzhu/gorm v1.9.16 github.com/mroth/weightedrand v0.4.1 github.com/pkumza/numcn v1.0.0 @@ -31,7 +32,6 @@ require ( github.com/disintegration/imaging v1.6.2 // indirect github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/uuid v1.3.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect diff --git a/main.go b/main.go index 66a5681e..baf7c768 100644 --- a/main.go +++ b/main.go @@ -75,6 +75,7 @@ import ( _ "github.com/FloatTech/ZeroBot-Plugin/plugin/epidemic" // 城市疫情查询 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/fortune" // 运势 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/funny" // 笑话 + _ "github.com/FloatTech/ZeroBot-Plugin/plugin/genshin" // 原神抽卡 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/gif" // 制图 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/github" // 搜索GitHub仓库 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs" // 炉石 diff --git a/plugin/genshin/data.go b/plugin/genshin/data.go new file mode 100644 index 00000000..86b15c26 --- /dev/null +++ b/plugin/genshin/data.go @@ -0,0 +1,16 @@ +package genshin + +type storage uint64 + +func (s *storage) is5starsmode() bool { + return *s&1 == 1 +} + +func (s *storage) setmode(is5stars bool) bool { + if is5stars { + *s |= 1 + } else { + *s &= 0xffffffff_fffffffe + } + return is5stars +} diff --git a/plugin/genshin/ys.go b/plugin/genshin/ys.go index 38746aeb..501bee64 100644 --- a/plugin/genshin/ys.go +++ b/plugin/genshin/ys.go @@ -1,453 +1,343 @@ +// Package genshin 原神抽卡 package genshin import ( "archive/zip" - "fmt" "image" "image/color" "image/draw" "image/jpeg" "image/png" - "io" "math/rand" - "os" - "path/filepath" - "regexp" - "runtime" - "strconv" "strings" - "time" + "sync/atomic" - control "github.com/FloatTech/zbputils/control" + "github.com/FloatTech/zbputils/control" "github.com/FloatTech/zbputils/control/order" + "github.com/FloatTech/zbputils/ctxext" "github.com/FloatTech/zbputils/file" + "github.com/FloatTech/zbputils/img/writer" + "github.com/FloatTech/zbputils/process" "github.com/golang/freetype" + "github.com/sirupsen/logrus" zero "github.com/wdvxdr1123/ZeroBot" "github.com/wdvxdr1123/ZeroBot/message" ) +type zipfilestructure map[string][]*zip.File + var ( - //genzip = "https://gitcode.net/qq_33747476/Images/-/raw/master/zero/Genshin.zip" - genzip = "https://raw.githubusercontent.com/FloatTech/zbpdata/main/Genshin/Genshin.zip" //素材包 - Three, four, four2, five, five2 = []string{}, []string{}, []string{}, []string{}, []string{} //三 , 四, 五星的名字 - - DP, gen, ZipN, Spath = "./data/Genshin/", "_genshin.jpg", DP + "Genshin.zip", DP + "gacha/" //路径 - five_bg, four_bg, three_bg = DP + "five_bg.jpg", DP + "four_bg.jpg", DP + "three_bg.jpg" //背景图片名 - StarN3, StarN4, StarN5 = Spath + "ThreeStar.png", Spath + "FourStar.png", Spath + "FiveStar.png" //星级图标 - - Toatl, IMGN, isPath, Lock = 0, 0, false, false //累计抽奖次数, 卡池总数, 是否遍历过路径, 锁 - DefaultMode, FiveMode, iPrefix = true, false, 0 //抽卡模式,文件前缀 - - engine = control.Register("genshin", order.AcquirePrio(), &control.Options{ - DisableOnDefault: false, - Help: "genshin\n@bot\n- 十连\n- 十连抽\n- 切换卡池\n- 刷新卡池", - }) + totl uint64 // 累计抽奖次数 + filetree = make(zipfilestructure, 32) + starN3, starN4, starN5 *zip.File ) func init() { + engine := control.Register("genshin", order.AcquirePrio(), &control.Options{ + DisableOnDefault: false, + Help: "原神抽卡\n- 原神十连\n- 切换原神卡池", + PublicDataFolder: "Genshin", + }).ApplySingle(ctxext.DefaultSingle) - engine.OnFullMatchGroup([]string{"刷新卡池"}, zero.OnlyToMe).SetBlock(false). + go func() { + zipfile := engine.DataFolder() + "Genshin.zip" + _, err := file.GetLazyData(zipfile, false, false) + if err != nil { + panic(err) + } + err = parsezip(zipfile) + if err != nil { + panic(err) + } + }() + + engine.OnFullMatch("切换原神卡池").SetBlock(true).Limit(ctxext.LimitByUser). Handle(func(ctx *zero.Ctx) { - if IsExists(DP) { - IMGN = 0 - LoadFolder() - ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("刷新完成!\n数量:", IMGN)) - IMGN = 0 - } else { - ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("没有素材哦~\n请发送 十连 \n下载素材..")) + c, ok := control.Lookup("genshin") + if !ok { + ctx.SendChain(message.Text("找不到服务!")) + return } - }) - - engine.OnFullMatchGroup([]string{"切换卡池"}, zero.OnlyToMe).SetBlock(false). - Handle(func(ctx *zero.Ctx) { - if !DefaultMode { - DefaultMode, FiveMode = true, false - ctx.SendChain(message.Text("切换到普通卡池~")) - } else { - DefaultMode, FiveMode = false, true + gid := ctx.Event.GroupID + if gid == 0 { + gid = -ctx.Event.UserID + } + store := (storage)(c.GetData(gid)) + if store.setmode(!store.is5starsmode()) { + process.SleepAbout1sTo2s() ctx.SendChain(message.Text("切换到五星卡池~")) + } else { + process.SleepAbout1sTo2s() + ctx.SendChain(message.Text("切换到普通卡池~")) + } + err := c.SetData(gid, int64(store)) + if err != nil { + process.SleepAbout1sTo2s() + ctx.SendChain(message.Text("ERROR:", err)) } }) - //@bot - engine.OnFullMatchGroup([]string{"十连", "十连抽", "来发十连", "来次十连", "来份十连"}, zero.OnlyToMe).SetBlock(false). + + engine.OnFullMatch("原神十连").SetBlock(true).Limit(ctxext.LimitByUser). Handle(func(ctx *zero.Ctx) { - times := time.Now().Unix() - iPrefix++ - if !isPath { - if Lock { - return - } - if !IsExists(DP) && !Lock { - Lock = true - ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("素材未下载...\n是否需要下载素材\n下载素材|取消下载")) - ch := make(chan int, 1) - defer close(ch) - rule := func(ctx *zero.Ctx) bool { - for _, v := range ctx.Event.Message { - if v.Type == "text" { - text := strings.ReplaceAll(v.Data["text"], " ", "") - if text == "下载素材" { - return true - } - if text == "取消下载" { - ch <- 1 - return false - } - } - } - return false - } - next := zero.NewFutureEvent("message", 999, false, zero.CheckUser(ctx.Event.UserID), rule) - recv, cancel := next.Repeat() - select { - case <-time.After(time.Second * 60): - Lock = false - cancel() - return - case <-recv: - cancel() - ctx.SendChain(message.Text("正在下载中~")) - os.Mkdir(DP, 0755) - err := file.DownloadTo(genzip, ZipN, true) - Lock = false - if err != nil { - ctx.SendChain(message.Text("下载出错了~", err)) - return - } - case <-ch: - cancel() - ctx.SendChain(message.Text("取消了呢~")) - Lock = false - close(ch) - return - } - err := unzip(ZipN, "./data/") - if err != nil { - ctx.SendChain(message.Text("解压出错了~", err)) - } - ctx.SendChain(message.Text("下载完成~")) - os.Remove(ZipN) - os.Chmod(DP, 0755) - return - } else { - LoadFolder() - } + c, ok := control.Lookup("genshin") + if !ok { + ctx.SendChain(message.Text("找不到服务!")) + return } - Str := strconv.Itoa(iPrefix) - defer os.Remove(DP + Str + gen) //删除图片 - Add(Str) - ctx.SendChain(message.At(ctx.Event.UserID), message.Text("十连成功~"), - message.Image("file:///"+file.Pwd()+"/data/Genshin/"+Str+gen)) - fmt.Printf("OK %v 秒\n", time.Now().Unix()-times) + gid := ctx.Event.GroupID + if gid == 0 { + gid = -ctx.Event.UserID + } + store := (storage)(c.GetData(gid)) + img, err := randnums(10, store) + if err != nil { + ctx.SendChain(message.Text("ERROR:", err)) + return + } + b, cl := writer.ToBytes(img) + ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.ImageBytes(b))) + cl() }) } -func Add(sf string) { +func randnums(nums int, store storage) (rgba *image.RGBA, err error) { var ( - fourName, fiveName = []string{}, []string{} //抽到 四, 五星角色的名字 - ThreeArms, fourArms, fiveArms = []string{}, []string{}, []string{} //抽到 三 , 四, 五星武器的名字 + fours, fives = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 抽到 四, 五星角色 + threeArms, fourArms, fiveArms = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 抽到 三 , 四, 五星武器 + fourN, fiveN = 0, 0 // 抽到 四, 五星角色的数量 + bgs = make([]*zip.File, 0, 10) // 背景图片名 + threeN2, fourN2, fiveN2 = 0, 0, 0 // 抽到 三 , 四, 五星武器的数量 + hero, stars = make([]*zip.File, 0, 10), make([]*zip.File, 0, 10) // 角色武器名, 储存星级图标 - fourN, fiveN, Nums, bgs = 0, 0, 10, []string{} //抽到 四, 五星角色的数量, 连抽次数, 背景图片名 - ThreeN2, fourN2, fiveN2 = 0, 0, 0 //抽到 三 , 四, 五星武器的数量 - Hero, StarName = []string{}, []string{} //角色武器名, 储存星级图标 - - Cicon, He_N = []string{}, []string{} //元素图标 + cicon = make([]*zip.File, 0, 10) // 元素图标 + five_bg, four_bg, three_bg = filetree["five_bg.jpg"][0], filetree["four_bg.jpg"][0], filetree["three_bg.jpg"][0] // 背景图片名 + fivelen = len(filetree["five"]) + five2len = len(filetree["five2"]) + threelen = len(filetree["Three"]) + fourlen = len(filetree["four"]) + four2len = len(filetree["four2"]) ) - rand.Seed(time.Now().UnixNano()) - if Toatl == 9 { //累计9次十连加入一个五星 - switch a := rand.Intn(2); a { + if totl%9 == 0 { // 累计9次加入一个五星 + switch rand.Intn(2) { case 0: fiveN++ - f := rand.Intn(len(five)) - fiveName = append(fiveName, five[f]) + fives = append(fives, filetree["five"][rand.Intn(fivelen)]) case 1: fiveN2++ - f := rand.Intn(len(five2)) - fiveArms = append(fiveArms, five2[f]) + fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)]) } - Toatl, Nums = 0, 9 + nums-- } - if DefaultMode { //默认模式 - for i := 0; i < Nums; i++ { - a := rand.Intn(1000) - if a >= 0 && a <= 750 { //抽卡几率 三星75% 四星18% 五星7% - ThreeN2++ - ta := rand.Intn(len(Three)) //名字总个数 - ThreeArms = append(ThreeArms, Three[ta]) - } else if a > 750 && a <= 840 { - fourN++ - tb := rand.Intn(len(four)) - fourName = append(fourName, four[tb]) //随机角色 - } else if a > 840 && a <= 930 { - fourN2++ - tb := rand.Intn(len(four2)) - fourArms = append(fourArms, four2[tb]) //随机武器 - } else if a > 930 && a <= 965 { + if store.is5starsmode() { // 5星模式 + for i := 0; i < nums; i++ { + switch rand.Intn(2) { + case 0: fiveN++ - tc := rand.Intn(len(five)) - fiveName = append(fiveName, five[tc]) - } else if a > 965 { + fives = append(fives, filetree["five"][rand.Intn(fivelen)]) + case 1: fiveN2++ - tc := rand.Intn(len(five2)) - fiveArms = append(fiveArms, five2[tc]) + fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)]) } } - if fourN+fourN2 == 0 && ThreeN2 > 0 { //没有四星时自动加入 - ThreeN2-- - ThreeArms = ThreeArms[:len(ThreeArms)-1] - switch a := rand.Intn(2); a { + } else { // 默认模式 + for i := 0; i < nums; i++ { + a := rand.Intn(1000) + switch { // 抽卡几率 三星75% 四星18% 五星7% + case a >= 0 && a <= 750: + threeN2++ + threeArms = append(threeArms, filetree["Three"][rand.Intn(threelen)]) + case a > 750 && a <= 840: + fourN++ + fours = append(fours, filetree["four"][rand.Intn(fourlen)]) // 随机角色 + case a > 840 && a <= 930: + fourN2++ + fourArms = append(fourArms, filetree["four2"][rand.Intn(four2len)]) // 随机武器 + case a > 930 && a <= 965: + fiveN++ + fives = append(fives, filetree["five"][rand.Intn(fivelen)]) + default: + fiveN2++ + fiveArms = append(fiveArms, filetree["five2"][rand.Intn(five2len)]) + } + } + if fourN+fourN2 == 0 && threeN2 > 0 { // 没有四星时自动加入 + threeN2-- + threeArms = threeArms[:len(threeArms)-1] + switch rand.Intn(2) { case 0: fourN++ - f := rand.Intn(len(four)) - fourName = append(fourName, four[f]) //随机角色 + fours = append(fours, filetree["four"][rand.Intn(fourlen)]) //随机角色 case 1: fourN2++ - f := rand.Intn(len(four2)) - fourArms = append(fourArms, four2[f]) //随机武器 + fourArms = append(fourArms, filetree["four2"][rand.Intn(four2len)]) //随机武器 } } - Toatl++ //次数+1 + _ = atomic.AddUint64(&totl, 1) } - if FiveMode { //5星模式 - for i := 0; i < Nums; i++ { - a := rand.Intn(100) - if a >= 0 && a <= 50 { - fiveN++ - tc := rand.Intn(len(five)) - fiveName = append(fiveName, five[tc]) //随机角色 - } else if a > 50 { - fiveN2++ - tc := rand.Intn(len(five2)) - fiveArms = append(fiveArms, five2[tc]) //随机武器 - } - } - } - //正则取出图标名 - Addicon := func(Prefix string) string { - - regC, _ := regexp.Compile(`\/[a-z]+_`) - regC2, _ := regexp.Compile(`\/`) - - if runtime.GOOS == "windows" { - regC, _ = regexp.Compile(`\\[a-z]+_`) - regC2, _ = regexp.Compile(`\\`) - } - Pr := regC.FindAllString(Prefix, 1) //取出字符 - str := strings.Join(Pr, "") //连接字符 - Sp := strings.Split(str, "_") - Str2 := strings.Join(Sp, "") - Str3 := regC2.ReplaceAllString(Str2, "") - - switch Str3 { - case "anemo": - return DP + "anemo.png" - case "cryo": - return DP + "cryo.png" - case "dendro": - return DP + "dendro.png" - case "electro": - return DP + "electro.png" - case "geo": - return DP + "geo.png" - case "hydro": - return DP + "hydro.png" - case "pyro": - return DP + "pyro.png" - case "bow": - return DP + "bow.png" - case "catalyst": - return DP + "catalyst.png" - case "claymore": - return DP + "claymore.png" - case "polearm": - return DP + "polearm.png" - default: - return DP + "sword.png" - } + icon := func(f *zip.File) *zip.File { + name := f.Name + name = name[strings.LastIndex(name, "/")+1:strings.Index(name, "_")] + ".png" + logrus.Debugln("[genshin]get named file", name) + return filetree[name][0] } - He := func(StarNum int, id int, Star string, bg string) { - for i := 0; i < StarNum; i++ { + he := func(cnt int, id int, f *zip.File, bg *zip.File) { + var hen *[]*zip.File + for i := 0; i < cnt; i++ { switch id { case 1: - He_N = ThreeArms + hen = &threeArms case 2: - He_N = fourArms + hen = &fourArms case 3: - He_N = fourName + hen = &fours case 4: - He_N = fiveArms + hen = &fiveArms case 5: - He_N = fiveName + hen = &fives } - bgs = append(bgs, bg) //加入颜色背景 - Hero = append(Hero, He_N[i]) - StarName = append(StarName, Star) //加入星级图标 - Cicon = append(Cicon, Addicon(He_N[i])) //加入元素图标 + bgs = append(bgs, bg) // 加入颜色背景 + hero = append(hero, (*hen)[i]) + stars = append(stars, f) // 加入星级图标 + cicon = append(cicon, icon((*hen)[i])) // 加入元素图标 } } - if fiveN > 0 { //按顺序加入 - He(fiveN, 5, StarN5, five_bg) //五星角色 + if fiveN > 0 { // 按顺序加入 + he(fiveN, 5, starN5, five_bg) // 五星角色 } if fourN > 0 { - He(fourN, 3, StarN4, four_bg) //四星角色 + he(fourN, 3, starN4, four_bg) // 四星角色 } if fiveN2 > 0 { - He(fiveN2, 4, StarN5, five_bg) //五星武器 + he(fiveN2, 4, starN5, five_bg) // 五星武器 } if fourN2 > 0 { - He(fourN2, 2, StarN4, four_bg) //四星武器 + he(fourN2, 2, starN4, four_bg) // 四星武器 } - if ThreeN2 > 0 { - He(ThreeN2, 1, StarN3, three_bg) //三星武器 + if threeN2 > 0 { + he(threeN2, 1, starN3, three_bg) // 三星武器 } - // fmt.Printf("三星数量 = %v 四星数量 = %v 五星数量 = %v\n", ThreeN2, fourN+fourN2, fiveN+fiveN2) - // fmt.Printf("三星 = %v \n四星 = %v%v \n五星 = %v%v\n", ThreeArms, fourName, fourArms, fiveName, fiveArms) - var ( - inp = DP + "bg0.jpg" //背景导入图片路径 - c1, c2, c3 uint8 = 50, 50, 50 //背景颜色 - opt jpeg.Options - //字体rgb 205, 205, 205 - ) + var c1, c2, c3 uint8 = 50, 50, 50 // 背景颜色 + + img00, err := filetree["bg0.jpg"][0].Open() // 打开背景图片 + if err != nil { + return + } rectangle := image.Rect(0, 0, 1920, 1080) // 图片宽度, 图片高度 - rgba := image.NewRGBA(rectangle) + rgba = image.NewRGBA(rectangle) draw.Draw(rgba, rgba.Bounds(), image.NewUniform(color.RGBA{c1, c2, c3, 255}), image.Point{}, draw.Over) context := freetype.NewContext() // 创建一个新的上下文 - context.SetDPI(72) //每英寸 dpi + context.SetDPI(72) // 每英寸 dpi context.SetClip(rgba.Bounds()) context.SetDst(rgba) - img00, _ := os.Open(inp) // 打开背景图片 defer img00.Close() - img0, _ := jpeg.Decode(img00) //读取一个本地图像 - offset := image.Pt(0, 0) //图片在背景上的位置 - draw.Draw(rgba, img0.Bounds().Add(offset), img0, image.Point{}, draw.Over) - - OpenW1, OpenH1 := 230, 0 - for i := 0; i < len(Hero); i++ { - if i > 0 { - OpenW1 += 146 //图片宽度 - } - imgs, _ := os.Open(bgs[i]) //取出背景图片 - defer imgs.Close() - img, _ := jpeg.Decode(imgs) - offset := image.Pt(OpenW1, OpenH1) - draw.Draw(rgba, img.Bounds().Add(offset), img, image.Point{}, draw.Over) - - imgs1, _ := os.Open(Hero[i]) //取出图片名 - defer imgs1.Close() - img1, _ := png.Decode(imgs1) - offset1 := image.Pt(OpenW1, OpenH1) - draw.Draw(rgba, img1.Bounds().Add(offset1), img1, image.Point{}, draw.Over) - - imgs2, _ := os.Open(StarName[i]) //取出星级图标 - defer imgs2.Close() - img2, _ := png.Decode(imgs2) - offset2 := image.Pt(OpenW1, OpenH1) - draw.Draw(rgba, img2.Bounds().Add(offset2), img2, image.Point{}, draw.Over) - - imgs3, _ := os.Open(Cicon[i]) //取出类型图标 - defer imgs3.Close() - img3, _ := png.Decode(imgs3) - offset3 := image.Pt(OpenW1, OpenH1) - draw.Draw(rgba, img3.Bounds().Add(offset3), img3, image.Point{}, draw.Over) - } - imgs4, _ := os.Open(DP + "Reply.png") //"分享" 图标 - defer imgs4.Close() - img4, _ := png.Decode(imgs4) - offset4 := image.Pt(1270, 945) //宽, 高 - draw.Draw(rgba, img4.Bounds().Add(offset4), img4, image.Point{}, draw.Over) - - file, err := os.Create(DP + sf + gen) //输出图片 - + img0, err := jpeg.Decode(img00) // 读取一个本地图像 if err != nil { - fmt.Printf("输出图片错误: %v\n", err) return } - defer file.Close() - //png.Encode(file, rgba) //输出png - opt.Quality = 100 - jpeg.Encode(file, rgba, &opt) //输出jpg -} -//遍历文件夹 -func LoadFolder() { - isPath = true - Three, four = []string{}, []string{} //重置变量 - four2, five, five2 = []string{}, []string{}, []string{} - ReadPath(DP+"Three", "Three") - ReadPath(DP+"four", "four") - ReadPath(DP+"four2", "four2") - ReadPath(DP+"five", "five") - ReadPath(DP+"five2", "five2") -} + offset := image.Pt(0, 0) // 图片在背景上的位置 + draw.Draw(rgba, img0.Bounds().Add(offset), img0, image.Point{}, draw.Over) -func ReadPath(lpath string, star string) { - err := filepath.Walk(lpath, func(filename string, fi os.FileInfo, err error) error { - if fi.IsDir() { // 忽略目录 - return nil + w1, h1 := 230, 0 + for i := 0; i < len(hero); i++ { + if i > 0 { + w1 += 146 // 图片宽度 } - f := filename - if star == "five" { - five = append(five, "./"+f) - } else if star == "five2" { - five2 = append(five2, "./"+f) - } else if star == "four" { - four = append(four, "./"+f) - } else if star == "four2" { - four2 = append(four2, "./"+f) - } else { - Three = append(Three, "./"+f) + + imgs, err := bgs[i].Open() // 取出背景图片 + if err != nil { + return nil, err } - IMGN++ - return nil - }) + defer imgs.Close() + + img, _ := jpeg.Decode(imgs) + offset := image.Pt(w1, h1) + draw.Draw(rgba, img.Bounds().Add(offset), img, image.Point{}, draw.Over) + + imgs1, err := hero[i].Open() // 取出图片名 + if err != nil { + return nil, err + } + defer imgs1.Close() + + img1, _ := png.Decode(imgs1) + offset1 := image.Pt(w1, h1) + draw.Draw(rgba, img1.Bounds().Add(offset1), img1, image.Point{}, draw.Over) + + imgs2, err := stars[i].Open() // 取出星级图标 + if err != nil { + return nil, err + } + defer imgs2.Close() + + img2, _ := png.Decode(imgs2) + offset2 := image.Pt(w1, h1) + draw.Draw(rgba, img2.Bounds().Add(offset2), img2, image.Point{}, draw.Over) + + imgs3, err := cicon[i].Open() // 取出类型图标 + if err != nil { + return nil, err + } + defer imgs3.Close() + + img3, _ := png.Decode(imgs3) + offset3 := image.Pt(w1, h1) + draw.Draw(rgba, img3.Bounds().Add(offset3), img3, image.Point{}, draw.Over) + } + imgs4, err := filetree["Reply.png"][0].Open() // "分享" 图标 if err != nil { - fmt.Printf("读取文件错误%v\n", err) + return nil, err } + defer imgs4.Close() + img4, err := png.Decode(imgs4) + if err != nil { + return nil, err + } + offset4 := image.Pt(1270, 945) // 宽, 高 + draw.Draw(rgba, img4.Bounds().Add(offset4), img4, image.Point{}, draw.Over) + return } -func IsExists(path string) bool { //判断文件是否存在 - _, err := os.Stat(path) - if err != nil && !os.IsExist(err) { - return false - } - return true -} - -//解压缩 -func unzip(zipFile string, destDir string) error { - zipReader, err := zip.OpenReader(zipFile) +func parsezip(zipFile string) error { + zipReader, err := zip.OpenReader(zipFile) // will not close if err != nil { return err } - defer zipReader.Close() for _, f := range zipReader.File { - fpath := filepath.Join(destDir, f.Name) if f.FileInfo().IsDir() { - os.MkdirAll(fpath, os.ModePerm) - } else { - if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil { - return err + filetree[f.Name] = make([]*zip.File, 0, 32) + continue + } + f.Name = f.Name[8:] + i := strings.LastIndex(f.Name, "/") + if i < 0 { + filetree[f.Name] = []*zip.File{f} + logrus.Debugln("[genshin]insert file", f.Name) + continue + } + folder := f.Name[:i] + if folder != "" { + filetree[folder] = append(filetree[folder], f) + logrus.Debugln("[genshin]insert file into", folder) + if folder == "gacha" { + switch f.Name[i+1:] { + case "ThreeStar.png": + starN3 = f + case "FourStar.png": + starN4 = f + case "FiveStar.png": + starN5 = f + } } - inFile, err := f.Open() //读取压缩文件 - if err != nil { - return err - } - defer inFile.Close() - outFile, err := os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, f.Mode()) //创建的新文件 - if err != nil { - return err - } - defer outFile.Close() - _, _ = io.Copy(outFile, inFile) } } - return err + return nil }