add: score new style (#655)

* newstyle

* make lint happy
This commit is contained in:
Jiang-Red 2023-04-04 23:32:29 +08:00 committed by GitHub
parent 76dbf5a4b6
commit ed26d31326
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 280 additions and 66 deletions

4
go.mod
View File

@ -6,7 +6,7 @@ require (
github.com/Baidu-AIP/golang-sdk v1.1.1 github.com/Baidu-AIP/golang-sdk v1.1.1
github.com/FloatTech/AnimeAPI v1.6.1-0.20230331074616-e33f890df71e github.com/FloatTech/AnimeAPI v1.6.1-0.20230331074616-e33f890df71e
github.com/FloatTech/floatbox v0.0.0-20230331064925-9af336a84944 github.com/FloatTech/floatbox v0.0.0-20230331064925-9af336a84944
github.com/FloatTech/gg v1.1.2 github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08
github.com/FloatTech/imgfactory v0.2.2-0.20230322091809-b0ddbe44b94b github.com/FloatTech/imgfactory v0.2.2-0.20230322091809-b0ddbe44b94b
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9 github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9
github.com/FloatTech/sqlite v1.5.7 github.com/FloatTech/sqlite v1.5.7
@ -24,7 +24,6 @@ require (
github.com/fumiama/go-base16384 v1.6.4 github.com/fumiama/go-base16384 v1.6.4
github.com/fumiama/go-registry v0.2.6 github.com/fumiama/go-registry v0.2.6
github.com/fumiama/gotracemoe v0.0.3 github.com/fumiama/gotracemoe v0.0.3
github.com/fumiama/imgsz v0.0.2
github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565 github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565
github.com/fumiama/unibase2n v0.0.0-20221020155353-02876e777430 github.com/fumiama/unibase2n v0.0.0-20221020155353-02876e777430
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
@ -52,6 +51,7 @@ require (
github.com/faiface/beep v1.1.0 // indirect github.com/faiface/beep v1.1.0 // indirect
github.com/fumiama/go-simple-protobuf v0.1.0 // indirect github.com/fumiama/go-simple-protobuf v0.1.0 // indirect
github.com/fumiama/gofastTEA v0.0.10 // indirect github.com/fumiama/gofastTEA v0.0.10 // indirect
github.com/fumiama/imgsz v0.0.2 // indirect
github.com/gabriel-vasile/mimetype v1.0.4 // indirect github.com/gabriel-vasile/mimetype v1.0.4 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect

4
go.sum
View File

@ -6,8 +6,8 @@ github.com/FloatTech/AnimeAPI v1.6.1-0.20230331074616-e33f890df71e h1:4V7UZyLZKm
github.com/FloatTech/AnimeAPI v1.6.1-0.20230331074616-e33f890df71e/go.mod h1:LSJN8VkJXBhyAdOolVNeUptJz6l1TZ+/CfXN1OafyEY= github.com/FloatTech/AnimeAPI v1.6.1-0.20230331074616-e33f890df71e/go.mod h1:LSJN8VkJXBhyAdOolVNeUptJz6l1TZ+/CfXN1OafyEY=
github.com/FloatTech/floatbox v0.0.0-20230331064925-9af336a84944 h1:/eQoMa6Aj3coF5F7yhzZe1+SzX6SItul7MW8//pl18o= github.com/FloatTech/floatbox v0.0.0-20230331064925-9af336a84944 h1:/eQoMa6Aj3coF5F7yhzZe1+SzX6SItul7MW8//pl18o=
github.com/FloatTech/floatbox v0.0.0-20230331064925-9af336a84944/go.mod h1:FwQm6wk+b4wuW54KCKn3zccMX47Q5apnHD/Yakzv0fI= github.com/FloatTech/floatbox v0.0.0-20230331064925-9af336a84944/go.mod h1:FwQm6wk+b4wuW54KCKn3zccMX47Q5apnHD/Yakzv0fI=
github.com/FloatTech/gg v1.1.2 h1:YolgOYg3uDHc1+g0bLtt6QuRA/pvLn+b9IBCIhOOX88= github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08 h1:dPLeoiTVSBlgls+66EB/UJ2e38BaASmBN5nANaycSBU=
github.com/FloatTech/gg v1.1.2/go.mod h1:uzPzAeT35egARdRuu+1oyjU3CmTwCceoq3Vvje7LpcI= github.com/FloatTech/gg v1.1.3-0.20230226151425-6ea91286ba08/go.mod h1:uzPzAeT35egARdRuu+1oyjU3CmTwCceoq3Vvje7LpcI=
github.com/FloatTech/imgfactory v0.2.2-0.20230322091809-b0ddbe44b94b h1:VMNci4SWBySdw/6poqF9Dn9zlT5ntTFSJOEEBjRnJ/4= github.com/FloatTech/imgfactory v0.2.2-0.20230322091809-b0ddbe44b94b h1:VMNci4SWBySdw/6poqF9Dn9zlT5ntTFSJOEEBjRnJ/4=
github.com/FloatTech/imgfactory v0.2.2-0.20230322091809-b0ddbe44b94b/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs= github.com/FloatTech/imgfactory v0.2.2-0.20230322091809-b0ddbe44b94b/go.mod h1:el5hGpj1C1bDRxcTXYRwEivDCr40zZeJpcrLrB1fajs=
github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9 h1:hffajvmQFfP68U6wUwHemPuuwCUoss+SEFfoLYwbGwE= github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9 h1:hffajvmQFfP68U6wUwHemPuuwCUoss+SEFfoLYwbGwE=

View File

@ -3,15 +3,18 @@ package score
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"image" "image"
"image/color" "image/color"
"strconv" "strconv"
"sync"
"time" "time"
"github.com/FloatTech/floatbox/file" "github.com/FloatTech/floatbox/file"
"github.com/FloatTech/gg" "github.com/FloatTech/gg"
"github.com/FloatTech/imgfactory" "github.com/FloatTech/imgfactory"
"github.com/FloatTech/rendercard"
"github.com/FloatTech/zbputils/control" "github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/img/text" "github.com/FloatTech/zbputils/img/text"
"github.com/disintegration/imaging" "github.com/disintegration/imaging"
@ -269,3 +272,219 @@ func drawScore17(a *scdata) (image.Image, error) {
canvas.SetRGB255(255, 255, 255) canvas.SetRGB255(255, 255, 255)
return canvas.Image(), nil return canvas.Image(), nil
} }
func drawScore17b2(a *scdata) (img image.Image, err error) {
fontdata, err := file.GetLazyData(text.GlowSansFontFile, control.Md5File, false)
if err != nil {
return
}
getAvatar, err := initPic(a.picfile, a.uid)
if err != nil {
return
}
back, err := gg.LoadImage(a.picfile)
if err != nil {
return
}
bx, by := float64(back.Bounds().Dx()), float64(back.Bounds().Dy())
sc := 1280 / bx
colors := gg.TakeColor(back, 3)
canvas := gg.NewContext(1280, 1280*int(by)/int(bx))
cw, ch := float64(canvas.W()), float64(canvas.H())
sch := ch * 6 / 10
var blurback, scbackimg, backshadowimg, avatarimg, avatarbackimg, avatarshadowimg, whitetext, blacktext image.Image
var wg sync.WaitGroup
wg.Add(8)
go func() {
defer wg.Done()
scback := gg.NewContext(canvas.W(), canvas.H())
scback.ScaleAbout(sc, sc, cw/2, ch/2)
scback.DrawImageAnchored(back, canvas.W()/2, canvas.H()/2, 0.5, 0.5)
scback.Identity()
go func() {
defer wg.Done()
blurback = imaging.Blur(scback.Image(), 20)
}()
scbackimg = rendercard.Fillet(scback.Image(), 12)
}()
go func() {
defer wg.Done()
pureblack := gg.NewContext(canvas.W(), canvas.H())
pureblack.SetRGBA255(0, 0, 0, 255)
pureblack.Clear()
shadow := gg.NewContext(canvas.W(), canvas.H())
shadow.ScaleAbout(0.6, 0.6, cw-cw/3, ch/2)
shadow.DrawImageAnchored(pureblack.Image(), canvas.W()-canvas.W()/3, canvas.H()/2, 0.5, 0.5)
shadow.Identity()
backshadowimg = imaging.Blur(shadow.Image(), 8)
}()
aw, ah := (ch-sch)/2/2/2*3, (ch-sch)/2/2/2*3
go func() {
defer wg.Done()
avatar, _, err := image.Decode(bytes.NewReader(getAvatar))
if err != nil {
return
}
isc := (ch - sch) / 2 / 2 / 2 * 3 / float64(avatar.Bounds().Dy())
scavatar := gg.NewContext(int(aw), int(ah))
scavatar.ScaleAbout(isc, isc, aw/2, ah/2)
scavatar.DrawImageAnchored(avatar, scavatar.W()/2, scavatar.H()/2, 0.5, 0.5)
scavatar.Identity()
avatarimg = rendercard.Fillet(scavatar.Image(), 8)
}()
err = canvas.ParseFontFace(fontdata, (ch-sch)/2/2/2)
if err != nil {
return
}
namew, _ := canvas.MeasureString(a.nickname)
go func() {
defer wg.Done()
avatarshadowimg = imaging.Blur(customrectangle(cw, ch, aw, ah, namew, color.Black), 8)
}()
go func() {
defer wg.Done()
avatarbackimg = customrectangle(cw, ch, aw, ah, namew, colors[0])
}()
go func() {
defer wg.Done()
whitetext, err = customtext(a, fontdata, cw, ch, aw, color.White)
if err != nil {
return
}
}()
go func() {
defer wg.Done()
blacktext, err = customtext(a, fontdata, cw, ch, aw, color.Black)
if err != nil {
return
}
}()
wg.Wait()
if scbackimg == nil || backshadowimg == nil || avatarimg == nil || avatarbackimg == nil || avatarshadowimg == nil || whitetext == nil || blacktext == nil {
err = errors.New("图片渲染失败")
return
}
canvas.DrawImageAnchored(blurback, canvas.W()/2, canvas.H()/2, 0.5, 0.5)
canvas.DrawImage(backshadowimg, 0, 0)
canvas.ScaleAbout(0.6, 0.6, cw-cw/3, ch/2)
canvas.DrawImageAnchored(scbackimg, canvas.W()-canvas.W()/3, canvas.H()/2, 0.5, 0.5)
canvas.Identity()
canvas.DrawImage(avatarshadowimg, 0, 0)
canvas.DrawImage(avatarbackimg, 0, 0)
canvas.DrawImageAnchored(avatarimg, int((ch-sch)/2/2), int((ch-sch)/2/2), 0.5, 0.5)
canvas.DrawImage(blacktext, 2, 2)
canvas.DrawImage(whitetext, 0, 0)
img = canvas.Image()
return
}
func customrectangle(cw, ch, aw, ah, namew float64, rtgcolor color.Color) (img image.Image) {
canvas := gg.NewContext(int(cw), int(ch))
sch := ch * 6 / 10
canvas.DrawRoundedRectangle((ch-sch)/2/2-aw/2-aw/40, (ch-sch)/2/2-aw/2-ah/40, aw+aw/40*2, ah+ah/40*2, 8)
canvas.SetColor(rtgcolor)
canvas.Fill()
canvas.DrawRoundedRectangle((ch-sch)/2/2, (ch-sch)/2/2-ah/4, aw/2+aw/40*5+namew, ah/2, 8)
canvas.Fill()
img = canvas.Image()
return
}
func customtext(a *scdata, fontdata []byte, cw, ch, aw float64, textcolor color.Color) (img image.Image, err error) {
canvas := gg.NewContext(int(cw), int(ch))
canvas.SetColor(textcolor)
scw, sch := cw*6/10, ch*6/10
err = canvas.ParseFontFace(fontdata, (ch-sch)/2/2/2)
if err != nil {
return
}
canvas.DrawStringAnchored(a.nickname, (ch-sch)/2/2+aw/2+aw/40*2, (ch-sch)/2/2, 0, 0.5)
err = canvas.ParseFontFace(fontdata, (ch-sch)/2/2/3*2)
if err != nil {
return
}
canvas.DrawStringAnchored(time.Now().Format("2006/01/02"), cw-cw/6, ch/2-sch/2-canvas.FontHeight(), 0.5, 0.5)
err = canvas.ParseFontFace(fontdata, (ch-sch)/2/2/2)
if err != nil {
return
}
nextrankScore := 0
if a.rank < 10 {
nextrankScore = rankArray[a.rank+1]
} else {
nextrankScore = SCOREMAX
}
nextLevelStyle := strconv.Itoa(a.level) + "/" + strconv.Itoa(nextrankScore)
canvas.DrawStringAnchored("Level "+strconv.Itoa(a.rank), cw/3*2-scw/2, ch/2+sch/2+canvas.FontHeight(), 0, 0.5)
canvas.DrawStringAnchored(nextLevelStyle, cw/3*2+scw/2, ch/2+sch/2+canvas.FontHeight(), 1, 0.5)
err = canvas.ParseFontFace(fontdata, (ch-sch)/2/2/3)
if err != nil {
return
}
canvas.DrawStringAnchored("Create By ZeroBot-Plugin "+banner.Version, 0+4, ch, 0, -0.5)
err = canvas.ParseFontFace(fontdata, (ch-sch)/2/5*3)
if err != nil {
return
}
tempfh := canvas.FontHeight()
canvas.DrawStringAnchored(getHourWord(time.Now()), ((cw-scw)-(cw/3-scw/2))/8, (ch-sch)/2+sch/4, 0, 0.5)
err = canvas.ParseFontFace(fontdata, (ch-sch)/2/5)
if err != nil {
return
}
canvas.DrawStringAnchored("ATRI币 + "+strconv.Itoa(a.inc), ((cw-scw)-(cw/3-scw/2))/8, (ch-sch)/2+sch/4+tempfh, 0, 0.5)
canvas.DrawStringAnchored("EXP + 1", ((cw-scw)-(cw/3-scw/2))/8, (ch-sch)/2+sch/4+tempfh+canvas.FontHeight(), 0, 1)
err = canvas.ParseFontFace(fontdata, (ch-sch)/2/4)
if err != nil {
return
}
canvas.DrawStringAnchored("你有 "+strconv.Itoa(a.score)+" 枚ATRI币", ((cw-scw)-(cw/3-scw/2))/8, (ch-sch)/2+sch/4*3, 0, 0.5)
img = canvas.Image()
return
}

View File

@ -7,6 +7,7 @@ import (
"math/rand" "math/rand"
"os" "os"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/FloatTech/AnimeAPI/bilibili" "github.com/FloatTech/AnimeAPI/bilibili"
@ -54,37 +55,53 @@ var (
} }
return true return true
}) })
stylemap = map[string]func(a *scdata) (image.Image, error){
"1": drawScore15,
"2": drawScore16,
"3": drawScore17,
"4": drawScore17b2,
}
) )
func init() { func init() {
cachePath := engine.DataFolder() + "cache/" cachePath := engine.DataFolder() + "cache/"
go func() { go func() {
_ = os.RemoveAll(cachePath) ok := file.IsExist(cachePath)
err := os.MkdirAll(cachePath, 0755) if !ok {
err := os.MkdirAll(cachePath, 0777)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return
}
files, err := os.ReadDir(cachePath)
if err == nil {
for _, f := range files {
if !strings.Contains(f.Name(), time.Now().Format("20060102")) {
_ = os.Remove(cachePath + f.Name())
}
}
}
sdb = initialize(engine.DataFolder() + "score.db") sdb = initialize(engine.DataFolder() + "score.db")
}() }()
engine.OnRegex(`^签到\s?(\d*)$`, initDef).Limit(ctxext.LimitByUser).SetBlock(true).Handle(func(ctx *zero.Ctx) { engine.OnRegex(`^签到\s?(\d*)$`, initDef).Limit(ctxext.LimitByUser).SetBlock(true).Handle(func(ctx *zero.Ctx) {
// 选择key // 选择key
var key string key := ctx.State["regex_matched"].([]string)[1]
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
if gid < 0 { if gid < 0 {
// 个人用户设为负数 // 个人用户设为负数
gid = -ctx.Event.UserID gid = -ctx.Event.UserID
} }
if ctx.State["regex_matched"].([]string)[1] != "" { if key == "" {
key = ctx.State["regex_matched"].([]string)[1]
} else {
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
_ = m.Manager.GetExtra(gid, &key) _ = m.Manager.GetExtra(gid, &key)
if key == "" { if key == "" {
_ = m.Manager.GetExtra(defKeyID, &key) _ = m.Manager.GetExtra(defKeyID, &key)
} }
} }
if !isExist(key) { drawfunc, ok := stylemap[key]
ctx.SendChain(message.Text("未找到签到设定:", key)) // 避免签到配置错误造成无图发送,但是已经签到的情况 if !ok {
ctx.SendChain(message.Text("ERROR: 未找到签到设定: ", key))
return return
} }
uid := ctx.Event.UserID uid := ctx.Event.UserID
@ -131,12 +148,14 @@ func init() {
// 更新钱包 // 更新钱包
rank := getrank(level) rank := getrank(level)
add := 1 + rand.Intn(10) + rank*5 // 等级越高获得的钱越高 add := 1 + rand.Intn(10) + rank*5 // 等级越高获得的钱越高
go func() {
err = wallet.InsertWalletOf(uid, add) err = wallet.InsertWalletOf(uid, add)
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
} }
alldata := scdata{ }()
alldata := &scdata{
drawedfile: drawedFile, drawedfile: drawedFile,
picfile: picFile, picfile: picFile,
uid: uid, uid: uid,
@ -146,30 +165,11 @@ func init() {
level: level, level: level,
rank: rank, rank: rank,
} }
var drawimage image.Image drawimage, err := drawfunc(alldata)
switch key {
case "1":
drawimage, err = drawScore16(&alldata)
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
} }
case "2":
drawimage, err = drawScore15(&alldata)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
case "3":
drawimage, err = drawScore17(&alldata)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
default:
ctx.SendChain(message.Text("未添加签到设定:", key))
return
}
// done. // done.
f, err := os.Create(drawedFile) f, err := os.Create(drawedFile)
if err != nil { if err != nil {
@ -182,7 +182,7 @@ func init() {
return return
} }
_, err = imgfactory.WriteTo(drawimage, f) _, err = imgfactory.WriteTo(drawimage, f)
_ = f.Close() defer f.Close()
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
@ -204,7 +204,9 @@ func init() {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("请先签到!")) ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("请先签到!"))
return return
} }
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + picFile)) if id := ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + picFile)); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 消息发送失败, 账号可能被风控"))
}
}) })
engine.OnFullMatch("查看等级排名", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true). engine.OnFullMatch("查看等级排名", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) { Handle(func(ctx *zero.Ctx) {
@ -279,13 +281,13 @@ func init() {
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile)) ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
}) })
engine.OnRegex(`^设置(默认)?签到预设\s?(\d*)$`, zero.SuperUserPermission).Limit(ctxext.LimitByUser).SetBlock(true).Handle(func(ctx *zero.Ctx) { engine.OnRegex(`^设置(默认)?签到预设\s?(\d*)$`, zero.SuperUserPermission).Limit(ctxext.LimitByUser).SetBlock(true).Handle(func(ctx *zero.Ctx) {
if ctx.State["regex_matched"].([]string)[2] == "" { if key := ctx.State["regex_matched"].([]string)[2]; key == "" {
ctx.SendChain(message.Text("设置失败,数据为空")) ctx.SendChain(message.Text("设置失败, 数据为空"))
} else { } else {
s := ctx.State["regex_matched"].([]string)[1] s := ctx.State["regex_matched"].([]string)[1]
key := ctx.State["regex_matched"].([]string)[2] _, ok := stylemap[key]
if !isExist(key) { if !ok {
ctx.SendChain(message.Text("未找到签到设定:", key)) // 避免签到配置错误 ctx.SendChain(message.Text("ERROR: 未找到签到设定: ", key)) // 避免签到配置错误
return return
} }
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
@ -300,7 +302,7 @@ func init() {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
} }
ctx.SendChain(message.Text("设置成功,当前", s, "预设为:", key)) ctx.SendChain(message.Text("设置成功, 当前", s, "预设为:", key))
} }
}) })
} }
@ -335,28 +337,21 @@ func getrank(count int) int {
} }
func initPic(picFile string, uid int64) (avatar []byte, err error) { func initPic(picFile string, uid int64) (avatar []byte, err error) {
if file.IsExist(picFile) {
return nil, nil
}
defer process.SleepAbout1sTo2s() defer process.SleepAbout1sTo2s()
avatar, err = web.GetData("http://q4.qlogo.cn/g?b=qq&nk=" + strconv.FormatInt(uid, 10) + "&s=640")
if err != nil {
return
}
if file.IsExist(picFile) {
return
}
url, err := bilibili.GetRealURL(backgroundURL) url, err := bilibili.GetRealURL(backgroundURL)
if err != nil { if err != nil {
return nil, err return
} }
data, err := web.RequestDataWith(web.NewDefaultClient(), url, "", referer, "", nil) data, err := web.RequestDataWith(web.NewDefaultClient(), url, "", referer, "", nil)
if err != nil { if err != nil {
return nil, err return
}
avatar, err = web.GetData("http://q4.qlogo.cn/g?b=qq&nk=" + strconv.FormatInt(uid, 10) + "&s=640")
if err != nil {
return nil, err
} }
return avatar, os.WriteFile(picFile, data, 0644) return avatar, os.WriteFile(picFile, data, 0644)
} }
func isExist(key string) bool {
if key != "1" && key != "2" && key != "3" {
return false
}
return true
}