Skip to content

添加签到,引入分数机制 #101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ zerobot -h -t token -u url [-d|w] [-g 监听地址:端口] qq1 qq2 qq3 ...
- **cp短打** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_cpstory"`
- [x] 组cp[@xxx][@xxx]
- [x] 组cp大老师 雪乃
- **签到得分** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin_score"`
- [x] 签到
- [x] 获得签到背景[@xxx]|获得签到背景
- **TODO...**

## 使用方法
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import (
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_novel" // 铅笔小说网搜索
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_omikuji" // 浅草寺求签
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_reborn" // 投胎
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_score" // 分数
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shadiao" // 沙雕app
_ "github.com/FloatTech/ZeroBot-Plugin/plugin_shindan" // 测定

Expand Down
6 changes: 3 additions & 3 deletions plugin_mocking_bird/mocking_bird.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (

"github.com/FloatTech/ZeroBot-Plugin/control"
aireply "github.com/FloatTech/ZeroBot-Plugin/plugin_ai_reply"
fileutil "github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
)

Expand Down Expand Up @@ -57,7 +57,7 @@ func init() {
syntPath := getSyntPath()
fileName := getWav(textReply, syntPath, vocoderList[1], ctx.Event.UserID)
// 回复
ctx.SendChain(message.Record("file:///" + fileutil.BOTPATH + "/" + cachePath + fileName))
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + cachePath + fileName))
})
}

Expand Down Expand Up @@ -126,7 +126,7 @@ func getWav(text, syntPath, vocoder string, uid int64) (fileName string) {
}
defer res.Body.Close()
data, _ := ioutil.ReadAll(res.Body)
err = ioutil.WriteFile(cachePath+fileName, data, 0666)
err = os.WriteFile(cachePath+fileName, data, 0666)
if err != nil {
log.Errorln("[mockingbird]:", err)
}
Expand Down
28 changes: 28 additions & 0 deletions plugin_score/data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package score

import (
"github.com/FloatTech/ZeroBot-Plugin/utils/process"
log "github.com/sirupsen/logrus"
"os"
)

const (
cachePath = dbpath + "cache/"
dbpath = "data/Score/"
dbfile = dbpath + "score.db"
)

// SDB 得分数据库
var SDB *DB

// 加载数据库
func init() {
go func() {
process.SleepAbout1sTo2s()
_ = os.MkdirAll(dbpath, 0755)
os.RemoveAll(cachePath)
_ = os.MkdirAll(cachePath, 0755)
SDB = Initialize(dbfile)
log.Println("[score]加载score数据库")
}()
}
124 changes: 124 additions & 0 deletions plugin_score/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package score

import (
"github.com/jinzhu/gorm"
_ "github.com/logoove/sqlite" // import sql
"os"
"time"
)

// DB 分数数据库
type DB gorm.DB

// Score 分数结构体
type Score struct {
UID int64 `gorm:"column:uid;primary_key"`
Score int `gorm:"column:score;default:0"`
}

// TableName ...
func (Score) TableName() string {
return "score"
}

// SignIn 签到结构体
type SignIn struct {
UID int64 `gorm:"column:uid;primary_key"`
Count int `gorm:"column:count;default:0"`
UpdatedAt time.Time
}

// TableName ...
func (SignIn) TableName() string {
return "sign_in"
}

// Initialize 初始化ScoreDB数据库
func Initialize(dbpath string) *DB {
var err error
if _, err = os.Stat(dbpath); err != nil || os.IsNotExist(err) {
// 生成文件
f, err := os.Create(dbpath)
if err != nil {
return nil
}
defer f.Close()
}
gdb, err := gorm.Open("sqlite3", dbpath)
if err != nil {
panic(err)
}
gdb.AutoMigrate(&Score{}).AutoMigrate(&SignIn{})
return (*DB)(gdb)
}

// Open ...
func Open(dbpath string) (*DB, error) {
db, err := gorm.Open("sqlite3", dbpath)
if err != nil {
return nil, err
}
return (*DB)(db), nil
}

// Close ...
func (sdb *DB) Close() error {
db := (*gorm.DB)(sdb)
return db.Close()
}

// GetScoreByUID 取得分数
func (sdb *DB) GetScoreByUID(uid int64) (s Score) {
db := (*gorm.DB)(sdb)
db.Debug().Model(&Score{}).FirstOrCreate(&s, "uid = ? ", uid)
return s
}

