diff --git a/data b/data index 9fc3ca23..5155c731 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 9fc3ca233bbe945ea3060622d7e2cb98ee606225 +Subproject commit 5155c7318a98648ad94adb720af4fd60cbc1aed7 diff --git a/go.mod b/go.mod index ac0e5d03..142f8c35 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,15 @@ module github.com/FloatTech/ZeroBot-Plugin go 1.18 require ( - github.com/FloatTech/AnimeAPI v1.3.2-0.20220326161751-d0d2797b91da + github.com/FloatTech/AnimeAPI v1.3.2-0.20220328090901-d01ce41ecaca github.com/FloatTech/sqlite v0.2.1 - github.com/FloatTech/zbputils v1.3.2-0.20220327063325-1389d5a92fff + github.com/FloatTech/zbputils v1.3.2-0.20220328090754-b949b4e868e5 github.com/antchfx/htmlquery v1.2.4 github.com/corona10/goimagehash v1.0.3 github.com/fogleman/gg v1.3.0 github.com/fumiama/cron v1.3.0 github.com/fumiama/go-base16384 v1.4.0 - github.com/fumiama/go-registry v0.1.1 + github.com/fumiama/go-registry v0.1.2 github.com/fumiama/gofastTEA v0.0.10 github.com/fumiama/gotracemoe v0.0.3 github.com/fumiama/sqlite3 v1.14.6 @@ -47,7 +47,7 @@ require ( github.com/tklauser/numcpus v0.4.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect - golang.org/x/sys v0.0.0-20220325203850-36772127a21f // indirect + golang.org/x/sys v0.0.0-20220327210214-530d0810a4d0 // indirect golang.org/x/text v0.3.7 // indirect modernc.org/libc v1.14.12 // indirect modernc.org/mathutil v1.4.1 // indirect diff --git a/go.sum b/go.sum index 015dfdaf..de56e4c1 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ -github.com/FloatTech/AnimeAPI v1.3.2-0.20220326161751-d0d2797b91da h1:KbJujP8k2/3BYRb+F292zLmDOV79uTOu/24n3fhIwRU= -github.com/FloatTech/AnimeAPI v1.3.2-0.20220326161751-d0d2797b91da/go.mod h1:aC3EOKpb0R0VOdW9QIQCfqN6ZFymOfvCgzVY1/Fz3Og= +github.com/FloatTech/AnimeAPI v1.3.2-0.20220328090901-d01ce41ecaca h1:mHrQLnuanvGeqc2EkKrNuBDSUMp8uhlPXBhLuinyMlI= +github.com/FloatTech/AnimeAPI v1.3.2-0.20220328090901-d01ce41ecaca/go.mod h1:EPRv+7KfmYwTq8xeLXpZLqzyjw7692fWE+2InqAn8t0= github.com/FloatTech/sqlite v0.2.1 h1:9t6Me48XJJCIoPy4nLRvcdhcVKfT0c2lilp7SEKROG8= github.com/FloatTech/sqlite v0.2.1/go.mod h1:6NfHRzqOo9RWeMJEoAQVuo51Omd5LFNxCNQhMF02/9U= -github.com/FloatTech/zbputils v1.3.2-0.20220327063325-1389d5a92fff h1:h72B2RgFc4ObczhlS38+seue7/6CLhQBcOAwMe3TBmw= -github.com/FloatTech/zbputils v1.3.2-0.20220327063325-1389d5a92fff/go.mod h1:qZlHzG1s1giQrXaosjOAA2utGNaPZjwJsVZfBog2bhg= +github.com/FloatTech/zbputils v1.3.2-0.20220328090754-b949b4e868e5 h1:qHuSftyvTepeXLdFIBKuAy7Ni9jlNBxXxp03efkqUJY= +github.com/FloatTech/zbputils v1.3.2-0.20220328090754-b949b4e868e5/go.mod h1:AcOSnCQjZe0jFzAre1YBwUXi/WQIKZXTD4pcsMro+p4= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc h1:AAx50/fb/xS4lvsdQg+bFbGvqSDhyV1MF+p2PLCamZ0= github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc/go.mod h1:OMmITAib6POA37xCichWM0aRnoVpSMZO1rB/G01wrr0= @@ -33,8 +33,8 @@ github.com/fumiama/cron v1.3.0 h1:ZWlwuexF+HQHl3cYytEE5HNwD99q+3vNZF1GrEiXCFo= github.com/fumiama/cron v1.3.0/go.mod h1:bz5Izvgi/xEUI8tlBN8BI2jr9Moo8N4or0KV8xXuPDY= github.com/fumiama/go-base16384 v1.4.0 h1:4KrtewnmAChrZjPA7/QYc72t+vvsKF+DYB0q1iRPdpo= github.com/fumiama/go-base16384 v1.4.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM= -github.com/fumiama/go-registry v0.1.1 h1:cmCRizjXHFW2ApwUHCXi8wKLJ6Gtt4GrShJlamGPbVI= -github.com/fumiama/go-registry v0.1.1/go.mod h1:iJT3DVgH7KXpJZs6waXEjnWtJPUBBGhF+ByJIMRfngk= +github.com/fumiama/go-registry v0.1.2 h1:mlH9QtbgzfV+uvm5YM8YZau/2yrekVziPuyn3UTzrYw= +github.com/fumiama/go-registry v0.1.2/go.mod h1:iJT3DVgH7KXpJZs6waXEjnWtJPUBBGhF+ByJIMRfngk= github.com/fumiama/gofastTEA v0.0.10 h1:JJJ+brWD4kie+mmK2TkspDXKzqq0IjXm89aGYfoGhhQ= github.com/fumiama/gofastTEA v0.0.10/go.mod h1:RIdbYZyB4MbH6ZBlPymRaXn3cD6SedlCu5W/HHfMPBk= github.com/fumiama/gotracemoe v0.0.3 h1:iI5EbE9A3UUbfukG6+/soYPjp1S31eCNYf4tw7s6/Jc= @@ -168,8 +168,8 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220325203850-36772127a21f h1:TrmogKRsSOxRMJbLYGrB4SBbW+LJcEllYBLME5Zk5pU= -golang.org/x/sys v0.0.0-20220325203850-36772127a21f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220327210214-530d0810a4d0 h1:G6WAvvcMaaFYQhMbC0L5ZWNExEcJ3j3yFTxx4mwOHtM= +golang.org/x/sys v0.0.0-20220327210214-530d0810a4d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/main.go b/main.go index d4b8c891..b0ae6df8 100644 --- a/main.go +++ b/main.go @@ -80,6 +80,7 @@ import ( _ "github.com/FloatTech/ZeroBot-Plugin/plugin/gif" // 制图 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/github" // 搜索GitHub仓库 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/hs" // 炉石 + _ "github.com/FloatTech/ZeroBot-Plugin/plugin/hyaku" // 百人一首 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/image_finder" // 关键字搜图 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/inject" // 注入指令 _ "github.com/FloatTech/ZeroBot-Plugin/plugin/jandan" // 煎蛋网无聊图 diff --git a/plugin/ai_reply/ai_tts.go b/plugin/ai_reply/ai_tts.go index e9cbab18..ddd11455 100644 --- a/plugin/ai_reply/ai_tts.go +++ b/plugin/ai_reply/ai_tts.go @@ -23,20 +23,7 @@ import ( const ttsServiceName = "tts" -var ( - t = &ttsInstances{ - m: map[string]tts.TTS{ - "百度女声": baidutts.NewBaiduTTS(0), - "百度男声": baidutts.NewBaiduTTS(1), - "百度度逍遥": baidutts.NewBaiduTTS(3), - "百度度丫丫": baidutts.NewBaiduTTS(4), - "拟声鸟阿梓": mockingbird.NewMockingBirdTTS(0), - "拟声鸟药水哥": mockingbird.NewMockingBirdTTS(1), - }, - l: []string{"拟声鸟阿梓", "拟声鸟药水哥", "百度女声", "百度男声", "百度度逍遥", "百度度丫丫"}, - } - re = regexp.MustCompile(`(\-|\+)?\d+(\.\d+)?`) -) +var re = regexp.MustCompile(`(\-|\+)?\d+(\.\d+)?`) type ttsInstances struct { sync.RWMutex @@ -53,6 +40,17 @@ func (t *ttsInstances) List() []string { } func init() { + t := &ttsInstances{ + m: map[string]tts.TTS{ + "百度女声": baidutts.NewBaiduTTS(0), + "百度男声": baidutts.NewBaiduTTS(1), + "百度度逍遥": baidutts.NewBaiduTTS(3), + "百度度丫丫": baidutts.NewBaiduTTS(4), + "拟声鸟阿梓": nil, + "拟声鸟药水哥": nil, + }, + l: []string{"拟声鸟阿梓", "拟声鸟药水哥", "百度女声", "百度男声", "百度度逍遥", "百度度丫丫"}, + } engine := control.Register(ttsServiceName, order.AcquirePrio(), &control.Options{ DisableOnDefault: true, Help: "语音回复(包括拟声鸟和百度)\n" + @@ -65,19 +63,21 @@ func init() { msg := ctx.ExtractPlainText() r := aireply.NewAIReply(getReplyMode(ctx)) tts := t.new(t.getSoundMode(ctx)) - ctx.SendChain(message.Record(tts.Speak(ctx.Event.UserID, func() string { - reply := r.TalkPlain(msg, zero.BotConfig.NickName[0]) - reply = re.ReplaceAllStringFunc(reply, func(s string) string { - f, err := strconv.ParseFloat(s, 64) - if err != nil { - log.Errorln("[tts]:", err) - return s - } - return numcn.EncodeFromFloat64(f) - }) - log.Println("[tts]:", reply) - return reply - }))) + if tts != nil { + ctx.SendChain(message.Record(tts.Speak(ctx.Event.UserID, func() string { + reply := r.TalkPlain(msg, zero.BotConfig.NickName[0]) + reply = re.ReplaceAllStringFunc(reply, func(s string) string { + f, err := strconv.ParseFloat(s, 64) + if err != nil { + log.Errorln("[tts]:", err) + return s + } + return numcn.EncodeFromFloat64(f) + }) + log.Println("[tts]:", reply) + return reply + }))) + } }) engine.OnRegex(`^设置语音模式(.*)$`, ctxext.FirstValueInList(t)).SetBlock(true). Handle(func(ctx *zero.Ctx) { @@ -98,8 +98,23 @@ func init() { } // new 语音简单工厂 -func (t *ttsInstances) new(name string) tts.TTS { - return t.m[name] +func (t *ttsInstances) new(name string) (ts tts.TTS) { + t.RLock() + ts = t.m[name] + t.RUnlock() + if ts == nil { + switch name { + case "拟声鸟阿梓": + t.Lock() + ts, _ = mockingbird.NewMockingBirdTTS(0) + t.Unlock() + case "拟声鸟药水哥": + t.Lock() + ts, _ = mockingbird.NewMockingBirdTTS(1) + t.Unlock() + } + } + return } func (t *ttsInstances) setSoundMode(ctx *zero.Ctx, name string) error { diff --git a/plugin/fortune/fortune.go b/plugin/fortune/fortune.go index d6373cc1..9ef8e379 100644 --- a/plugin/fortune/fortune.go +++ b/plugin/fortune/fortune.go @@ -58,15 +58,15 @@ func init() { "- 设置底图[车万 | DC4 | 爱因斯坦 | 星空列车 | 樱云之恋 | 富婆妹 | 李清歌 | 公主连结 | 原神 | 明日方舟 | 碧蓝航线 | 碧蓝幻想 | 战双 | 阴阳师 | 赛马娘 | 东方归言录]", PublicDataFolder: "Fortune", }) + _ = os.RemoveAll(cache) + err := os.MkdirAll(cache, 0755) + if err != nil { + panic(err) + } go func() { for i, s := range table { index[s] = uint8(i) } - _ = os.RemoveAll(cache) - err := os.MkdirAll(cache, 0755) - if err != nil { - panic(err) - } data, err := file.GetLazyData(omikujson, true, false) if err != nil { panic(err) @@ -75,7 +75,9 @@ func init() { if err != nil { panic(err) } - _, err = file.GetLazyData(font, false, true) + }() + go func() { + _, err := file.GetLazyData(font, false, true) if err != nil { panic(err) } diff --git a/plugin/hyaku/main.go b/plugin/hyaku/main.go new file mode 100644 index 00000000..e8fed209 --- /dev/null +++ b/plugin/hyaku/main.go @@ -0,0 +1,107 @@ +package hyaku + +import ( + "encoding/csv" + "fmt" + "math/rand" + "os" + "strconv" + "unsafe" + + "github.com/FloatTech/zbputils/control" + "github.com/FloatTech/zbputils/control/order" + "github.com/FloatTech/zbputils/ctxext" + "github.com/FloatTech/zbputils/file" + zero "github.com/wdvxdr1123/ZeroBot" + "github.com/wdvxdr1123/ZeroBot/message" +) + +const bed = "https://gitcode.net/u011570312/OguraHyakuninIsshu/-/raw/master/" + +type line struct { + no, 歌人, 上の句, 下の句, 上の句ひらがな, 下の句ひらがな string +} + +var lines [100]*line + +func init() { + engine := control.Register("hyaku", order.AcquirePrio(), &control.Options{ + DisableOnDefault: false, + Help: "百人一首\n" + + "- 百人一首(随机发一首)\n" + + "- 百人一首之n", + PrivateDataFolder: "hyaku", + }) + csvfile := engine.DataFolder() + "hyaku.csv" + go func() { + if file.IsNotExist(csvfile) { + err := file.DownloadTo(bed+"小倉百人一首.csv", csvfile, true) + if err != nil { + _ = os.Remove(csvfile) + panic(err) + } + } + f, err := os.Open(csvfile) + if err != nil { + panic(err) + } + records, err := csv.NewReader(f).ReadAll() + if err != nil { + panic(err) + } + records = records[1:] // skip title + if len(records) != 100 { + panic("invalid csvfile") + } + for j, r := range records { + i, err := strconv.Atoi(r[0]) + if err != nil { + panic(err) + } + i-- + if j != i { + panic("invalid csvfile") + } + lines[i] = (*line)(*(*unsafe.Pointer)(unsafe.Pointer(&r))) + } + }() + engine.OnFullMatch("百人一首").SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) { + i := rand.Intn(100) + ctx.SendChain( + message.Image(fmt.Sprintf(bed+"img/%03d.jpg", i+1)), + message.Text("\n", + "●番 号: ", lines[i].no, "\n", + "●歌 人: ", lines[i].歌人, "\n", + "●上の句: ", lines[i].上の句, "\n", + "●下の句: ", lines[i].下の句, "\n", + "●上の句ひらがな: ", lines[i].上の句ひらがな, "\n", + "●下の句ひらがな: ", lines[i].下の句ひらがな, "\n", + ), + message.Image(fmt.Sprintf(bed+"img/%03d.png", i+1)), + ) + }) + engine.OnRegex(`^百人一首之\s?(\d+)$`).SetBlock(true).Limit(ctxext.LimitByUser).Handle(func(ctx *zero.Ctx) { + i, err := strconv.Atoi(ctx.State["regex_matched"].([]string)[1]) + if err != nil { + ctx.SendChain(message.Text("ERROR:", err)) + return + } + if i > 100 || i < 1 { + ctx.SendChain(message.Text("ERROR:超出范围")) + return + } + i-- + ctx.SendChain( + message.Image(fmt.Sprintf(bed+"img/%03d.jpg", i+1)), + message.Text("\n", + "●番 号: ", lines[i].no, "\n", + "●歌 人: ", lines[i].歌人, "\n", + "●上の句: ", lines[i].上の句, "\n", + "●下の句: ", lines[i].下の句, "\n", + "●上の句ひらがな: ", lines[i].上の句ひらがな, "\n", + "●下の句ひらがな: ", lines[i].下の句ひらがな, "\n", + ), + message.Image(fmt.Sprintf(bed+"img/%03d.png", i+1)), + ) + }) +} diff --git a/plugin/score/sign_in.go b/plugin/score/sign_in.go index 46183b3c..8c9687dc 100644 --- a/plugin/score/sign_in.go +++ b/plugin/score/sign_in.go @@ -47,14 +47,6 @@ func init() { if err != nil { panic(err) } - _, err = file.GetLazyData(text.BoldFontFile, false, true) - if err != nil { - panic(err) - } - _, err = file.GetLazyData(text.FontFile, false, true) - if err != nil { - panic(err) - } sdb = initialize(engine.DataFolder() + "score.db") log.Println("[score]加载score数据库") }() @@ -99,6 +91,11 @@ func init() { monthWord := now.Format("01/02") hourWord := getHourWord(now) + _, err = file.GetLazyData(text.BoldFontFile, false, true) + if err != nil { + ctx.SendChain(message.Text("ERROR:", err)) + return + } if err = canvas.LoadFontFace(text.BoldFontFile, float64(back.Bounds().Size().X)*0.1); err != nil { ctx.SendChain(message.Text("ERROR:", err)) return @@ -107,6 +104,11 @@ func init() { canvas.DrawString(hourWord, float64(back.Bounds().Size().X)*0.1, float64(back.Bounds().Size().Y)*1.2) canvas.DrawString(monthWord, float64(back.Bounds().Size().X)*0.6, float64(back.Bounds().Size().Y)*1.2) nickName := ctx.CardOrNickName(uid) + _, err = file.GetLazyData(text.FontFile, false, true) + if err != nil { + ctx.SendChain(message.Text("ERROR:", err)) + return + } if err = canvas.LoadFontFace(text.FontFile, float64(back.Bounds().Size().X)*0.04); err != nil { ctx.SendChain(message.Text("ERROR:", err)) return diff --git a/plugin/wordle/wordle.go b/plugin/wordle/wordle.go index 07205b08..3fe2a751 100644 --- a/plugin/wordle/wordle.go +++ b/plugin/wordle/wordle.go @@ -8,6 +8,7 @@ import ( "math/rand" "sort" "strings" + "sync" "time" "github.com/FloatTech/zbputils/control" @@ -53,7 +54,10 @@ type dictionary map[int]struct { cet4 []string } -var words = make(dictionary) +var ( + words = make(dictionary) + wordsmu sync.Mutex +) func init() { en := control.Register("wordle", order.AcquirePrio(), &control.Options{ @@ -72,26 +76,34 @@ func init() { ) }), )) - go func() { - for i := 5; i <= 7; i++ { + for i := 5; i <= 7; i++ { + go func(i int) { dc, err := file.GetLazyData(fmt.Sprintf("%scet-4_%d.txt", en.DataFolder(), i), true, true) if err != nil { panic(err) } c := strings.Split(string(dc), "\n") sort.Strings(c) + wordsmu.Lock() + tmp := words[i] + tmp.cet4 = c + words[i] = tmp + wordsmu.Unlock() + }(i) + go func(i int) { dd, err := file.GetLazyData(fmt.Sprintf("%sdict_%d.txt", en.DataFolder(), i), true, true) if err != nil { panic(err) } d := strings.Split(string(dd), "\n") sort.Strings(d) - words[i] = struct { - dict []string - cet4 []string - }{d, c} - } - }() + wordsmu.Lock() + tmp := words[i] + tmp.dict = d + words[i] = tmp + wordsmu.Unlock() + }(i) + } en.OnRegex(`(个人|团队)(五阶|六阶|七阶)?猜单词`, zero.OnlyGroup).SetBlock(true).Limit(ctxext.LimitByUser). Handle(func(ctx *zero.Ctx) { class := classdict[ctx.State["regex_matched"].([]string)[2]]