refactor: 重构数据库逻辑
This commit is contained in:
parent
7aebdeae56
commit
769308389a
3
.gitignore
vendored
3
.gitignore
vendored
@ -30,3 +30,6 @@ bindss.db
|
|||||||
tmp/xibao.png
|
tmp/xibao.png
|
||||||
resource/font.ttf
|
resource/font.ttf
|
||||||
resource/xibao_background.png
|
resource/xibao_background.png
|
||||||
|
data.db
|
||||||
|
config.yml
|
||||||
|
tmp/
|
5
auth/auth.go
Normal file
5
auth/auth.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
func isRootUser(qqID string) bool {
|
||||||
|
return false
|
||||||
|
}
|
1
go.mod
1
go.mod
@ -5,6 +5,7 @@ go 1.22.6
|
|||||||
require (
|
require (
|
||||||
github.com/fogleman/gg v1.3.0
|
github.com/fogleman/gg v1.3.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
|
github.com/jmoiron/sqlx v1.4.0
|
||||||
github.com/mattn/go-sqlite3 v1.14.23
|
github.com/mattn/go-sqlite3 v1.14.23
|
||||||
github.com/sashabaranov/go-openai v1.30.3
|
github.com/sashabaranov/go-openai v1.30.3
|
||||||
)
|
)
|
||||||
|
9
go.sum
9
go.sum
@ -1,9 +1,18 @@
|
|||||||
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
|
||||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
||||||
|
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
|
||||||
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
|
github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
|
||||||
github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/sashabaranov/go-openai v1.30.3 h1:TEdRP3otRXX2A7vLoU+kI5XpoSo7VUUlM/rEttUqgek=
|
github.com/sashabaranov/go-openai v1.30.3 h1:TEdRP3otRXX2A7vLoU+kI5XpoSo7VUUlM/rEttUqgek=
|
||||||
|
26
handler/beatleader/beatleader.go
Normal file
26
handler/beatleader/beatleader.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package beatleader
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.lxtend.com/qqbot/handler"
|
||||||
|
"git.lxtend.com/qqbot/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
handler.RegisterHandler("查bl", getMyBL)
|
||||||
|
// handler.RegisterHandler("绑定bl", bindBL)
|
||||||
|
// handler.RegisterHandler("解绑bl", unbindSS)
|
||||||
|
// handler.RegisterHandler("最新bl", getMyRecentScore)
|
||||||
|
// handler.RegisterHandler("最热bl", getRecentScore)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMyBL(msg model.Message) (reply model.Reply) {
|
||||||
|
if len(msg.Msg) <= len("查bl ") {
|
||||||
|
return model.Reply{}
|
||||||
|
}
|
||||||
|
bindResult := ""
|
||||||
|
return model.Reply{
|
||||||
|
ReplyMsg: bindResult,
|
||||||
|
ReferOriginMsg: true,
|
||||||
|
FromMsg: msg,
|
||||||
|
}
|
||||||
|
}
|
19
handler/health/health.go
Normal file
19
handler/health/health.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package health
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.lxtend.com/qqbot/handler"
|
||||||
|
"git.lxtend.com/qqbot/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
handler.RegisterHandler("health", health)
|
||||||
|
}
|
||||||
|
|
||||||
|
func health(msg model.Message) (reply model.Reply) {
|
||||||
|
heathResult := ""
|
||||||
|
return model.Reply{
|
||||||
|
ReplyMsg: heathResult,
|
||||||
|
ReferOriginMsg: true,
|
||||||
|
FromMsg: msg,
|
||||||
|
}
|
||||||
|
}
|
@ -6,15 +6,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
handler.RegisterHandler("记下", say)
|
handler.RegisterHandler("kw", say)
|
||||||
}
|
}
|
||||||
|
|
||||||
func say(msg model.Message) (reply model.Reply) {
|
func say(msg model.Message) (reply model.Reply) {
|
||||||
if len(msg.Msg) <= 5 {
|
if len(msg.Msg) <= len("kw ") {
|
||||||
return model.Reply{}
|
return model.Reply{}
|
||||||
}
|
}
|
||||||
return model.Reply{
|
return model.Reply{
|
||||||
ReplyMsg: msg.Msg[5:],
|
ReplyMsg: "记下了",
|
||||||
ReferOriginMsg: true,
|
ReferOriginMsg: true,
|
||||||
FromMsg: msg,
|
FromMsg: msg,
|
||||||
}
|
}
|
||||||
|
@ -9,16 +9,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
handler.RegisterHandler("查ss", getScore)
|
handler.RegisterHandler("查ss", getMySS)
|
||||||
handler.RegisterHandler("绑定ss", bindSS)
|
handler.RegisterHandler("绑定ss", bindSS)
|
||||||
handler.RegisterHandler("解绑ss", unbindSS)
|
handler.RegisterHandler("解绑ss", unbindSS)
|
||||||
handler.RegisterHandler("最新ss", getMyRecentScore)
|
handler.RegisterHandler("最新ss", getMyRecentScore)
|
||||||
handler.RegisterHandler("最热ss", getRecentScore)
|
handler.RegisterHandler("最热ss", getRecentScore)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getScore(msg model.Message) (reply model.Reply) {
|
func getMySS(msg model.Message) (reply model.Reply) {
|
||||||
|
resultStr := ""
|
||||||
|
var err error
|
||||||
|
for ; err != nil; resultStr, err = scoresaber.SSQuery.GetScore(strconv.Itoa(int(msg.UserId))) {
|
||||||
|
|
||||||
|
}
|
||||||
return model.Reply{
|
return model.Reply{
|
||||||
ReplyMsg: scoresaber.SSQuery.GetScore(strconv.Itoa(int(msg.UserId))),
|
ReplyMsg: resultStr,
|
||||||
ReferOriginMsg: true,
|
ReferOriginMsg: true,
|
||||||
FromMsg: msg,
|
FromMsg: msg,
|
||||||
}
|
}
|
||||||
@ -54,7 +59,7 @@ func getRecentScore(msg model.Message) (reply model.Reply) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
scoreMsg := ""
|
scoreMsg := ""
|
||||||
for _, v := range scoresaber.ScoresManager.GetRecentScores(count) {
|
for _, v := range scoresaber.ScoresManager.GetRecentScores(count, " WHERE country = 'CN' ") {
|
||||||
scoreMsg += v.ToString() + "\n\n"
|
scoreMsg += v.ToString() + "\n\n"
|
||||||
}
|
}
|
||||||
if len(scoreMsg) > 0 {
|
if len(scoreMsg) > 0 {
|
||||||
|
@ -2,34 +2,24 @@ package jrrp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.lxtend.com/qqbot/sqlite3"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 初始化 SQLite 数据库
|
// 初始化 SQLite 数据库
|
||||||
func initDB() {
|
func initDB() {
|
||||||
db, err := sql.Open("sqlite3", "./jrrp.db")
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
createTableSQL := `CREATE TABLE IF NOT EXISTS jrrp (
|
createTableSQL := `CREATE TABLE IF NOT EXISTS jrrp (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
qqid TEXT UNIQUE,
|
qqid TEXT UNIQUE,
|
||||||
date TEXT,
|
date TEXT,
|
||||||
rp_value INTEGER
|
rp_value INTEGER
|
||||||
);`
|
);`
|
||||||
|
sqlite3.TryCreateTable(createTableSQL)
|
||||||
_, err = db.Exec(createTableSQL)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取今天的日期
|
// 获取今天的日期
|
||||||
@ -50,26 +40,21 @@ func rpValueConstructor() (string, int) {
|
|||||||
|
|
||||||
// Jrrp 结构体
|
// Jrrp 结构体
|
||||||
type Jrrp struct {
|
type Jrrp struct {
|
||||||
db *sql.DB
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewJrrp 创建 Jrrp 实例
|
// NewJrrp 创建 Jrrp 实例
|
||||||
func NewJrrp() *Jrrp {
|
func NewJrrp() *Jrrp {
|
||||||
initDB()
|
initDB()
|
||||||
db, err := sql.Open("sqlite3", "./jrrp.db")
|
return &Jrrp{}
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
return &Jrrp{db: db}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// findJrrp 查找RP数据
|
// findJrrp 查找RP数据
|
||||||
func (j *Jrrp) findJrrp(qqid string) (string, int, error) {
|
func (j *Jrrp) findJrrp(qqid string, tx *sqlx.Tx) (string, int, error) {
|
||||||
var date string
|
var date string
|
||||||
var rpValue int
|
var rpValue int
|
||||||
|
|
||||||
query := "SELECT date, rp_value FROM jrrp WHERE qqid = ?"
|
query := "SELECT date, rp_value FROM jrrp WHERE qqid = ?"
|
||||||
err := j.db.QueryRow(query, qqid).Scan(&date, &rpValue)
|
err := tx.QueryRow(query, qqid).Scan(&date, &rpValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return "", 0, nil
|
return "", 0, nil
|
||||||
@ -80,47 +65,44 @@ func (j *Jrrp) findJrrp(qqid string) (string, int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insertJrrp 插入RP数据
|
// insertJrrp 插入RP数据
|
||||||
func (j *Jrrp) insertJrrp(qqid string, date string, rpValue int) error {
|
func (j *Jrrp) insertJrrp(qqid string, date string, rpValue int, tx *sqlx.Tx) error {
|
||||||
query := "INSERT OR REPLACE INTO jrrp (qqid, date, rp_value) VALUES (?, ?, ?)"
|
query := "INSERT OR REPLACE INTO jrrp (qqid, date, rp_value) VALUES (?, ?, ?)"
|
||||||
_, err := j.db.Exec(query, qqid, date, rpValue)
|
_, err := tx.Exec(query, qqid, date, rpValue)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateJrrp 更新RP数据
|
|
||||||
func (j *Jrrp) updateJrrp(qqid string) error {
|
|
||||||
date, _, err := j.findJrrp(qqid)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if date == "" {
|
|
||||||
return fmt.Errorf("updateJrrp()-> Error: the qqid does not exist!")
|
|
||||||
}
|
|
||||||
newDate, newRpValue := rpValueConstructor()
|
|
||||||
return j.insertJrrp(qqid, newDate, newRpValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetJrrp 获取RP值
|
// GetJrrp 获取RP值
|
||||||
func (j *Jrrp) GetJrrp(qqid string) (int, error) {
|
func (j *Jrrp) GetJrrp(qqid string) (int, error) {
|
||||||
|
tx, err := sqlite3.GetTran()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
today := getTodayFullDate()
|
today := getTodayFullDate()
|
||||||
|
|
||||||
date, rpValue, err := j.findJrrp(qqid)
|
date, rpValue, err := j.findJrrp(qqid, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if date == "" || date != today {
|
if date == "" || date != today {
|
||||||
newDate, newRpValue := rpValueConstructor()
|
newDate, newRpValue := rpValueConstructor()
|
||||||
err = j.insertJrrp(qqid, newDate, newRpValue)
|
err = j.insertJrrp(qqid, newDate, newRpValue, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
if err = tx.Commit(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
return newRpValue, nil
|
return newRpValue, nil
|
||||||
}
|
}
|
||||||
|
if err = tx.Commit(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
return rpValue, nil
|
return rpValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close 关闭数据库连接
|
// Close 关闭数据库连接
|
||||||
func (j *Jrrp) Close() {
|
func (j *Jrrp) Close() {
|
||||||
j.db.Close()
|
sqlite3.GetDB().Close()
|
||||||
}
|
}
|
||||||
|
4
service/say/say.go
Normal file
4
service/say/say.go
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package say
|
||||||
|
|
||||||
|
func saveSay(key string, value string, group string) {
|
||||||
|
}
|
@ -7,16 +7,11 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.lxtend.com/qqbot/sqlite3"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initDB() {
|
func init() {
|
||||||
db, err := sql.Open("sqlite3", "./bindss.db")
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
createBindTableSQL := `CREATE TABLE IF NOT EXISTS ssBind (
|
createBindTableSQL := `CREATE TABLE IF NOT EXISTS ssBind (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
qqid TEXT UNIQUE,
|
qqid TEXT UNIQUE,
|
||||||
@ -60,6 +55,7 @@ func initDB() {
|
|||||||
missed_notes INT,
|
missed_notes INT,
|
||||||
max_combo INT,
|
max_combo INT,
|
||||||
score INT,
|
score INT,
|
||||||
|
max_score INT,
|
||||||
full_combo BOOLEAN,
|
full_combo BOOLEAN,
|
||||||
device_hmd VARCHAR(100),
|
device_hmd VARCHAR(100),
|
||||||
device_controller_left VARCHAR(100),
|
device_controller_left VARCHAR(100),
|
||||||
@ -67,37 +63,18 @@ func initDB() {
|
|||||||
generated_time TEXT
|
generated_time TEXT
|
||||||
);`
|
);`
|
||||||
|
|
||||||
_, err = db.Exec(createBindTableSQL)
|
sqlite3.TryCreateTable(createBindTableSQL)
|
||||||
if err != nil {
|
sqlite3.TryCreateTable(createScoreTableSQL)
|
||||||
log.Print(err)
|
sqlite3.TryCreateTable(createRecordTableSQL)
|
||||||
}
|
|
||||||
_, err = db.Exec(createScoreTableSQL)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
_, err = db.Exec(createRecordTableSQL)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var SSQuery = &ssQuery{}
|
var SSQuery = &ssQuery{}
|
||||||
|
|
||||||
type ssQuery struct {
|
type ssQuery struct {
|
||||||
db *sql.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
initDB()
|
|
||||||
db, err := sql.Open("sqlite3", "./bindss.db")
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
SSQuery = &ssQuery{db: db}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *ssQuery) BindSS(qqId string, ssId string) (reply string) {
|
func (ss *ssQuery) BindSS(qqId string, ssId string) (reply string) {
|
||||||
tx, err := ss.db.Begin()
|
tx, err := sqlite3.GetTran()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
@ -129,7 +106,7 @@ func (ss *ssQuery) BindSS(qqId string, ssId string) (reply string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ss *ssQuery) UnbindSS(qqId string) (reply string) {
|
func (ss *ssQuery) UnbindSS(qqId string) (reply string) {
|
||||||
tx, err := ss.db.Begin()
|
tx, err := sqlite3.GetTran()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
@ -152,24 +129,29 @@ func (ss *ssQuery) UnbindSS(qqId string) (reply string) {
|
|||||||
return "解绑成功,重新绑定请输入\"绑定ss [ssId]\""
|
return "解绑成功,重新绑定请输入\"绑定ss [ssId]\""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *ssQuery) GetScore(qqId string) (reply string) {
|
func (ss *ssQuery) GetScore(qqId string) (reply string, err error) {
|
||||||
tx, err := ss.db.Begin()
|
db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB
|
||||||
|
tx, err := db.Beginx()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
|
return "数据库连接失败,请稍后重试", err
|
||||||
}
|
}
|
||||||
defer tx.Rollback()
|
defer tx.Rollback()
|
||||||
//是否已绑定
|
|
||||||
if rows, err := tx.Query("SELECT * FROM ssBind WHERE qqid = ?", qqId); err == nil {
|
// 检查是否已绑定
|
||||||
if !rows.Next() {
|
|
||||||
return "您未绑定ss账号,输入\"绑定ss [ssId]\"绑定"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var ssId string
|
var ssId string
|
||||||
tx.QueryRow("SELECT ssid FROM ssBind WHERE qqid = ?", qqId).Scan(&ssId)
|
err = tx.Get(&ssId, "SELECT ssid FROM ssBind WHERE qqid = ?", qqId)
|
||||||
|
if err != nil {
|
||||||
|
return "您未绑定ss账号,输入\"绑定ss [ssId]\"绑定", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询玩家数据
|
||||||
data, _ := FetchPlayerData(ssId)
|
data, _ := FetchPlayerData(ssId)
|
||||||
if data == nil {
|
if data == nil {
|
||||||
return "查询出错,服务器返回了空数据"
|
return "查询出错,服务器返回了空数据", errors.New("查询出错,服务器返回了空数据")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 构建 PlayerDataLite 结构体
|
||||||
dataLite := PlayerDataLite{
|
dataLite := PlayerDataLite{
|
||||||
ID: data.ID,
|
ID: data.ID,
|
||||||
Name: data.Name,
|
Name: data.Name,
|
||||||
@ -183,31 +165,60 @@ func (ss *ssQuery) GetScore(qqId string) (reply string) {
|
|||||||
TotalPlayCount: data.ScoreStats.TotalPlayCount,
|
TotalPlayCount: data.ScoreStats.TotalPlayCount,
|
||||||
RankedPlayCount: data.ScoreStats.RankedPlayCount,
|
RankedPlayCount: data.ScoreStats.RankedPlayCount,
|
||||||
ReplaysWatched: data.ScoreStats.ReplaysWatched,
|
ReplaysWatched: data.ScoreStats.ReplaysWatched,
|
||||||
GeneratedTime: time.Now(),
|
GeneratedTime: time.Now().Format("2006-01-02 15:04:05.999999999-07:00"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查询最近的玩家数据
|
||||||
var lastDataLite PlayerDataLite
|
var lastDataLite PlayerDataLite
|
||||||
tx.QueryRow("SELECT * FROM ssData WHERE id = ? ORDER BY generated_time DESC LIMIT 1", dataLite.ID).Scan(&lastDataLite.ID, &lastDataLite.Name, &lastDataLite.Country, &lastDataLite.PP, &lastDataLite.Rank, &lastDataLite.CountryRank, &lastDataLite.TotalScore, &lastDataLite.TotalRankedScore, &lastDataLite.AverageRankedAccuracy, &lastDataLite.TotalPlayCount, &lastDataLite.RankedPlayCount, &lastDataLite.ReplaysWatched, &lastDataLite.GeneratedTime)
|
err = tx.Get(&lastDataLite, "SELECT * FROM ssData WHERE id = ? ORDER BY generated_time DESC LIMIT 1", dataLite.ID)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
log.Print(err)
|
||||||
|
return "查询历史数据时出错", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有新的数据,则插入
|
||||||
if lastDataLite.TotalPlayCount != dataLite.TotalPlayCount {
|
if lastDataLite.TotalPlayCount != dataLite.TotalPlayCount {
|
||||||
tx.Exec("INSERT INTO ssData(id, name, country, pp, rank, country_rank, total_score, total_ranked_score, average_ranked_accuracy, total_play_count, ranked_play_count, replays_watched, generated_time) VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)", dataLite.ID, dataLite.Name, dataLite.Country, dataLite.PP, dataLite.Rank, dataLite.CountryRank, dataLite.TotalScore, dataLite.TotalRankedScore, dataLite.AverageRankedAccuracy, dataLite.TotalPlayCount, dataLite.RankedPlayCount, dataLite.ReplaysWatched, dataLite.GeneratedTime)
|
_, err = tx.NamedExec(`INSERT INTO ssData (id, name, country, pp, rank, country_rank, total_score,
|
||||||
|
total_ranked_score, average_ranked_accuracy, total_play_count, ranked_play_count, replays_watched, generated_time)
|
||||||
|
VALUES (:id, :name, :country, :pp, :rank, :country_rank, :total_score,
|
||||||
|
:total_ranked_score, :average_ranked_accuracy, :total_play_count, :ranked_play_count, :replays_watched, :generated_time)`, dataLite)
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
return "插入新数据时出错", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交事务
|
||||||
err = tx.Commit()
|
err = tx.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "SQL事务提交失败,请重试"
|
log.Print(err)
|
||||||
|
return "SQL事务提交失败,请重试", err
|
||||||
}
|
}
|
||||||
return data.LastDiffToString(lastDataLite)
|
|
||||||
|
// 返回差异信息
|
||||||
|
return data.LastDiffToString(lastDataLite), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果没有新数据,直接提交事务
|
||||||
err = tx.Commit()
|
err = tx.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "SQL事务提交失败,请重试"
|
log.Print(err)
|
||||||
|
return "SQL事务提交失败,请重试", err
|
||||||
}
|
}
|
||||||
return data.ToString()
|
|
||||||
|
// 返回当前数据的字符串表示
|
||||||
|
return data.ToString(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *ssQuery) SaveRecord(cmdData CommandData) {
|
func (ss *ssQuery) SaveRecord(cmdData CommandData) {
|
||||||
tx, err := ss.db.Begin()
|
db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB
|
||||||
|
tx, err := db.Beginx()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer tx.Rollback()
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
// 创建 RecordDataLite 结构体实例
|
||||||
dataLite := RecordDataLite{
|
dataLite := RecordDataLite{
|
||||||
ScoreID: cmdData.Score.ID,
|
ScoreID: cmdData.Score.ID,
|
||||||
SsID: cmdData.Score.LeaderboardPlayerInfo.ID,
|
SsID: cmdData.Score.LeaderboardPlayerInfo.ID,
|
||||||
@ -226,6 +237,7 @@ func (ss *ssQuery) SaveRecord(cmdData CommandData) {
|
|||||||
Multiplier: cmdData.Score.Multiplier,
|
Multiplier: cmdData.Score.Multiplier,
|
||||||
BadCuts: cmdData.Score.BadCuts,
|
BadCuts: cmdData.Score.BadCuts,
|
||||||
Score: cmdData.Score.ModifiedScore,
|
Score: cmdData.Score.ModifiedScore,
|
||||||
|
MaxScore: cmdData.Leaderboard.MaxScore,
|
||||||
MissedNotes: cmdData.Score.MissedNotes,
|
MissedNotes: cmdData.Score.MissedNotes,
|
||||||
MaxCombo: cmdData.Score.MaxCombo,
|
MaxCombo: cmdData.Score.MaxCombo,
|
||||||
FullCombo: cmdData.Score.FullCombo,
|
FullCombo: cmdData.Score.FullCombo,
|
||||||
@ -234,6 +246,8 @@ func (ss *ssQuery) SaveRecord(cmdData CommandData) {
|
|||||||
DeviceControllerRight: "",
|
DeviceControllerRight: "",
|
||||||
GeneratedTime: time.Now().Format("2006-01-02 15:04:05.999999999-07:00"),
|
GeneratedTime: time.Now().Format("2006-01-02 15:04:05.999999999-07:00"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查设备信息并设置
|
||||||
if cmdData.Score.DeviceHmd != nil {
|
if cmdData.Score.DeviceHmd != nil {
|
||||||
dataLite.DeviceHmd = *cmdData.Score.DeviceHmd
|
dataLite.DeviceHmd = *cmdData.Score.DeviceHmd
|
||||||
}
|
}
|
||||||
@ -243,9 +257,25 @@ func (ss *ssQuery) SaveRecord(cmdData CommandData) {
|
|||||||
if cmdData.Score.DeviceControllerRight != nil {
|
if cmdData.Score.DeviceControllerRight != nil {
|
||||||
dataLite.DeviceControllerRight = *cmdData.Score.DeviceControllerRight
|
dataLite.DeviceControllerRight = *cmdData.Score.DeviceControllerRight
|
||||||
}
|
}
|
||||||
if _, err = tx.Exec("INSERT INTO ssRecordData(score_id, ss_id, name, country, song_name, song_sub_name, song_author_name, song_hash, cover_image, difficulty_raw, pp, stars, weight, modifiers, multiplier, bad_cuts, missed_notes, max_combo,score, full_combo, device_hmd, device_controller_left, device_controller_right, generated_time) VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23,?24)", dataLite.ScoreID, dataLite.SsID, dataLite.Name, dataLite.Country, dataLite.SongName, dataLite.SongSubName, dataLite.SongAuthorName, dataLite.SongHash, dataLite.CoverImage, dataLite.DifficultyRaw, dataLite.PP, dataLite.Stars, dataLite.Weight, dataLite.Modifiers, dataLite.Multiplier, dataLite.BadCuts, dataLite.MissedNotes, dataLite.MaxCombo, dataLite.Score, dataLite.FullCombo, dataLite.DeviceHmd, dataLite.DeviceControllerLeft, dataLite.DeviceControllerRight, dataLite.GeneratedTime); err != nil {
|
|
||||||
|
// 使用 NamedExec 插入数据
|
||||||
|
_, err = tx.NamedExec(`INSERT INTO ssRecordData
|
||||||
|
(score_id, ss_id, name, country, song_name, song_sub_name, song_author_name,
|
||||||
|
song_hash, cover_image, difficulty_raw, pp, stars, weight, modifiers,
|
||||||
|
multiplier, bad_cuts, missed_notes, max_combo, score, max_score,
|
||||||
|
full_combo, device_hmd, device_controller_left, device_controller_right,
|
||||||
|
generated_time)
|
||||||
|
VALUES (:score_id, :ss_id, :name, :country, :song_name, :song_sub_name,
|
||||||
|
:song_author_name, :song_hash, :cover_image, :difficulty_raw, :pp, :stars,
|
||||||
|
:weight, :modifiers, :multiplier, :bad_cuts, :missed_notes, :max_combo,
|
||||||
|
:score, :max_score, :full_combo, :device_hmd, :device_controller_left,
|
||||||
|
:device_controller_right, :generated_time)`, dataLite)
|
||||||
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提交事务
|
||||||
err = tx.Commit()
|
err = tx.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
@ -253,37 +283,42 @@ func (ss *ssQuery) SaveRecord(cmdData CommandData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ss *ssQuery) GetRecentScores(count int, qqId string) ([]RecordDataLite, error) {
|
func (ss *ssQuery) GetRecentScores(count int, qqId string) ([]RecordDataLite, error) {
|
||||||
tx, err := ss.db.Begin()
|
db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB
|
||||||
|
tx, err := db.Beginx()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
|
return nil, errors.New("数据库连接失败,请稍后重试")
|
||||||
}
|
}
|
||||||
defer tx.Rollback()
|
defer tx.Rollback()
|
||||||
|
|
||||||
|
// 查询绑定的 ssId
|
||||||
var ssId string
|
var ssId string
|
||||||
tx.QueryRow("SELECT ssid FROM ssBind WHERE qqid = ?", qqId).Scan(&ssId)
|
err = tx.Get(&ssId, "SELECT ssid FROM ssBind WHERE qqid = ?", qqId)
|
||||||
if ssId == "" {
|
if err != nil {
|
||||||
return nil, errors.New("未绑定ss账号,输入\"绑定ss [ssId]\"绑定")
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, errors.New("未绑定ss账号,输入\"绑定ss [ssId]\"绑定")
|
||||||
|
}
|
||||||
|
log.Println("查询 ssId 出错:", err)
|
||||||
|
return nil, errors.New("查询 ssId 失败")
|
||||||
}
|
}
|
||||||
rows, err := tx.Query("SELECT * FROM ssRecordData WHERE ss_id = ? ORDER BY generated_time DESC LIMIT ?", ssId, count)
|
|
||||||
|
// 查询记录
|
||||||
|
var records []RecordDataLite
|
||||||
|
err = tx.Select(&records, "SELECT * FROM ssRecordData WHERE ss_id = ? ORDER BY generated_time DESC LIMIT ?", ssId, count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, errors.New("未查询到数据")
|
return nil, errors.New("未查询到数据")
|
||||||
}
|
}
|
||||||
log.Println("Query error:", err)
|
log.Println("查询数据出错:", err)
|
||||||
return nil, errors.New("")
|
return nil, errors.New("查询记录失败")
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
var records []RecordDataLite
|
|
||||||
for rows.Next() {
|
|
||||||
var record RecordDataLite
|
|
||||||
if err := rows.Scan(&record.ID, &record.ScoreID, &record.SsID, &record.Name, &record.Country, &record.SongName, &record.SongSubName, &record.SongAuthorName, &record.SongHash, &record.CoverImage, &record.DifficultyRaw, &record.PP, &record.Stars, &record.Weight, &record.Modifiers, &record.Multiplier, &record.BadCuts, &record.MissedNotes, &record.MaxCombo, &record.Score, &record.FullCombo, &record.DeviceHmd, &record.DeviceControllerLeft, &record.DeviceControllerRight, &record.GeneratedTime); err != nil {
|
|
||||||
log.Println("Scan error:", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
records = append(records, record)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提交事务
|
||||||
err = tx.Commit()
|
err = tx.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
|
return nil, errors.New("提交事务失败")
|
||||||
}
|
}
|
||||||
|
|
||||||
return records, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
5
service/scoresaber/gen_picture.go
Normal file
5
service/scoresaber/gen_picture.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package scoresaber
|
||||||
|
|
||||||
|
func (data *PlayerData) ToPicture() (outputImgPath string) {
|
||||||
|
return ""
|
||||||
|
}
|
@ -2,9 +2,9 @@ package scoresaber
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.lxtend.com/qqbot/sqlite3"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,10 +13,8 @@ const wsURL = "wss://scoresaber.com/ws"
|
|||||||
var ScoresManager = scoresManager{}
|
var ScoresManager = scoresManager{}
|
||||||
|
|
||||||
type scoresManager struct {
|
type scoresManager struct {
|
||||||
recentScores []Command
|
conn *websocket.Conn
|
||||||
mu sync.Mutex
|
retryTimes int
|
||||||
conn *websocket.Conn
|
|
||||||
retryTimes int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -33,7 +31,6 @@ func (sm *scoresManager) connect() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sm.retryTimes = 0
|
sm.retryTimes = 0
|
||||||
sm.recentScores = make([]Command, 0)
|
|
||||||
go sm.receiveData()
|
go sm.receiveData()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -58,25 +55,24 @@ func (sm *scoresManager) receiveData() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
SSQuery.SaveRecord(cmd.CommandData)
|
SSQuery.SaveRecord(cmd.CommandData)
|
||||||
if cmd.CommandData.Score.LeaderboardPlayerInfo.Country != "CN" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sm.mu.Lock()
|
|
||||||
if len(sm.recentScores) >= 50 {
|
|
||||||
sm.recentScores = sm.recentScores[1:]
|
|
||||||
}
|
|
||||||
sm.recentScores = append(sm.recentScores, cmd)
|
|
||||||
sm.mu.Unlock()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *scoresManager) GetRecentScores(count int) []Command {
|
func (sm *scoresManager) GetRecentScores(count int, predict string) []RecordDataLite {
|
||||||
sm.mu.Lock()
|
db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB
|
||||||
defer sm.mu.Unlock()
|
scoresCopy := make([]RecordDataLite, 0, count)
|
||||||
if count > len(sm.recentScores) {
|
|
||||||
count = len(sm.recentScores)
|
query := "SELECT * FROM ssRecordData"
|
||||||
|
if predict != "" {
|
||||||
|
query += " " + predict
|
||||||
}
|
}
|
||||||
scoresCopy := make([]Command, count)
|
query += " ORDER BY generated_time DESC LIMIT ?"
|
||||||
copy(scoresCopy, sm.recentScores[len(sm.recentScores)-count:])
|
|
||||||
|
err := db.Select(&scoresCopy, query, count)
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return scoresCopy
|
return scoresCopy
|
||||||
}
|
}
|
||||||
|
@ -129,6 +129,7 @@ type RecordDataLite struct {
|
|||||||
MissedNotes int `json:"missedNotes" db:"missed_notes"`
|
MissedNotes int `json:"missedNotes" db:"missed_notes"`
|
||||||
MaxCombo int `json:"maxCombo" db:"max_combo"`
|
MaxCombo int `json:"maxCombo" db:"max_combo"`
|
||||||
Score int `json:"score" db:"score"`
|
Score int `json:"score" db:"score"`
|
||||||
|
MaxScore int `json:"maxScore" db:"max_score"`
|
||||||
FullCombo bool `json:"fullCombo" db:"full_combo"`
|
FullCombo bool `json:"fullCombo" db:"full_combo"`
|
||||||
DeviceHmd string `json:"deviceHmd" db:"device_hmd"`
|
DeviceHmd string `json:"deviceHmd" db:"device_hmd"`
|
||||||
DeviceControllerLeft string `json:"deviceControllerLeft" db:"device_controller_left"`
|
DeviceControllerLeft string `json:"deviceControllerLeft" db:"device_controller_left"`
|
||||||
@ -137,19 +138,19 @@ type RecordDataLite struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r RecordDataLite) ToString() string {
|
func (r RecordDataLite) ToString() string {
|
||||||
formatedStrRanked := "使用 %s 在 %s 的 %s 难度(%.1f星级)中获得了 %d 分,pp 为 %.2f。"
|
formatedStrRanked := "%s 使用 %s 在 %s 的 %s 难度(%.1f星级)中获得了 %d 分,pp 为 %.2f,准度为 %s。"
|
||||||
formatedStrUnranked := "使用 %s 在 %s 的 %s 难度中获得了 %d 分。"
|
formatedStrUnranked := "%s 使用 %s 在 %s 的 %s 难度中获得了 %d 分,准度为 %s。"
|
||||||
formatedStrWithoutDevice := "在 %s 的 %s 难度(%.1f星级)中获得了 %d 分,pp 为 %.2f。"
|
formatedStrWithoutDevice := "%s 在 %s 的 %s 难度(%.1f星级)中获得了 %d 分,pp 为 %.2f,准度为 %s。"
|
||||||
formatedStrWithoutDeviceAndRank := "在 %s 的 %s 难度(%.1f星级)中获得了 %d 分。"
|
formatedStrWithoutDeviceAndRank := "%s 在 %s 的 %s 难度(%.1f星级)中获得了 %d 分,准度为 %s。"
|
||||||
hardStr := strings.Split(r.DifficultyRaw, "_")[1]
|
hardStr := strings.Split(r.DifficultyRaw, "_")[1]
|
||||||
if r.Stars == 0 && r.DeviceHmd != "" {
|
if r.Stars == 0 && r.DeviceHmd != "" {
|
||||||
return fmt.Sprintf(formatedStrUnranked, r.DeviceHmd, r.SongName, hardStr, r.Score)
|
return fmt.Sprintf(formatedStrUnranked, r.Name, r.DeviceHmd, r.SongName, hardStr, r.Score, fmt.Sprintf("%.2f%%", float64(r.Score)/float64(r.MaxScore)*100))
|
||||||
} else if r.Stars != 0 && r.DeviceHmd != "" {
|
} else if r.Stars != 0 && r.DeviceHmd != "" {
|
||||||
return fmt.Sprintf(formatedStrRanked, r.DeviceHmd, r.SongName, hardStr, r.Stars, r.Score, r.PP)
|
return fmt.Sprintf(formatedStrRanked, r.Name, r.DeviceHmd, r.SongName, hardStr, r.Stars, r.Score, r.PP, fmt.Sprintf("%.2f%%", float64(r.Score)/float64(r.MaxScore)*100))
|
||||||
} else if r.Stars != 0 && r.DeviceHmd == "" {
|
} else if r.Stars != 0 && r.DeviceHmd == "" {
|
||||||
return fmt.Sprintf(formatedStrWithoutDevice, r.SongName, hardStr, r.Stars, r.Score, r.PP)
|
return fmt.Sprintf(formatedStrWithoutDevice, r.Name, r.SongName, hardStr, r.Stars, r.Score, r.PP, fmt.Sprintf("%.2f%%", float64(r.Score)/float64(r.MaxScore)*100))
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf(formatedStrWithoutDeviceAndRank, r.SongName, hardStr, r.Stars, r.Score)
|
return fmt.Sprintf(formatedStrWithoutDeviceAndRank, r.Name, r.SongName, hardStr, r.Stars, r.Score, fmt.Sprintf("%.2f%%", float64(r.Score)/float64(r.MaxScore)*100))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,20 +187,20 @@ type PlayerData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PlayerDataLite struct {
|
type PlayerDataLite struct {
|
||||||
ID string `json:"id" db:"id"`
|
ID string `json:"id" db:"id"`
|
||||||
Name string `json:"name" db:"name"`
|
Name string `json:"name" db:"name"`
|
||||||
Country string `json:"country" db:"country"`
|
Country string `json:"country" db:"country"`
|
||||||
Device string `json:"device" db:"device"`
|
Device string `json:"device" db:"device"`
|
||||||
PP float64 `json:"pp" db:"pp"`
|
PP float64 `json:"pp" db:"pp"`
|
||||||
Rank int `json:"rank" db:"rank"`
|
Rank int `json:"rank" db:"rank"`
|
||||||
CountryRank int `json:"countryRank" db:"country_rank"`
|
CountryRank int `json:"countryRank" db:"country_rank"`
|
||||||
TotalScore int `json:"totalScore" db:"total_score"`
|
TotalScore int `json:"totalScore" db:"total_score"`
|
||||||
TotalRankedScore int `json:"totalRankedScore" db:"total_ranked_score"`
|
TotalRankedScore int `json:"totalRankedScore" db:"total_ranked_score"`
|
||||||
AverageRankedAccuracy float64 `json:"averageRankedAccuracy" db:"average_ranked_accuracy"`
|
AverageRankedAccuracy float64 `json:"averageRankedAccuracy" db:"average_ranked_accuracy"`
|
||||||
TotalPlayCount int `json:"totalPlayCount" db:"total_play_count"`
|
TotalPlayCount int `json:"totalPlayCount" db:"total_play_count"`
|
||||||
RankedPlayCount int `json:"rankedPlayCount" db:"ranked_play_count"`
|
RankedPlayCount int `json:"rankedPlayCount" db:"ranked_play_count"`
|
||||||
ReplaysWatched int `json:"replaysWatched" db:"replays_watched"`
|
ReplaysWatched int `json:"replaysWatched" db:"replays_watched"`
|
||||||
GeneratedTime time.Time `json:"generatedTime" db:"generated_time"`
|
GeneratedTime string `json:"generatedTime" db:"generated_time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PlayerData) ToString() string {
|
func (p PlayerData) ToString() string {
|
||||||
|
@ -7,9 +7,9 @@ import (
|
|||||||
"github.com/fogleman/gg"
|
"github.com/fogleman/gg"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenerateCongratulationImage(text string, outputFile string) {
|
func GenerateCongratulationImage(text string, inputFile, outputFile string, isGood bool) {
|
||||||
// 加载喜报背景图片
|
// 加载喜报背景图片
|
||||||
im, err := gg.LoadImage("./resource/xibao_background.png") // 需要提前准备的背景图片
|
im, err := gg.LoadImage(inputFile) // 需要提前准备的背景图片
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print("无法加载喜报图片:", err)
|
log.Print("无法加载喜报图片:", err)
|
||||||
return
|
return
|
||||||
@ -28,10 +28,12 @@ func GenerateCongratulationImage(text string, outputFile string) {
|
|||||||
log.Print("无法加载字体:", err)
|
log.Print("无法加载字体:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if isGood {
|
||||||
// 设置文本颜色为红色
|
// 设置文本颜色为红色
|
||||||
dc.SetRGB(1, 0, 0)
|
dc.SetRGB(1, 0.1, 0.1)
|
||||||
|
} else {
|
||||||
|
dc.SetRGB(0.1, 0.1, 1)
|
||||||
|
}
|
||||||
// 将文本按 \n 分割为多行
|
// 将文本按 \n 分割为多行
|
||||||
lines := strings.Split(text, "\n")
|
lines := strings.Split(text, "\n")
|
||||||
|
|
||||||
|
32
sqlite3/db.go
Normal file
32
sqlite3/db.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package sqlite3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var db *sqlx.DB
|
||||||
|
|
||||||
|
func InitDB() {
|
||||||
|
if db == nil {
|
||||||
|
db, _ = sqlx.Open("sqlite3", "./data.db")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TryCreateTable(query string) error {
|
||||||
|
InitDB()
|
||||||
|
_, err := db.Exec(query)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDB() *sqlx.DB {
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTran() (*sqlx.Tx, error) {
|
||||||
|
return db.Beginx()
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user