// InsertOrUpdateScoreByUID 插入或更新分数
func (sdb *DB) InsertOrUpdateScoreByUID(uid int64, score int) (err error) {
db := (*gorm.DB)(sdb)
s := Score{
UID: uid,
Score: score,
}
if err = db.Debug().Model(&Score{}).First(&s, "uid = ? ", uid).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
db.Debug().Model(&Score{}).Create(&s) // newUser not user
}
} else {
err = db.Debug().Model(&Score{}).Where("uid = ? ", uid).Update(
map[string]interface{}{
"score": score,
}).Error
}
return
}

// GetSignInByUID 取得签到次数
func (sdb *DB) GetSignInByUID(uid int64) (si SignIn) {
db := (*gorm.DB)(sdb)
db.Debug().Model(&SignIn{}).FirstOrCreate(&si, "uid = ? ", uid)
return si
}

// InsertOrUpdateSignInCountByUID 插入或更新签到次数
func (sdb *DB) InsertOrUpdateSignInCountByUID(uid int64, count int) (err error) {
db := (*gorm.DB)(sdb)
si := SignIn{
UID: uid,
Count: count,
}
if err = db.Debug().Model(&SignIn{}).First(&si, "uid = ? ", uid).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
db.Debug().Model(&SignIn{}).Create(&si) // newUser not user
}
} else {
err = db.Debug().Model(&SignIn{}).Where("uid = ? ", uid).Update(
map[string]interface{}{
"count": count,
}).Error
}
return
}
187 changes: 187 additions & 0 deletions plugin_score/sign_in.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
// Package score 签到,答题得分
package score

import (
"fmt"
"github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/utils/ctxext"
"github.com/FloatTech/ZeroBot-Plugin/utils/file"
"github.com/FloatTech/ZeroBot-Plugin/utils/txt2img"
"github.com/FloatTech/ZeroBot-Plugin/utils/web"
"github.com/fogleman/gg"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/wdvxdr1123/ZeroBot/utils/helper"
"os"
"strconv"
"sync"
"time"
)

const (
prio = 5
backgroundURL = "https://iw233.cn/API/pc.php?type=json"
referer = "https://iw233.cn/main.html"
ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
signinMax = 1
// ScoreMax 分数上限定为120
ScoreMax = 120
)

var (
engine = control.Register("score", &control.Options{
DisableOnDefault: false,
Help: "签到得分\n- 签到\n- 获得签到背景[@xxx]|获得签到背景",
})
levelArray = [...]int{0, 1, 2, 5, 10, 20, 35, 55, 75, 100, 120}
// 下载锁
mu sync.Mutex
)

