diff --git a/README.md b/README.md index 619054fa..c85f4c8e 100644 --- a/README.md +++ b/README.md @@ -1250,7 +1250,7 @@ print("run[CQ:image,file="+j["img"]+"]") - [x] 签到 - [x] 获得签到背景[@xxx] | 获得签到背景 - - [x] 设置[默认]签到预设(1~9) + - [x] 设置签到预设(0~3) - [x] 查看等级排名 - 注:跨群排行 - [x] 查看我的钱包 diff --git a/go.mod b/go.mod index c131aa02..38f1fae2 100644 --- a/go.mod +++ b/go.mod @@ -11,8 +11,8 @@ require ( github.com/FloatTech/rendercard v0.0.10-0.20230223064326-45d29fa4ede9 github.com/FloatTech/sqlite v1.6.2 github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b - github.com/FloatTech/zbpctrl v1.5.3-0.20230406055807-cb5f5edad2c7 - github.com/FloatTech/zbputils v1.6.2-0.20230407083549-931d7968df13 + github.com/FloatTech/zbpctrl v1.5.3-0.20230408032827-50ef967f2849 + github.com/FloatTech/zbputils v1.6.2-0.20230408085317-f2f525cff6fc github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5 github.com/antchfx/htmlquery v1.2.5 diff --git a/go.sum b/go.sum index 87fba9b6..1adbf923 100644 --- a/go.sum +++ b/go.sum @@ -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/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw= 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.20230406055807-cb5f5edad2c7/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.20230407083549-931d7968df13/go.mod h1:iPlPghAE6SSDBZPHA6ZiPyspfeVDNQqtfLDkftHlD4I= +github.com/FloatTech/zbpctrl v1.5.3-0.20230408032827-50ef967f2849 h1:ARKWV3tXJLENWY6vcwTStEDwJckYnxoHXgZMsuJ3gUw= +github.com/FloatTech/zbpctrl v1.5.3-0.20230408032827-50ef967f2849/go.mod h1:IagyEhY38VcbbQgVRzAM9f9mhaUn90rM5BTPfudtl1g= +github.com/FloatTech/zbputils v1.6.2-0.20230408085317-f2f525cff6fc h1:myLvTVYvTaBgKoXJW1rHPFfr0W4wWPlJQ5DlKBhfHuw= +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/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA= github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w= diff --git a/plugin/ai_reply/ai_tts.go b/plugin/ai_reply/ai_tts.go index f84eb7fe..e6a27e41 100644 --- a/plugin/ai_reply/ai_tts.go +++ b/plugin/ai_reply/ai_tts.go @@ -2,10 +2,8 @@ package aireply import ( "errors" - "net/url" "github.com/RomiChan/syncx" - "github.com/sirupsen/logrus" zero "github.com/wdvxdr1123/ZeroBot" "github.com/FloatTech/AnimeAPI/aireply" @@ -54,25 +52,23 @@ var ttscnspeakers = [...]string{ "晓甄(女 - 年轻人)", } -const ( - defaultttsindexkey = -2905 - gsapikeyextragrp = -1 - chatgptapikeyextragrp = -2 +const defaultttsindexkey = -2905 + +var ( + 原 = newapikeystore("./data/tts/o.txt") + ཆཏ = newapikeystore("./data/tts/c.txt") ) -type replymode struct { - APIKey string // APIKey is for chatgpt - replyModes []string `json:"-"` -} +type replymode []string -func (r *replymode) setReplyMode(ctx *zero.Ctx, name string) error { +func (r replymode) setReplyMode(ctx *zero.Ctx, name string) error { gid := ctx.Event.GroupID if gid == 0 { gid = -ctx.Event.UserID } var ok bool var index int64 - for i, s := range r.replyModes { + for i, s := range r { if s == name { ok = true 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)) } -func (r *replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply { +func (r replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply { gid := ctx.Event.GroupID if gid == 0 { gid = -ctx.Event.UserID @@ -102,7 +98,7 @@ func (r *replymode) getReplyMode(ctx *zero.Ctx) aireply.AIReply { case 1: return aireply.NewXiaoAi(aireply.XiaoAiURL, aireply.XiaoAiBotName) case 2: - k := r.getAPIKey(ctx) + k := ཆཏ.k if 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) } -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 { m := make(map[string]tts.TTS, 128) for _, mode := range append(genshin.SoundList[:], extrattsname...) { @@ -141,10 +122,7 @@ var ttsModes = func() []string { return s }() -type ttsmode struct { - APIKey string // APIKey is for genshin vits - mode syncx.Map[int64, int64] `json:"-"` // mode grp index -} +type ttsmode syncx.Map[int64, int64] func list(list []string, num int) string { s := "" @@ -162,33 +140,17 @@ func list(list []string, num int) string { func newttsmode() *ttsmode { t := &ttsmode{} m, ok := control.Lookup("tts") - t.mode = syncx.Map[int64, int64]{} - t.mode.Store(defaultttsindexkey, 0) + (*syncx.Map[int64, int64])(t).Store(defaultttsindexkey, 0) if ok { index := m.GetData(defaultttsindexkey) msk := index & 0xff 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 } -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 { gid := ctx.Event.GroupID 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]) - 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)) } @@ -225,14 +187,14 @@ func (t *ttsmode) getSoundMode(ctx *zero.Ctx) (tts.TTS, error) { if gid == 0 { gid = -ctx.Event.UserID } - i, ok := t.mode.Load(gid) + i, ok := (*syncx.Map[int64, int64])(t).Load(gid) if !ok { m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) i = m.GetData(gid) >> 8 } m := i & 0xff 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 } mode := ttsModes[m] @@ -248,9 +210,9 @@ func (t *ttsmode) getSoundMode(ctx *zero.Ctx) (tts.TTS, error) { return nil, err } default: // 原神 - k := t.getAPIKey(ctx) + k := 原.k if k != "" { - ins = genshin.NewGenshin(int(m), t.getAPIKey(ctx)) + ins = genshin.NewGenshin(int(m), 原.k) ttsins[mode] = ins } else { return nil, errors.New("no valid speaker") @@ -296,6 +258,6 @@ func (t *ttsmode) setDefaultSoundMode(name string, baiduper, mockingsynt int) er if !ok { 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)) } diff --git a/plugin/ai_reply/main.go b/plugin/ai_reply/main.go index 58e583e4..fa4fb988 100644 --- a/plugin/ai_reply/main.go +++ b/plugin/ai_reply/main.go @@ -15,9 +15,7 @@ import ( "github.com/wdvxdr1123/ZeroBot/message" ) -var replmd = replymode{ - replyModes: []string{"青云客", "小爱", "ChatGPT"}, -} +var replmd = replymode([]string{"青云客", "小爱", "ChatGPT"}) var ttsmd = newttsmode() @@ -32,6 +30,7 @@ func init() { // 插件主体 "- 设置原神语音 api key xxxxxx (key请加开发群获得)\n" + "当前适用的原神人物含有以下: \n" + list(genshin.SoundList[:], 5) + "\n当前适用的TTSCN人物含有以下(以数字顺序代表): \n" + list(ttscnspeakers[:], 5), + PrivateDataFolder: "tts", }) 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) { - 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 { ctx.SendChain(message.Text("ERROR: ", err)) 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) { - 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 { ctx.SendChain(message.Text("ERROR: ", err)) return diff --git a/plugin/ai_reply/model.go b/plugin/ai_reply/model.go new file mode 100644 index 00000000..1e79d5e3 --- /dev/null +++ b/plugin/ai_reply/model.go @@ -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) +} diff --git a/plugin/moegoe/main.go b/plugin/moegoe/main.go index 1233e800..6a4f3e8b 100644 --- a/plugin/moegoe/main.go +++ b/plugin/moegoe/main.go @@ -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, } +var 原 = newapikeystore("./data/tts/o.txt") + func init() { en := control.Register("moegoe", &ctrl.Options[*zero.Ctx]{ DisableOnDefault: false, @@ -47,21 +49,11 @@ func init() { }) en.OnRegex("^让(派蒙|凯亚|安柏|丽莎|琴|香菱|枫原万叶|迪卢克|温迪|可莉|早柚|托马|芭芭拉|优菈|云堇|钟离|魈|凝光|雷电将军|北斗|甘雨|七七|刻晴|神里绫华|雷泽|神里绫人|罗莎莉亚|阿贝多|八重神子|宵宫|荒泷一斗|九条裟罗|夜兰|珊瑚宫心海|五郎|达达利亚|莫娜|班尼特|申鹤|行秋|烟绯|久岐忍|辛焱|砂糖|胡桃|重云|菲谢尔|诺艾尔|迪奥娜|鹿野院平藏)说([\\s\u4e00-\u9fa5\\pP]+)$").Limit(ctxext.LimitByGroup).SetBlock(true). Handle(func(ctx *zero.Ctx) { + if 原.k == "" { + return + } text := ctx.State["regex_matched"].([]string)[2] id := speakers[ctx.State["regex_matched"].([]string)[1]] - c, ok := control.Lookup("tts") - 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)))) + ctx.SendChain(message.Record(fmt.Sprintf(genshin.CNAPI, id, url.QueryEscape(text), url.QueryEscape(原.k)))) }) } diff --git a/plugin/moegoe/model.go b/plugin/moegoe/model.go new file mode 100644 index 00000000..cd09b72a --- /dev/null +++ b/plugin/moegoe/model.go @@ -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 +} diff --git a/plugin/novel/qianbi.go b/plugin/novel/qianbi.go index 529fe05a..964b9c8a 100644 --- a/plugin/novel/qianbi.go +++ b/plugin/novel/qianbi.go @@ -9,6 +9,7 @@ import ( "path/filepath" "regexp" "strings" + "sync" "github.com/antchfx/htmlquery" "github.com/sirupsen/logrus" @@ -42,12 +43,14 @@ const ( var ( cachePath string // apikey 由账号和密码拼接而成, 例: zerobot,123456 - apikey string + apikey string + apikeymu sync.Mutex ) func init() { engine := control.Register("novel", &ctrl.Options[*zero.Ctx]{ DisableOnDefault: false, + Extra: control.ExtraFromString("novel"), Brief: "铅笔小说网搜索", Help: "- 小说[xxx]\n" + "- 设置小说配置 zerobot 123456\n" + @@ -290,16 +293,19 @@ func download(id string, cookie string) (downloadHTML string, err error) { } func getAPIKey(ctx *zero.Ctx) string { + apikeymu.Lock() + defer apikeymu.Unlock() if apikey == "" { m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) - _ = m.Manager.GetExtra(-1, &apikey) + _ = m.GetExtra(&apikey) logrus.Debugln("[novel] get api key:", apikey) } return apikey } func setAPIKey(m *ctrl.Control[*zero.Ctx], key string) error { + apikeymu.Lock() + defer apikeymu.Unlock() apikey = key - _ = m.Manager.Response(-1) - return m.Manager.SetExtra(-1, apikey) + return m.SetExtra(apikey) } diff --git a/plugin/score/draw.go b/plugin/score/draw.go index 4709e549..33cc58b4 100644 --- a/plugin/score/draw.go +++ b/plugin/score/draw.go @@ -22,6 +22,8 @@ import ( "github.com/FloatTech/ZeroBot-Plugin/kanban/banner" ) +type scoredrawer func(a *scdata) (image.Image, error) + func drawScore16(a *scdata) (image.Image, error) { // 绘图 getAvatar, err := initPic(a.picfile, a.uid) diff --git a/plugin/score/sign_in.go b/plugin/score/sign_in.go index 8ce971a8..17185d44 100644 --- a/plugin/score/sign_in.go +++ b/plugin/score/sign_in.go @@ -2,7 +2,6 @@ package score import ( - "image" "math" "math/rand" "os" @@ -12,7 +11,6 @@ import ( "github.com/FloatTech/AnimeAPI/bilibili" "github.com/FloatTech/AnimeAPI/wallet" - fcext "github.com/FloatTech/floatbox/ctxext" "github.com/FloatTech/floatbox/file" "github.com/FloatTech/floatbox/process" "github.com/FloatTech/floatbox/web" @@ -32,8 +30,7 @@ const ( referer = "https://weibo.com/" signinMax = 1 // SCOREMAX 分数上限定为1200 - SCOREMAX = 1200 - defKeyID int64 = -6 + SCOREMAX = 1200 ) var ( @@ -41,25 +38,14 @@ var ( engine = control.Register("score", &ctrl.Options[*zero.Ctx]{ DisableOnDefault: false, 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", }) - initDef = fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool { - var defkey string - m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) - _ = m.Manager.Response(defKeyID) - _ = m.Manager.GetExtra(defKeyID, &defkey) - 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, + styles = []scoredrawer{ + drawScore15, + drawScore16, + drawScore17, + drawScore17b2, } ) @@ -84,7 +70,7 @@ func init() { } 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 := ctx.State["regex_matched"].([]string)[1] gid := ctx.Event.GroupID @@ -92,15 +78,18 @@ func init() { // 个人用户设为负数 gid = -ctx.Event.UserID } + k := uint8(0) if key == "" { - m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) - _ = m.Manager.GetExtra(gid, &key) - if key == "" { - _ = m.Manager.GetExtra(defKeyID, &key) + k = uint8(ctx.State["manager"].(*ctrl.Control[*zero.Ctx]).GetData(gid)) + } else { + kn, err := strconv.Atoi(key) + if err != nil { + ctx.SendChain(message.Text("ERROR: ", err)) + return } + k = uint8(kn) } - drawfunc, ok := stylemap[key] - if !ok { + if int(k) >= len(styles) { ctx.SendChain(message.Text("ERROR: 未找到签到设定: ", key)) return } @@ -165,7 +154,7 @@ func init() { level: level, rank: rank, } - drawimage, err := drawfunc(alldata) + drawimage, err := styles[k](alldata) if err != nil { ctx.SendChain(message.Text("ERROR: ", err)) return @@ -280,30 +269,28 @@ func init() { } ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile)) }) - 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 == "" { - ctx.SendChain(message.Text("设置失败, 数据为空")) - } else { - s := ctx.State["regex_matched"].([]string)[1] - _, ok := stylemap[key] - 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)) + engine.OnRegex(`^设置签到预设\s*(\d+)$`, zero.SuperUserPermission).Limit(ctxext.LimitByUser).SetBlock(true).Handle(func(ctx *zero.Ctx) { + key := ctx.State["regex_matched"].([]string)[1] + kn, err := strconv.Atoi(key) + if err != nil { + ctx.SendChain(message.Text("ERROR: ", err)) + return } + 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("设置成功")) }) } diff --git a/plugin/steam/listenter.go b/plugin/steam/listenter.go index 97682655..25032f98 100644 --- a/plugin/steam/listenter.go +++ b/plugin/steam/listenter.go @@ -4,6 +4,7 @@ import ( "fmt" "strconv" "strings" + "sync" "time" "github.com/FloatTech/floatbox/binary" @@ -16,19 +17,22 @@ import ( // ----------------------- 远程调用 ---------------------- const ( - URL = "https://api.steampowered.com/" // steam API 调用地址 - StatusURL = "ISteamUser/GetPlayerSummaries/v2/?key=%+v&steamids=%+v" // 根据用户steamID获取用户状态 - steamapikeygid = 3 + apiurl = "https://api.steampowered.com/" // steam API 调用地址 + statusurl = "ISteamUser/GetPlayerSummaries/v2/?key=%+v&steamids=%+v" // 根据用户steamID获取用户状态 ) -var apiKey string +var ( + apiKey string + apiKeyMu sync.Mutex +) func init() { 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] m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) - _ = m.Manager.Response(steamapikeygid) - err := m.Manager.SetExtra(steamapikeygid, apiKey) + err := m.SetExtra(apiKey) if err != nil { ctx.SendChain(message.Text("[steam] ERROR: 保存apikey失败!")) return @@ -36,6 +40,8 @@ func init() { ctx.SendChain(message.Text("保存apikey成功!")) }) 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)) }) engine.OnFullMatch("拉取steam订阅", getDB).SetBlock(true).Handle(func(ctx *zero.Ctx) { @@ -55,7 +61,7 @@ func init() { localPlayerMap := make(map[int64]*player) for i := 0; i < len(infos); i++ { streamIds[i] = strconv.FormatInt(infos[i].SteamID, 10) - localPlayerMap[infos[i].SteamID] = &infos[i] + localPlayerMap[infos[i].SteamID] = infos[i] } // 将所有用户状态查一遍 playerStatus, err := getPlayerStatus(streamIds...) @@ -114,7 +120,9 @@ func init() { func getPlayerStatus(streamIds ...string) ([]*player, error) { 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) if err != nil { diff --git a/plugin/steam/steam.go b/plugin/steam/steam.go index db51b2b5..fe913fa7 100644 --- a/plugin/steam/steam.go +++ b/plugin/steam/steam.go @@ -19,6 +19,7 @@ import ( var ( engine = control.Register("steam", &ctrl.Options[*zero.Ctx]{ DisableOnDefault: false, + Extra: control.ExtraFromString("steam"), Brief: "steam相关插件", Help: "- steam添加订阅 xxxxxxx (可输入需要绑定的 steamid)\n" + "- steam删除订阅 xxxxxxx (删除你创建的对于 steamid 的绑定)\n" + diff --git a/plugin/steam/store.go b/plugin/steam/store.go index 171a60f7..e68aa719 100644 --- a/plugin/steam/store.go +++ b/plugin/steam/store.go @@ -22,14 +22,15 @@ var ( ctx.SendChain(message.Text("[steam] ERROR: ", err)) 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)) return false } // 校验密钥是否初始化 m := ctx.State["manager"].(*ctrl.Control[*zero.Ctx]) - _ = m.Manager.Response(steamapikeygid) - _ = m.Manager.GetExtra(steamapikeygid, &apiKey) + apiKeyMu.Lock() + defer apiKeyMu.Unlock() + _ = m.GetExtra(&apiKey) if apiKey == "" { ctx.SendChain(message.Text("ERROR: 未设置steam apikey")) return false @@ -45,8 +46,8 @@ type streamDB struct { } const ( - // TableListenPlayer 存储查询用户信息 - TableListenPlayer = "listen_player" + // tableListenPlayer 存储查询用户信息 + tableListenPlayer = "listen_player" ) // player 用户状态存储结构体 @@ -60,58 +61,46 @@ type player struct { } // update 如果主键不存在则插入一条新的数据,如果主键存在直接复写 -func (sql *streamDB) update(dbInfo *player) error { - sql.Lock() - defer sql.Unlock() - return sql.db.Insert(TableListenPlayer, dbInfo) +func (sdb *streamDB) update(dbInfo *player) error { + sdb.Lock() + defer sdb.Unlock() + return sdb.db.Insert(tableListenPlayer, dbInfo) } // find 根据主键查信息 -func (sql *streamDB) find(steamID int64) (dbInfo player, err error) { - sql.Lock() - defer sql.Unlock() +func (sdb *streamDB) find(steamID int64) (dbInfo player, err error) { + sdb.Lock() + defer sdb.Unlock() condition := "where steam_id = " + strconv.FormatInt(steamID, 10) - if !sql.db.CanFind(TableListenPlayer, condition) { - return player{}, nil // 规避没有该用户数据的报错 + err = sdb.db.Find(tableListenPlayer, &dbInfo, condition) + if err == sql.ErrNullResult { // 规避没有该用户数据的报错 + err = nil } - err = sql.db.Find(TableListenPlayer, &dbInfo, condition) return } // findWithGroupID 根据用户steamID和groupID查询信息 -func (sql *streamDB) findWithGroupID(steamID int64, groupID string) (dbInfo player, err error) { - sql.Lock() - defer sql.Unlock() +func (sdb *streamDB) findWithGroupID(steamID int64, groupID string) (dbInfo player, err error) { + sdb.Lock() + defer sdb.Unlock() condition := "where steam_id = " + strconv.FormatInt(steamID, 10) + " AND target LIKE '%" + groupID + "%'" - if !sql.db.CanFind(TableListenPlayer, condition) { - return player{}, nil // 规避没有该用户数据的报错 + err = sdb.db.Find(tableListenPlayer, &dbInfo, condition) + if err == sql.ErrNullResult { // 规避没有该用户数据的报错 + err = nil } - err = sql.db.Find(TableListenPlayer, &dbInfo, condition) return } // findAll 查询所有库信息 -func (sql *streamDB) findAll() (dbInfos []player, err error) { - sql.Lock() - defer sql.Unlock() - var info player - 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 +func (sdb *streamDB) findAll() (dbInfos []*player, err error) { + sdb.Lock() + defer sdb.Unlock() + return sql.FindAll[player](&sdb.db, tableListenPlayer, "") } // del 删除指定数据 -func (sql *streamDB) del(steamID int64) error { - sql.Lock() - defer sql.Unlock() - return sql.db.Del(TableListenPlayer, "where steam_id = "+strconv.FormatInt(steamID, 10)) +func (sdb *streamDB) del(steamID int64) error { + sdb.Lock() + defer sdb.Unlock() + return sdb.db.Del(tableListenPlayer, "where steam_id = "+strconv.FormatInt(steamID, 10)) }