fix extra

This commit is contained in:
源文雨 2023-04-08 17:18:36 +08:00
parent 635eb9832a
commit 5c8ead8b1d
14 changed files with 187 additions and 188 deletions

View File

@ -1250,7 +1250,7 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 签到 - [x] 签到
- [x] 获得签到背景[@xxx] | 获得签到背景 - [x] 获得签到背景[@xxx] | 获得签到背景
- [x] 设置[默认]签到预设(1~9) - [x] 设置签到预设(0~3)
- [x] 查看等级排名 - [x] 查看等级排名
- 注:跨群排行 - 注:跨群排行
- [x] 查看我的钱包 - [x] 查看我的钱包

4
go.mod
View File

@ -11,8 +11,8 @@ require (
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.6.2 github.com/FloatTech/sqlite v1.6.2
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
github.com/FloatTech/zbpctrl v1.5.3-0.20230406055807-cb5f5edad2c7 github.com/FloatTech/zbpctrl v1.5.3-0.20230408032827-50ef967f2849
github.com/FloatTech/zbputils v1.6.2-0.20230407083549-931d7968df13 github.com/FloatTech/zbputils v1.6.2-0.20230408085317-f2f525cff6fc
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5 github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5
github.com/antchfx/htmlquery v1.2.5 github.com/antchfx/htmlquery v1.2.5

8
go.sum
View File

@ -16,10 +16,10 @@ github.com/FloatTech/sqlite v1.6.2 h1:FytbExjpvYalZxxITtmSenHiPGLPUvlz47LY/P0SCC
github.com/FloatTech/sqlite v1.6.2/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY= github.com/FloatTech/sqlite v1.6.2/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY=
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw= github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw=
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs= github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
github.com/FloatTech/zbpctrl v1.5.3-0.20230406055807-cb5f5edad2c7 h1:ii/HjRAAH1Ot1mwg4r+kabiI0H8EZ/PwTZryEbN4Jvg= github.com/FloatTech/zbpctrl v1.5.3-0.20230408032827-50ef967f2849 h1:ARKWV3tXJLENWY6vcwTStEDwJckYnxoHXgZMsuJ3gUw=
github.com/FloatTech/zbpctrl v1.5.3-0.20230406055807-cb5f5edad2c7/go.mod h1:IagyEhY38VcbbQgVRzAM9f9mhaUn90rM5BTPfudtl1g= github.com/FloatTech/zbpctrl v1.5.3-0.20230408032827-50ef967f2849/go.mod h1:IagyEhY38VcbbQgVRzAM9f9mhaUn90rM5BTPfudtl1g=
github.com/FloatTech/zbputils v1.6.2-0.20230407083549-931d7968df13 h1:7HX4TP7/ihnoCvD/XyM2nxi4EI0wClQB7SSDCSgfx8I= github.com/FloatTech/zbputils v1.6.2-0.20230408085317-f2f525cff6fc h1:myLvTVYvTaBgKoXJW1rHPFfr0W4wWPlJQ5DlKBhfHuw=
github.com/FloatTech/zbputils v1.6.2-0.20230407083549-931d7968df13/go.mod h1:iPlPghAE6SSDBZPHA6ZiPyspfeVDNQqtfLDkftHlD4I= github.com/FloatTech/zbputils v1.6.2-0.20230408085317-f2f525cff6fc/go.mod h1:GLuSpLdTOCpqkR1oxqjuDz/rOif/ZrH4zGhtMzBqlqo=
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA= github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA=
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w= github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=

View File

@ -2,10 +2,8 @@ package aireply
import ( import (
"errors" "errors"
"net/url"
"github.com/RomiChan/syncx" "github.com/RomiChan/syncx"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot" zero "github.com/wdvxdr1123/ZeroBot"
"github.com/FloatTech/AnimeAPI/aireply" "github.com/FloatTech/AnimeAPI/aireply"
@ -54,25 +52,23 @@ var ttscnspeakers = [...]string{
"晓甄(女 - 年轻人)", "晓甄(女 - 年轻人)",
} }
const ( const defaultttsindexkey = -2905
defaultttsindexkey = -2905
gsapikeyextragrp = -1 var (
chatgptapikeyextragrp = -2 = newapikeystore("./data/tts/o.txt")
ཆཏ = newapikeystore("./data/tts/c.txt")
) )
type replymode struct { type replymode []string
APIKey string // APIKey is for chatgpt
replyModes []string `json:"-"`
}
func (r *replymode) setReplyMode(ctx *zero.Ctx, name string) error { func (r replymode) setReplyMode(ctx *zero.Ctx, name string) error {
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
if gid == 0 { if gid == 0 {
gid = -ctx.Event.UserID gid = -ctx.Event.UserID
} }
var ok bool var ok bool
var index int64 var index int64
for i, s := range r.replyModes { for i, s := range r {
if s == name { if s == name {
ok = true ok = true
index = int64(i) index = int64(i)
@ -89,7 +85,7 @@ func (r *replymode) setReplyMode(ctx *zero.Ctx, name string) error {
return m.SetData(gid, (m.GetData(index)&^0xff)|(index&0xff)) return m.SetData(gid, (m.GetData(index)&^0xff)|(index&0xff))
} }
func (r *replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply { func (r replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply {
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
if gid == 0 { if gid == 0 {
gid = -ctx.Event.UserID gid = -ctx.Event.UserID
@ -102,7 +98,7 @@ func (r *replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply {
case 1: case 1:
return aireply.NewXiaoAi(aireply.XiaoAiURL, aireply.XiaoAiBotName) return aireply.NewXiaoAi(aireply.XiaoAiURL, aireply.XiaoAiBotName)
case 2: case 2:
k := r.getAPIKey(ctx) k := ཆཏ.k
if k != "" { if k != "" {
return aireply.NewChatGPT(aireply.ChatGPTURL, k) return aireply.NewChatGPT(aireply.ChatGPTURL, k)
} }
@ -112,21 +108,6 @@ func (r *replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply {
return aireply.NewQYK(aireply.QYKURL, aireply.QYKBotName) return aireply.NewQYK(aireply.QYKURL, aireply.QYKBotName)
} }
func (r *replymode) getAPIKey(ctx *zero.Ctx) string {
if r.APIKey == "" {
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
_ = m.Manager.GetExtra(chatgptapikeyextragrp, &r)
logrus.Debugln("[tts] get api key:", r.APIKey)
}
return r.APIKey
}
func (r *replymode) setAPIKey(m *ctrl.Control[*zero.Ctx], key string) error {
r.APIKey = key
_ = m.Manager.Response(chatgptapikeyextragrp)
return m.Manager.SetExtra(chatgptapikeyextragrp, r)
}
var ttsins = func() map[string]tts.TTS { var ttsins = func() map[string]tts.TTS {
m := make(map[string]tts.TTS, 128) m := make(map[string]tts.TTS, 128)
for _, mode := range append(genshin.SoundList[:], extrattsname...) { for _, mode := range append(genshin.SoundList[:], extrattsname...) {
@ -141,10 +122,7 @@ var ttsModes = func() []string {
return s return s
}() }()
type ttsmode struct { type ttsmode syncx.Map[int64, int64]
APIKey string // APIKey is for genshin vits
mode syncx.Map[int64, int64] `json:"-"` // mode grp index
}
func list(list []string, num int) string { func list(list []string, num int) string {
s := "" s := ""
@ -162,33 +140,17 @@ func list(list []string, num int) string {
func newttsmode() *ttsmode { func newttsmode() *ttsmode {
t := &ttsmode{} t := &ttsmode{}
m, ok := control.Lookup("tts") m, ok := control.Lookup("tts")
t.mode = syncx.Map[int64, int64]{} (*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, 0)
t.mode.Store(defaultttsindexkey, 0)
if ok { if ok {
index := m.GetData(defaultttsindexkey) index := m.GetData(defaultttsindexkey)
msk := index & 0xff msk := index & 0xff
if msk >= 0 && (msk < int64(len(genshin.SoundList)) || msk == baiduttsindex || msk == ttscnttsindex) { if msk >= 0 && (msk < int64(len(genshin.SoundList)) || msk == baiduttsindex || msk == ttscnttsindex) {
t.mode.Store(defaultttsindexkey, index) (*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, index)
} }
} }
return t return t
} }
func (t *ttsmode) getAPIKey(ctx *zero.Ctx) string {
if t.APIKey == "" {
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
_ = m.Manager.GetExtra(gsapikeyextragrp, &t)
logrus.Debugln("[tts] get api key:", t.APIKey)
}
return url.QueryEscape(t.APIKey)
}
func (t *ttsmode) setAPIKey(m *ctrl.Control[*zero.Ctx], key string) error {
t.APIKey = key
_ = m.Manager.Response(gsapikeyextragrp)
return m.Manager.SetExtra(gsapikeyextragrp, t)
}
func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, baiduper, mockingsynt int) error { func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, baiduper, mockingsynt int) error {
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
if gid == 0 { if gid == 0 {
@ -216,7 +178,7 @@ func (t *ttsmode) setSoundMode(ctx *zero.Ctx, name string, baiduper, mockingsynt
} }
} }
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
t.mode.Store(gid, index) (*syncx.Map[int64, int64])(t).Store(gid, index)
return m.SetData(gid, (m.GetData(gid)&^0xffff00)|((index<<8)&0xff00)|((int64(baiduper)<<16)&0x0f0000)|((int64(mockingsynt)<<20)&0xf00000)) return m.SetData(gid, (m.GetData(gid)&^0xffff00)|((index<<8)&0xff00)|((int64(baiduper)<<16)&0x0f0000)|((int64(mockingsynt)<<20)&0xf00000))
} }
@ -225,14 +187,14 @@ func (t *ttsmode) getSoundMode(ctx *zero.Ctx) (tts.TTS, error) {
if gid == 0 { if gid == 0 {
gid = -ctx.Event.UserID gid = -ctx.Event.UserID
} }
i, ok := t.mode.Load(gid) i, ok := (*syncx.Map[int64, int64])(t).Load(gid)
if !ok { if !ok {
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
i = m.GetData(gid) >> 8 i = m.GetData(gid) >> 8
} }
m := i & 0xff m := i & 0xff
if m < 0 || (m >= int64(len(genshin.SoundList)) && m != baiduttsindex && m != ttscnttsindex) { if m < 0 || (m >= int64(len(genshin.SoundList)) && m != baiduttsindex && m != ttscnttsindex) {
i, _ = t.mode.Load(defaultttsindexkey) i, _ = (*syncx.Map[int64, int64])(t).Load(defaultttsindexkey)
m = i & 0xff m = i & 0xff
} }
mode := ttsModes[m] mode := ttsModes[m]
@ -248,9 +210,9 @@ func (t *ttsmode) getSoundMode(ctx *zero.Ctx) (tts.TTS, error) {
return nil, err return nil, err
} }
default: // 原神 default: // 原神
k := t.getAPIKey(ctx) k := .k
if k != "" { if k != "" {
ins = genshin.NewGenshin(int(m), t.getAPIKey(ctx)) ins = genshin.NewGenshin(int(m), .k)
ttsins[mode] = ins ttsins[mode] = ins
} else { } else {
return nil, errors.New("no valid speaker") return nil, errors.New("no valid speaker")
@ -296,6 +258,6 @@ func (t *ttsmode) setDefaultSoundMode(name string, baiduper, mockingsynt int) er
if !ok { if !ok {
return errors.New("[tts] service not found") return errors.New("[tts] service not found")
} }
t.mode.Store(defaultttsindexkey, index) (*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, index)
return m.SetData(defaultttsindexkey, (index&0xff)|((int64(baiduper)<<8)&0x0f00)|((int64(mockingsynt)<<12)&0xf000)) return m.SetData(defaultttsindexkey, (index&0xff)|((int64(baiduper)<<8)&0x0f00)|((int64(mockingsynt)<<12)&0xf000))
} }

View File

@ -15,9 +15,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message" "github.com/wdvxdr1123/ZeroBot/message"
) )
var replmd = replymode{ var replmd = replymode([]string{"青云客", "小爱", "ChatGPT"})
replyModes: []string{"青云客", "小爱", "ChatGPT"},
}
var ttsmd = newttsmode() var ttsmd = newttsmode()
@ -32,6 +30,7 @@ func init() { // 插件主体
"- 设置原神语音 api key xxxxxx (key请加开发群获得)\n" + "- 设置原神语音 api key xxxxxx (key请加开发群获得)\n" +
"当前适用的原神人物含有以下: \n" + list(genshin.SoundList[:], 5) + "当前适用的原神人物含有以下: \n" + list(genshin.SoundList[:], 5) +
"\n当前适用的TTSCN人物含有以下(以数字顺序代表): \n" + list(ttscnspeakers[:], 5), "\n当前适用的TTSCN人物含有以下(以数字顺序代表): \n" + list(ttscnspeakers[:], 5),
PrivateDataFolder: "tts",
}) })
enr := control.Register("aireply", &ctrl.Options[*zero.Ctx]{ enr := control.Register("aireply", &ctrl.Options[*zero.Ctx]{
@ -66,7 +65,7 @@ func init() { // 插件主体
}) })
enr.OnRegex(`^设置\s*ChatGPT\s*api\s*key\s*(.*)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) { enr.OnRegex(`^设置\s*ChatGPT\s*api\s*key\s*(.*)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
err := replmd.setAPIKey(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), ctx.State["regex_matched"].([]string)[1]) err := ཆཏ.set(ctx.State["regex_matched"].([]string)[1])
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
@ -184,7 +183,7 @@ func init() { // 插件主体
}) })
ent.OnRegex(`^设置原神语音\s*api\s*key\s*([0-9a-zA-Z-_]{54}==)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) { ent.OnRegex(`^设置原神语音\s*api\s*key\s*([0-9a-zA-Z-_]{54}==)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
err := ttsmd.setAPIKey(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]), ctx.State["regex_matched"].([]string)[1]) err := .set(ctx.State["regex_matched"].([]string)[1])
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return

29
plugin/ai_reply/model.go Normal file
View File

@ -0,0 +1,29 @@
package aireply
import (
"os"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
)
type apikeystore struct {
k string
p string
}
func newapikeystore(p string) (s apikeystore) {
s.p = p
if file.IsExist(p) {
data, err := os.ReadFile(p)
if err == nil {
s.k = binary.BytesToString(data)
}
}
return
}
func (s *apikeystore) set(k string) error {
s.k = k
return os.WriteFile(s.p, binary.StringToBytes(k), 0644)
}

View File

@ -25,6 +25,8 @@ var speakers = map[string]uint{
"派蒙": 0, "凯亚": 1, "安柏": 2, "丽莎": 3, "琴": 4, "香菱": 5, "枫原万叶": 6, "迪卢克": 7, "温迪": 8, "可莉": 9, "早柚": 10, "托马": 11, "芭芭拉": 12, "优菈": 13, "云堇": 14, "钟离": 15, "魈": 16, "凝光": 17, "雷电将军": 18, "北斗": 19, "甘雨": 20, "七七": 21, "刻晴": 22, "神里绫华": 23, "戴因斯雷布": 24, "雷泽": 25, "神里绫人": 26, "罗莎莉亚": 27, "阿贝多": 28, "八重神子": 29, "宵宫": 30, "荒泷一斗": 31, "九条裟罗": 32, "夜兰": 33, "珊瑚宫心海": 34, "五郎": 35, "散兵": 36, "女士": 37, "达达利亚": 38, "莫娜": 39, "班尼特": 40, "申鹤": 41, "行秋": 42, "烟绯": 43, "久岐忍": 44, "辛焱": 45, "砂糖": 46, "胡桃": 47, "重云": 48, "菲谢尔": 49, "诺艾尔": 50, "迪奥娜": 51, "鹿野院平藏": 52, "派蒙": 0, "凯亚": 1, "安柏": 2, "丽莎": 3, "琴": 4, "香菱": 5, "枫原万叶": 6, "迪卢克": 7, "温迪": 8, "可莉": 9, "早柚": 10, "托马": 11, "芭芭拉": 12, "优菈": 13, "云堇": 14, "钟离": 15, "魈": 16, "凝光": 17, "雷电将军": 18, "北斗": 19, "甘雨": 20, "七七": 21, "刻晴": 22, "神里绫华": 23, "戴因斯雷布": 24, "雷泽": 25, "神里绫人": 26, "罗莎莉亚": 27, "阿贝多": 28, "八重神子": 29, "宵宫": 30, "荒泷一斗": 31, "九条裟罗": 32, "夜兰": 33, "珊瑚宫心海": 34, "五郎": 35, "散兵": 36, "女士": 37, "达达利亚": 38, "莫娜": 39, "班尼特": 40, "申鹤": 41, "行秋": 42, "烟绯": 43, "久岐忍": 44, "辛焱": 45, "砂糖": 46, "胡桃": 47, "重云": 48, "菲谢尔": 49, "诺艾尔": 50, "迪奥娜": 51, "鹿野院平藏": 52,
} }
var = newapikeystore("./data/tts/o.txt")
func init() { func init() {
en := control.Register("moegoe", &ctrl.Options[*zero.Ctx]{ en := control.Register("moegoe", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false, DisableOnDefault: false,
@ -47,21 +49,11 @@ func init() {
}) })
en.OnRegex("^让(派蒙|凯亚|安柏|丽莎|琴|香菱|枫原万叶|迪卢克|温迪|可莉|早柚|托马|芭芭拉|优菈|云堇|钟离|魈|凝光|雷电将军|北斗|甘雨|七七|刻晴|神里绫华|雷泽|神里绫人|罗莎莉亚|阿贝多|八重神子|宵宫|荒泷一斗|九条裟罗|夜兰|珊瑚宫心海|五郎|达达利亚|莫娜|班尼特|申鹤|行秋|烟绯|久岐忍|辛焱|砂糖|胡桃|重云|菲谢尔|诺艾尔|迪奥娜|鹿野院平藏)说([\\s\u4e00-\u9fa5\\pP]+)$").Limit(ctxext.LimitByGroup).SetBlock(true). en.OnRegex("^让(派蒙|凯亚|安柏|丽莎|琴|香菱|枫原万叶|迪卢克|温迪|可莉|早柚|托马|芭芭拉|优菈|云堇|钟离|魈|凝光|雷电将军|北斗|甘雨|七七|刻晴|神里绫华|雷泽|神里绫人|罗莎莉亚|阿贝多|八重神子|宵宫|荒泷一斗|九条裟罗|夜兰|珊瑚宫心海|五郎|达达利亚|莫娜|班尼特|申鹤|行秋|烟绯|久岐忍|辛焱|砂糖|胡桃|重云|菲谢尔|诺艾尔|迪奥娜|鹿野院平藏)说([\\s\u4e00-\u9fa5\\pP]+)$").Limit(ctxext.LimitByGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) { Handle(func(ctx *zero.Ctx) {
if .k == "" {
return
}
text := ctx.State["regex_matched"].([]string)[2] text := ctx.State["regex_matched"].([]string)[2]
id := speakers[ctx.State["regex_matched"].([]string)[1]] id := speakers[ctx.State["regex_matched"].([]string)[1]]
c, ok := control.Lookup("tts") ctx.SendChain(message.Record(fmt.Sprintf(genshin.CNAPI, id, url.QueryEscape(text), url.QueryEscape(.k))))
if !ok {
ctx.SendChain(message.Text("ERROR: plugin tts not found"))
return
}
var key struct {
APIKey string
}
err := c.Manager.GetExtra(-1, &key)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Record(fmt.Sprintf(genshin.CNAPI, id, url.QueryEscape(text), url.QueryEscape(key.APIKey))))
}) })
} }

24
plugin/moegoe/model.go Normal file
View File

@ -0,0 +1,24 @@
package moegoe
import (
"os"
"github.com/FloatTech/floatbox/binary"
"github.com/FloatTech/floatbox/file"
)
type apikeystore struct {
k string
p string
}
func newapikeystore(p string) (s apikeystore) {
s.p = p
if file.IsExist(p) {
data, err := os.ReadFile(p)
if err == nil {
s.k = binary.BytesToString(data)
}
}
return
}

View File

@ -9,6 +9,7 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"sync"
"github.com/antchfx/htmlquery" "github.com/antchfx/htmlquery"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -42,12 +43,14 @@ const (
var ( var (
cachePath string cachePath string
// apikey 由账号和密码拼接而成, 例: zerobot,123456 // apikey 由账号和密码拼接而成, 例: zerobot,123456
apikey string apikey string
apikeymu sync.Mutex
) )
func init() { func init() {
engine := control.Register("novel", &ctrl.Options[*zero.Ctx]{ engine := control.Register("novel", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false, DisableOnDefault: false,
Extra: control.ExtraFromString("novel"),
Brief: "铅笔小说网搜索", Brief: "铅笔小说网搜索",
Help: "- 小说[xxx]\n" + Help: "- 小说[xxx]\n" +
"- 设置小说配置 zerobot 123456\n" + "- 设置小说配置 zerobot 123456\n" +
@ -290,16 +293,19 @@ func download(id string, cookie string) (downloadHTML string, err error) {
} }
func getAPIKey(ctx *zero.Ctx) string { func getAPIKey(ctx *zero.Ctx) string {
apikeymu.Lock()
defer apikeymu.Unlock()
if apikey == "" { if apikey == "" {
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
_ = m.Manager.GetExtra(-1, &apikey) _ = m.GetExtra(&apikey)
logrus.Debugln("[novel] get api key:", apikey) logrus.Debugln("[novel] get api key:", apikey)
} }
return apikey return apikey
} }
func setAPIKey(m *ctrl.Control[*zero.Ctx], key string) error { func setAPIKey(m *ctrl.Control[*zero.Ctx], key string) error {
apikeymu.Lock()
defer apikeymu.Unlock()
apikey = key apikey = key
_ = m.Manager.Response(-1) return m.SetExtra(apikey)
return m.Manager.SetExtra(-1, apikey)
} }

View File

@ -22,6 +22,8 @@ import (
"github.com/FloatTech/ZeroBot-Plugin/kanban/banner" "github.com/FloatTech/ZeroBot-Plugin/kanban/banner"
) )
type scoredrawer func(a *scdata) (image.Image, error)
func drawScore16(a *scdata) (image.Image, error) { func drawScore16(a *scdata) (image.Image, error) {
// 绘图 // 绘图
getAvatar, err := initPic(a.picfile, a.uid) getAvatar, err := initPic(a.picfile, a.uid)

View File

@ -2,7 +2,6 @@
package score package score
import ( import (
"image"
"math" "math"
"math/rand" "math/rand"
"os" "os"
@ -12,7 +11,6 @@ import (
"github.com/FloatTech/AnimeAPI/bilibili" "github.com/FloatTech/AnimeAPI/bilibili"
"github.com/FloatTech/AnimeAPI/wallet" "github.com/FloatTech/AnimeAPI/wallet"
fcext "github.com/FloatTech/floatbox/ctxext"
"github.com/FloatTech/floatbox/file" "github.com/FloatTech/floatbox/file"
"github.com/FloatTech/floatbox/process" "github.com/FloatTech/floatbox/process"
"github.com/FloatTech/floatbox/web" "github.com/FloatTech/floatbox/web"
@ -32,8 +30,7 @@ const (
referer = "https://weibo.com/" referer = "https://weibo.com/"
signinMax = 1 signinMax = 1
// SCOREMAX 分数上限定为1200 // SCOREMAX 分数上限定为1200
SCOREMAX = 1200 SCOREMAX = 1200
defKeyID int64 = -6
) )
var ( var (
@ -41,25 +38,14 @@ var (
engine = control.Register("score", &ctrl.Options[*zero.Ctx]{ engine = control.Register("score", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false, DisableOnDefault: false,
Brief: "签到", Brief: "签到",
Help: "- 签到\n- 获得签到背景[@xxx] | 获得签到背景\n- 设置[默认]签到预设(1~9)\n- 查看等级排名\n注:为跨群排名\n- 查看我的钱包\n- 查看钱包排名\n注:为本群排行,若群人数太多不建议使用该功能!!!", Help: "- 签到\n- 获得签到背景[@xxx] | 获得签到背景\n- 设置签到预设(0~3)\n- 查看等级排名\n注:为跨群排名\n- 查看我的钱包\n- 查看钱包排名\n注:为本群排行,若群人数太多不建议使用该功能!!!",
PrivateDataFolder: "score", PrivateDataFolder: "score",
}) })
initDef = fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool { styles = []scoredrawer{
var defkey string drawScore15,
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) drawScore16,
_ = m.Manager.Response(defKeyID) drawScore17,
_ = m.Manager.GetExtra(defKeyID, &defkey) drawScore17b2,
if defkey == "" {
_ = m.Manager.SetExtra(defKeyID, "1")
return true
}
return true
})
stylemap = map[string]func(a *scdata) (image.Image, error){
"1": drawScore15,
"2": drawScore16,
"3": drawScore17,
"4": drawScore17b2,
} }
) )
@ -84,7 +70,7 @@ func init() {
} }
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*)$`).Limit(ctxext.LimitByUser).SetBlock(true).Handle(func(ctx *zero.Ctx) {
// 选择key // 选择key
key := ctx.State["regex_matched"].([]string)[1] key := ctx.State["regex_matched"].([]string)[1]
gid := ctx.Event.GroupID gid := ctx.Event.GroupID
@ -92,15 +78,18 @@ func init() {
// 个人用户设为负数 // 个人用户设为负数
gid = -ctx.Event.UserID gid = -ctx.Event.UserID
} }
k := uint8(0)
if key == "" { if key == "" {
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) k = uint8(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).GetData(gid))
_ = m.Manager.GetExtra(gid, &key) } else {
if key == "" { kn, err := strconv.Atoi(key)
_ = m.Manager.GetExtra(defKeyID, &key) if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
} }
k = uint8(kn)
} }
drawfunc, ok := stylemap[key] if int(k) >= len(styles) {
if !ok {
ctx.SendChain(message.Text("ERROR: 未找到签到设定: ", key)) ctx.SendChain(message.Text("ERROR: 未找到签到设定: ", key))
return return
} }
@ -165,7 +154,7 @@ func init() {
level: level, level: level,
rank: rank, rank: rank,
} }
drawimage, err := drawfunc(alldata) drawimage, err := styles[k](alldata)
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
@ -280,30 +269,28 @@ 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 key := ctx.State["regex_matched"].([]string)[2]; key == "" { key := ctx.State["regex_matched"].([]string)[1]
ctx.SendChain(message.Text("设置失败, 数据为空")) kn, err := strconv.Atoi(key)
} else { if err != nil {
s := ctx.State["regex_matched"].([]string)[1] ctx.SendChain(message.Text("ERROR: ", err))
_, ok := stylemap[key] return
if !ok {
ctx.SendChain(message.Text("ERROR: 未找到签到设定: ", key)) // 避免签到配置错误
return
}
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
if s != "" {
gid = defKeyID
}
err := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).Manager.SetExtra(gid, key)
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("设置成功, 当前", s, "预设为:", key))
} }
k := uint8(kn)
if int(k) >= len(styles) {
ctx.SendChain(message.Text("ERROR: 未找到签到设定: ", key))
return
}
gid := ctx.Event.GroupID
if gid == 0 {
gid = -ctx.Event.UserID
}
err = ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).SetData(gid, int64(k))
if err != nil {
ctx.SendChain(message.Text("ERROR: ", err))
return
}
ctx.SendChain(message.Text("设置成功"))
}) })
} }

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
"github.com/FloatTech/floatbox/binary" "github.com/FloatTech/floatbox/binary"
@ -16,19 +17,22 @@ import (
// ----------------------- 远程调用 ---------------------- // ----------------------- 远程调用 ----------------------
const ( const (
URL = "https://api.steampowered.com/" // steam API 调用地址 apiurl = "https://api.steampowered.com/" // steam API 调用地址
StatusURL = "ISteamUser/GetPlayerSummaries/v2/?key=%+v&steamids=%+v" // 根据用户steamID获取用户状态 statusurl = "ISteamUser/GetPlayerSummaries/v2/?key=%+v&steamids=%+v" // 根据用户steamID获取用户状态
steamapikeygid = 3
) )
var apiKey string var (
apiKey string
apiKeyMu sync.Mutex
)
func init() { func init() {
engine.OnRegex(`^steam绑定\s*api\s*key\s*(.*)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) { engine.OnRegex(`^steam绑定\s*api\s*key\s*(.*)$`, zero.OnlyPrivate, zero.SuperUserPermission).SetBlock(true).Handle(func(ctx *zero.Ctx) {
apiKeyMu.Lock()
defer apiKeyMu.Unlock()
apiKey = ctx.State["regex_matched"].([]string)[1] apiKey = ctx.State["regex_matched"].([]string)[1]
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
_ = m.Manager.Response(steamapikeygid) err := m.SetExtra(apiKey)
err := m.Manager.SetExtra(steamapikeygid, apiKey)
if err != nil { if err != nil {
ctx.SendChain(message.Text("[steam] ERROR: 保存apikey失败")) ctx.SendChain(message.Text("[steam] ERROR: 保存apikey失败"))
return return
@ -36,6 +40,8 @@ func init() {
ctx.SendChain(message.Text("保存apikey成功")) ctx.SendChain(message.Text("保存apikey成功"))
}) })
engine.OnFullMatch("查看apikey", zero.OnlyPrivate, zero.SuperUserPermission, getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) { engine.OnFullMatch("查看apikey", zero.OnlyPrivate, zero.SuperUserPermission, getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) {
apiKeyMu.Lock()
defer apiKeyMu.Unlock()
ctx.SendChain(message.Text("apikey为: ", apiKey)) ctx.SendChain(message.Text("apikey为: ", apiKey))
}) })
engine.OnFullMatch("拉取steam订阅", getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) { engine.OnFullMatch("拉取steam订阅", getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) {
@ -55,7 +61,7 @@ func init() {
localPlayerMap := make(map[int64]*player) localPlayerMap := make(map[int64]*player)
for i := 0; i < len(infos); i++ { for i := 0; i < len(infos); i++ {
streamIds[i] = strconv.FormatInt(infos[i].SteamID, 10) streamIds[i] = strconv.FormatInt(infos[i].SteamID, 10)
localPlayerMap[infos[i].SteamID] = &infos[i] localPlayerMap[infos[i].SteamID] = infos[i]
} }
// 将所有用户状态查一遍 // 将所有用户状态查一遍
playerStatus, err := getPlayerStatus(streamIds...) playerStatus, err := getPlayerStatus(streamIds...)
@ -114,7 +120,9 @@ func init() {
func getPlayerStatus(streamIds ...string) ([]*player, error) { func getPlayerStatus(streamIds ...string) ([]*player, error) {
players := make([]*player, 0) players := make([]*player, 0)
// 拼接请求地址 // 拼接请求地址
url := fmt.Sprintf(URL+StatusURL, apiKey, strings.Join(streamIds, ",")) apiKeyMu.Lock()
url := fmt.Sprintf(apiurl+statusurl, apiKey, strings.Join(streamIds, ","))
apiKeyMu.Unlock()
// 拉取并解析数据 // 拉取并解析数据
data, err := web.GetData(url) data, err := web.GetData(url)
if err != nil { if err != nil {

View File

@ -19,6 +19,7 @@ import (
var ( var (
engine = control.Register("steam", &ctrl.Options[*zero.Ctx]{ engine = control.Register("steam", &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false, DisableOnDefault: false,
Extra: control.ExtraFromString("steam"),
Brief: "steam相关插件", Brief: "steam相关插件",
Help: "- steam添加订阅 xxxxxxx (可输入需要绑定的 steamid)\n" + Help: "- steam添加订阅 xxxxxxx (可输入需要绑定的 steamid)\n" +
"- steam删除订阅 xxxxxxx (删除你创建的对于 steamid 的绑定)\n" + "- steam删除订阅 xxxxxxx (删除你创建的对于 steamid 的绑定)\n" +

View File

@ -22,14 +22,15 @@ var (
ctx.SendChain(message.Text("[steam] ERROR: ", err)) ctx.SendChain(message.Text("[steam] ERROR: ", err))
return false return false
} }
if err = database.db.Create(TableListenPlayer, &player{}); err != nil { if err = database.db.Create(tableListenPlayer, &player{}); err != nil {
ctx.SendChain(message.Text("[steam] ERROR: ", err)) ctx.SendChain(message.Text("[steam] ERROR: ", err))
return false return false
} }
// 校验密钥是否初始化 // 校验密钥是否初始化
m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx])
_ = m.Manager.Response(steamapikeygid) apiKeyMu.Lock()
_ = m.Manager.GetExtra(steamapikeygid, &apiKey) defer apiKeyMu.Unlock()
_ = m.GetExtra(&apiKey)
if apiKey == "" { if apiKey == "" {
ctx.SendChain(message.Text("ERROR: 未设置steam apikey")) ctx.SendChain(message.Text("ERROR: 未设置steam apikey"))
return false return false
@ -45,8 +46,8 @@ type streamDB struct {
} }
const ( const (
// TableListenPlayer 存储查询用户信息 // tableListenPlayer 存储查询用户信息
TableListenPlayer = "listen_player" tableListenPlayer = "listen_player"
) )
// player 用户状态存储结构体 // player 用户状态存储结构体
@ -60,58 +61,46 @@ type player struct {
} }
// update 如果主键不存在则插入一条新的数据,如果主键存在直接复写 // update 如果主键不存在则插入一条新的数据,如果主键存在直接复写
func (sql *streamDB) update(dbInfo *player) error { func (sdb *streamDB) update(dbInfo *player) error {
sql.Lock() sdb.Lock()
defer sql.Unlock() defer sdb.Unlock()
return sql.db.Insert(TableListenPlayer, dbInfo) return sdb.db.Insert(tableListenPlayer, dbInfo)
} }
// find 根据主键查信息 // find 根据主键查信息
func (sql *streamDB) find(steamID int64) (dbInfo player, err error) { func (sdb *streamDB) find(steamID int64) (dbInfo player, err error) {
sql.Lock() sdb.Lock()
defer sql.Unlock() defer sdb.Unlock()
condition := "where steam_id = " + strconv.FormatInt(steamID, 10) condition := "where steam_id = " + strconv.FormatInt(steamID, 10)
if !sql.db.CanFind(TableListenPlayer, condition) { err = sdb.db.Find(tableListenPlayer, &dbInfo, condition)
return player{}, nil // 规避没有该用户数据的报错 if err == sql.ErrNullResult { // 规避没有该用户数据的报错
err = nil
} }
err = sql.db.Find(TableListenPlayer, &dbInfo, condition)
return return
} }
// findWithGroupID 根据用户steamID和groupID查询信息 // findWithGroupID 根据用户steamID和groupID查询信息
func (sql *streamDB) findWithGroupID(steamID int64, groupID string) (dbInfo player, err error) { func (sdb *streamDB) findWithGroupID(steamID int64, groupID string) (dbInfo player, err error) {
sql.Lock() sdb.Lock()
defer sql.Unlock() defer sdb.Unlock()
condition := "where steam_id = " + strconv.FormatInt(steamID, 10) + " AND target LIKE '%" + groupID + "%'" condition := "where steam_id = " + strconv.FormatInt(steamID, 10) + " AND target LIKE '%" + groupID + "%'"
if !sql.db.CanFind(TableListenPlayer, condition) { err = sdb.db.Find(tableListenPlayer, &dbInfo, condition)
return player{}, nil // 规避没有该用户数据的报错 if err == sql.ErrNullResult { // 规避没有该用户数据的报错
err = nil
} }
err = sql.db.Find(TableListenPlayer, &dbInfo, condition)
return return
} }
// findAll 查询所有库信息 // findAll 查询所有库信息
func (sql *streamDB) findAll() (dbInfos []player, err error) { func (sdb *streamDB) findAll() (dbInfos []*player, err error) {
sql.Lock() sdb.Lock()
defer sql.Unlock() defer sdb.Unlock()
var info player return sql.FindAll[player](&sdb.db, tableListenPlayer, "")
num, err := sql.db.Count(TableListenPlayer)
if err != nil || num == 0 {
return
}
dbInfos = make([]player, 0, num)
err = sql.db.FindFor(TableListenPlayer, &info, "", func() error {
if info.SteamID != 0 {
dbInfos = append(dbInfos, info)
}
return nil
})
return
} }
// del 删除指定数据 // del 删除指定数据
func (sql *streamDB) del(steamID int64) error { func (sdb *streamDB) del(steamID int64) error {
sql.Lock() sdb.Lock()
defer sql.Unlock() defer sdb.Unlock()
return sql.db.Del(TableListenPlayer, "where steam_id = "+strconv.FormatInt(steamID, 10)) return sdb.db.Del(tableListenPlayer, "where steam_id = "+strconv.FormatInt(steamID, 10))
} }