func init() {
engine.OnFullMatch("签到").SetBlock(true).SetPriority(prio).
Handle(func(ctx *zero.Ctx) {
uid := ctx.Event.UserID
now := time.Now()
today := now.Format("20060102")
si := SDB.GetSignInByUID(uid)
picFile := cachePath + strconv.FormatInt(uid, 10) + today + ".png"
if file.IsNotExist(picFile) {
mu.Lock()
initPic(picFile)
mu.Unlock()
}
siUpdateTimeStr := si.UpdatedAt.Format("20060102")
if siUpdateTimeStr != today {
if err := SDB.InsertOrUpdateSignInCountByUID(uid, 0); err != nil {
log.Errorln("[score]:", err)
}
}
if si.Count >= signinMax && siUpdateTimeStr == today {
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("今天你已经签到过了!"))
return
}
if err := SDB.InsertOrUpdateSignInCountByUID(uid, si.Count+1); err != nil {
log.Errorln("[score]:", err)
}
back, err := gg.LoadImage(picFile)
if err != nil {
log.Errorln("[score]:", err)
}
canvas := gg.NewContext(back.Bounds().Size().X, int(float64(back.Bounds().Size().Y)*1.7))
canvas.SetRGB(1, 1, 1)
canvas.Clear()
canvas.DrawImage(back, 0, 0)

monthWord := now.Format("01/02")
hourWord := getHourWord(now)
if err = canvas.LoadFontFace(txt2img.BoldFontFile, float64(back.Bounds().Size().X)*0.1); err != nil {
log.Println("[score]:", err)
}
canvas.SetRGB(0, 0, 0)
canvas.DrawString(hourWord, float64(back.Bounds().Size().X)*0.1, float64(back.Bounds().Size().Y)*1.2)
canvas.DrawString(monthWord, float64(back.Bounds().Size().X)*0.6, float64(back.Bounds().Size().Y)*1.2)
nickName := ctxext.CardOrNickName(ctx, uid)
if err = canvas.LoadFontFace(txt2img.FontFile, float64(back.Bounds().Size().X)*0.04); err != nil {
log.Println("[score]:", err)
}
add := 1
canvas.DrawString(nickName+fmt.Sprintf(" 小熊饼干+%d", add), float64(back.Bounds().Size().X)*0.1, float64(back.Bounds().Size().Y)*1.3)
score := SDB.GetScoreByUID(uid).Score
score += add
if score > ScoreMax {
score = ScoreMax
ctx.SendChain(message.At(uid), message.Text("你获得的小熊饼干已经达到上限"))
}
if err := SDB.InsertOrUpdateScoreByUID(uid, score); err != nil {
log.Println("[score]:", err)
}
level := getLevel(score)
canvas.DrawString("当前小熊饼干:"+strconv.FormatInt(int64(score), 10), float64(back.Bounds().Size().X)*0.1, float64(back.Bounds().Size().Y)*1.4)
canvas.DrawString("LEVEL:"+strconv.FormatInt(int64(level), 10), float64(back.Bounds().Size().X)*0.1, float64(back.Bounds().Size().Y)*1.5)
canvas.DrawRectangle(float64(back.Bounds().Size().X)*0.1, float64(back.Bounds().Size().Y)*1.55, float64(back.Bounds().Size().X)*0.6, float64(back.Bounds().Size().Y)*0.1)
canvas.SetRGB255(150, 150, 150)
canvas.Fill()
var nextLevelScore int
if level < 10 {
nextLevelScore = levelArray[level+1]
} else {
nextLevelScore = ScoreMax
}
canvas.SetRGB255(0, 0, 0)
canvas.DrawRectangle(float64(back.Bounds().Size().X)*0.1, float64(back.Bounds().Size().Y)*1.55, float64(back.Bounds().Size().X)*0.6*float64(score)/float64(nextLevelScore), float64(back.Bounds().Size().Y)*0.1)
canvas.SetRGB255(102, 102, 102)
canvas.Fill()
canvas.DrawString(fmt.Sprintf("%d/%d", score, nextLevelScore), float64(back.Bounds().Size().X)*0.75, float64(back.Bounds().Size().Y)*1.62)
canvasBase64, err := txt2img.CanvasToBase64(canvas)
if err != nil {
log.Println("[score]:", err)
}
ctx.SendChain(message.Image("base64://" + helper.BytesToString(canvasBase64)))
})
engine.OnPrefix("获得签到背景", zero.OnlyGroup).SetBlock(true).SetPriority(20).
Handle(func(ctx *zero.Ctx) {
param := ctx.State["args"].(string)
var uidStr string
if len(ctx.Event.Message) > 1 && ctx.Event.Message[1].Type == "at" {
uidStr = ctx.Event.Message[1].Data["qq"]
} else if param == "" {
uidStr = strconv.FormatInt(ctx.Event.UserID, 10)
}
picFile := cachePath + uidStr + time.Now().Format("20060102") + ".png"
if file.IsNotExist(picFile) {
mu.Lock()
initPic(picFile)
mu.Unlock()
}
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + picFile))
})
}

func getHourWord(t time.Time) string {
switch {
case 6 <= t.Hour() && t.Hour() < 12:
return "早上好"
case 12 <= t.Hour() && t.Hour() < 14:
return "中午好"
case 14 <= t.Hour() && t.Hour() < 19:
return "下午好"
case 19 <= t.Hour() && t.Hour() < 24:
return "晚上好"
case 0 <= t.Hour() && t.Hour() < 6:
return "凌晨好"
default:
return ""
}
}

func getLevel(count int) int {
for k, v := range levelArray {
if count == v {
return k
} else if count < v {
return k - 1
}
}
return -1
}

func initPic(picFile string) {
if file.IsNotExist(picFile) {
data, err := web.ReqWith(backgroundURL, "GET", referer, ua)
if err != nil {
log.Errorln("[score]:", err)
}
picURL := gjson.Get(string(data), "pic").String()
data, err = web.ReqWith(picURL, "GET", "", ua)
if err != nil {
log.Errorln("[score]:", err)
}
err = os.WriteFile(picFile, data, 0666)
if err != nil {
log.Errorln("[score]:", err)
}
}
}
2 changes: 1 addition & 1 deletion plugin_shadiao/shadiao.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const (
)

var (
engine = control.Register("curse", &control.Options{
engine = control.Register("shadiao", &control.Options{
DisableOnDefault: false,
Help: "沙雕app\n" +
"- 骂他[@xxx]|骂他[qq号](停用)\n- 骂我(停用)\n- 哄我\n- 渣我\n- 来碗绿茶\n- 发个朋友圈\n- 来碗毒鸡汤\n- 讲个段子",
Expand Down
Loading