diff --git a/README.md b/README.md index 8041d77df2..a630a5cdb1 100644 --- a/README.md +++ b/README.md @@ -655,6 +655,8 @@ print("run[CQ:image,file="+j["img"]+"]") - [x] 齁语解密 [密文] 或 h解密 [密文] - [x] fumo加密 [文本] - [x] fumo解密 [文本] + - [x] qq加密 [文本] + - [x] qq解密 [密文]
diff --git a/go.mod b/go.mod index 4b2cf8ab3b..bf5e019293 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/FloatTech/sqlite v1.7.2 github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d github.com/FloatTech/zbpctrl v1.7.1 - github.com/FloatTech/zbputils v1.7.2-0.20260131170726-494cb1776a47 + github.com/FloatTech/zbputils v1.7.2-0.20260117132036-29f021ceb949 github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 github.com/RomiChan/websocket v1.4.3-0.20251002072000-d3eb41798438 github.com/Tnze/go-mc v1.20.2 @@ -24,17 +24,16 @@ require ( github.com/fumiama/cron v1.3.0 github.com/fumiama/deepinfra v0.0.0-20251221163610-e98ee3ba437a github.com/fumiama/go-base16384 v1.7.1 - github.com/fumiama/go-onebot-agent v0.0.0-20260128132028-05e6b4809f0a + github.com/fumiama/go-onebot-agent v0.0.0-20260117094018-cd93ccfd6e04 github.com/fumiama/go-registry v0.2.7 github.com/fumiama/gotracemoe v0.0.3 - github.com/fumiama/imgsz v0.0.4 github.com/fumiama/jieba v0.0.0-20221203025406-36c17a10b565 github.com/fumiama/slowdo v0.0.0-20241001074058-27c4fe5259a4 github.com/fumiama/terasu v1.0.2 github.com/fumiama/unibase2n v0.0.0-20240530074540-ec743fd5a6d6 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/google/uuid v1.6.0 - github.com/guohuiyuan/music-lib v1.0.2-0.20260121020416-53f6cb24629d + github.com/guohuiyuan/music-lib v1.0.3 github.com/jinzhu/gorm v1.9.16 github.com/jozsefsallai/gophersauce v1.0.1 github.com/kanrichan/resvg-go v0.0.2-0.20231001163256-63db194ca9f5 @@ -44,14 +43,14 @@ require ( github.com/mroth/weightedrand v1.0.0 github.com/notnil/chess v1.10.0 github.com/pkg/errors v0.9.1 - github.com/shirou/gopsutil/v4 v4.25.12 + github.com/shirou/gopsutil/v4 v4.26.1 github.com/sirupsen/logrus v1.9.4 github.com/tidwall/gjson v1.18.0 github.com/wcharczuk/go-chart/v2 v2.1.2 github.com/wdvxdr1123/ZeroBot v1.8.3-0.20260117102541-393033a35adb gitlab.com/gomidi/midi/v2 v2.3.18 golang.org/x/image v0.34.0 - golang.org/x/sys v0.39.0 + golang.org/x/sys v0.40.0 golang.org/x/text v0.32.0 ) @@ -67,6 +66,7 @@ require ( github.com/ericpauley/go-quantize v0.0.0-20200331213906-ae555eb2afa4 // indirect github.com/fumiama/go-simple-protobuf v0.2.0 // indirect github.com/fumiama/gofastTEA v0.1.3 // indirect + github.com/fumiama/imgsz v0.0.4 // indirect github.com/fumiama/orbyte v0.0.0-20251002065953-3bb358367eb5 // indirect github.com/gabriel-vasile/mimetype v1.4.12 // indirect github.com/go-ole/go-ole v1.2.6 // indirect diff --git a/go.sum b/go.sum index 6ec7775d99..fde9c3a138 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d h1:mUQ/c3wXKsUGa4Sg9 github.com/FloatTech/ttl v0.0.0-20250224045156-012b1463287d/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs= github.com/FloatTech/zbpctrl v1.7.1 h1:0yPEmCForhyMbnhTckmjDUFFDZgQp1RjO2bVF4ZVqOs= github.com/FloatTech/zbpctrl v1.7.1/go.mod h1:xmM4dSwHA02Gei3ogCRiG+RTrw/7Z69PfrN5NYf8BPE= -github.com/FloatTech/zbputils v1.7.2-0.20260131170726-494cb1776a47 h1:slMr6r4XDKnYCFmWhcHA02O3MTAUnU8p2gEe843JyQA= -github.com/FloatTech/zbputils v1.7.2-0.20260131170726-494cb1776a47/go.mod h1:W2kaR/A5oUtEb7DnveXCc0T374VjI+f3KmOWH9FE5vU= +github.com/FloatTech/zbputils v1.7.2-0.20260117132036-29f021ceb949 h1:1AEUIu4up84J4VqrENGyzUuYEIaQ5xYNDwIm00voL5c= +github.com/FloatTech/zbputils v1.7.2-0.20260117132036-29f021ceb949/go.mod h1:uX5JHIADt9/vSIriLZTRwkeVvOVwxOGiDyS5O1lTPGE= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U= github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= @@ -67,8 +67,8 @@ github.com/fumiama/deepinfra v0.0.0-20251221163610-e98ee3ba437a h1:a0+2vaXajfxsN github.com/fumiama/deepinfra v0.0.0-20251221163610-e98ee3ba437a/go.mod h1:uqsWK/GM9OvKV0pXZOQB63rWugBbiXInY8E1JoRKhkg= github.com/fumiama/go-base16384 v1.7.1 h1:1P1x6FWRvd7PtbH4idDAGWAjKKcVxggxlROYKRXbw58= github.com/fumiama/go-base16384 v1.7.1/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM= -github.com/fumiama/go-onebot-agent v0.0.0-20260128132028-05e6b4809f0a h1:8GYo5nctK2si5WDNX0WmZTxY7TWXRjAOBu5pjK7GDW0= -github.com/fumiama/go-onebot-agent v0.0.0-20260128132028-05e6b4809f0a/go.mod h1:rTrS23rvTYuZcSngENJTvcBFTz1nGsImSv+bW7yfhqs= +github.com/fumiama/go-onebot-agent v0.0.0-20260117094018-cd93ccfd6e04 h1:TAvkyECK+lSVh+AnVSPNfCmeCiYiJCd+z9QQwfjHSuw= +github.com/fumiama/go-onebot-agent v0.0.0-20260117094018-cd93ccfd6e04/go.mod h1:rTrS23rvTYuZcSngENJTvcBFTz1nGsImSv+bW7yfhqs= github.com/fumiama/go-registry v0.2.7 h1:tLEqgEpsiybQMqBv0dLHm5leia/z1DhajMupwnOHeNs= github.com/fumiama/go-registry v0.2.7/go.mod h1:m+wp5fF8dYgVoFkBPZl+vlK90loymaJE0JCtocVQLEs= github.com/fumiama/go-simple-protobuf v0.2.0 h1:ACyN1MAlu7pDR3EszWgzUeNP+IRsSHwH6V9JCJA5R5o= @@ -117,8 +117,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopxl/beep/v2 v2.1.1 h1:6FYIYMm2qPAdWkjX+7xwKrViS1x0Po5kDMdRkq8NVbU= github.com/gopxl/beep/v2 v2.1.1/go.mod h1:ZAm9TGQ9lvpoiFLd4zf5B1IuyxZhgRACMId1XJbaW0E= -github.com/guohuiyuan/music-lib v1.0.2-0.20260121020416-53f6cb24629d h1:6Cw52c4JaYvq55yAa9ZgUQeBL6b3ZWErQqkbeMZiAYw= -github.com/guohuiyuan/music-lib v1.0.2-0.20260121020416-53f6cb24629d/go.mod h1:D/6kQDwhQFDNZEMjN8y760DQSVYpOGlQXrYzhKz0rCQ= +github.com/guohuiyuan/music-lib v1.0.3 h1:lp1/YrQ+KcJ/Maww8pndrjHXNvWlJ6wXRRCGoyuZiZ8= +github.com/guohuiyuan/music-lib v1.0.3/go.mod h1:3DexVzzLf4nVxdz/b1qpRnDJ7y66TjUaQWjTOCwl1ro= github.com/jfreymuth/oggvorbis v1.0.5 h1:u+Ck+R0eLSRhgq8WTmffYnrVtSztJcYrl588DM4e3kQ= github.com/jfreymuth/oggvorbis v1.0.5/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII= github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE= @@ -182,8 +182,8 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/shirou/gopsutil/v4 v4.25.12 h1:e7PvW/0RmJ8p8vPGJH4jvNkOyLmbkXgXW4m6ZPic6CY= -github.com/shirou/gopsutil/v4 v4.25.12/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU= +github.com/shirou/gopsutil/v4 v4.26.1 h1:TOkEyriIXk2HX9d4isZJtbjXbEjf5qyKPAzbzY0JWSo= +github.com/shirou/gopsutil/v4 v4.26.1/go.mod h1:medLI9/UNAb0dOI9Q3/7yWSqKkj00u+1tgY8nvv41pc= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -277,8 +277,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= diff --git a/plugin/crypter/handlers.go b/plugin/crypter/handlers.go index 45a51b805f..6a96410e70 100644 --- a/plugin/crypter/handlers.go +++ b/plugin/crypter/handlers.go @@ -2,18 +2,104 @@ package crypter import ( + "fmt" + "regexp" + "strconv" + "strings" + "github.com/FloatTech/AnimeAPI/airecord" zero "github.com/wdvxdr1123/ZeroBot" "github.com/wdvxdr1123/ZeroBot/message" ) +var faceTagRe = regexp.MustCompile(`\{\{face:(\d+)\}\}`) + +func parseID(v interface{}) int64 { + n, _ := strconv.ParseInt(fmt.Sprint(v), 10, 64) + return n +} + +func serializeMsg(segs message.Message) string { + var sb strings.Builder + for _, seg := range segs { + switch seg.Type { + case "text": + sb.WriteString(seg.Data["text"]) + case "face": + fmt.Fprintf(&sb, "{{face:%v}}", seg.Data["id"]) + } + } + return sb.String() +} + +func deserializeMsg(s string) message.Message { + var msg message.Message + parts := faceTagRe.Split(s, -1) + matches := faceTagRe.FindAllStringSubmatch(s, -1) + for i, part := range parts { + if part != "" { + msg = append(msg, message.Text(part)) + } + if i < len(matches) { + id, _ := strconv.Atoi(matches[i][1]) + msg = append(msg, message.Face(id)) + } + } + return msg +} + +func getInput(ctx *zero.Ctx, cmds ...string) string { + full := serializeMsg(ctx.Event.Message) + for _, cmd := range cmds { + if idx := strings.Index(full, cmd); idx >= 0 { + return strings.TrimSpace(full[idx+len(cmd):]) + } + } + return "" +} + +func getReplyContent(ctx *zero.Ctx) string { + for _, seg := range ctx.Event.Message { + if seg.Type == "reply" { + if msgID := parseID(seg.Data["id"]); msgID > 0 { + if msg := ctx.GetMessage(msgID); msg.Elements != nil { + return serializeMsg(msg.Elements) + } + } + } + } + return "" +} + +func getReplyFaceIDs(ctx *zero.Ctx) []int { + for _, seg := range ctx.Event.Message { + if seg.Type == "reply" { + if msgID := parseID(seg.Data["id"]); msgID > 0 { + return extractFaceIDs(ctx.GetMessage(msgID).Elements) + } + } + } + return nil +} + +func extractFaceIDs(segs message.Message) []int { + var ids []int + for _, seg := range segs { + if seg.Type == "face" { + if id := int(parseID(seg.Data["id"])); id > 0 { + ids = append(ids, id) + } + } + } + return ids +} + // hou func houEncryptHandler(ctx *zero.Ctx) { - text := ctx.State["regex_matched"].([]string)[1] + text := getInput(ctx, "h加密", "齁语加密") result := encodeHou(text) recCfg := airecord.GetConfig() - record := ctx.GetAIRecord(recCfg.ModelID, recCfg.Customgid, result) - if record != "" { + if record := ctx.GetAIRecord(recCfg.ModelID, recCfg.Customgid, result); record != "" { ctx.SendChain(message.Record(record)) } else { ctx.SendChain(message.Text(result)) @@ -21,20 +107,52 @@ func houEncryptHandler(ctx *zero.Ctx) { } func houDecryptHandler(ctx *zero.Ctx) { - text := ctx.State["regex_matched"].([]string)[1] - result := decodeHou(text) - ctx.SendChain(message.Text(result)) + text := getInput(ctx, "h解密", "齁语解密") + if text == "" { + text = getReplyContent(ctx) + } + if text == "" { + ctx.SendChain(message.Text("请输入密文或回复加密消息")) + return + } + ctx.SendChain(deserializeMsg(decodeHou(text))...) } // fumo func fumoEncryptHandler(ctx *zero.Ctx) { - text := ctx.State["regex_matched"].([]string)[1] - result := encryptFumo(text) - ctx.SendChain(message.Text(result)) + ctx.SendChain(message.Text(encryptFumo(getInput(ctx, "fumo加密")))) } func fumoDecryptHandler(ctx *zero.Ctx) { - text := ctx.State["regex_matched"].([]string)[1] - result := decryptFumo(text) - ctx.SendChain(message.Text(result)) + text := getInput(ctx, "fumo解密") + if text == "" { + text = getReplyContent(ctx) + } + if text == "" { + ctx.SendChain(message.Text("请输入密文或回复加密消息")) + return + } + ctx.SendChain(deserializeMsg(decryptFumo(text))...) +} + +// qq表情 +func qqEmojiEncryptHandler(ctx *zero.Ctx) { + text := getInput(ctx, "qq加密") + if text == "" { + ctx.SendChain(message.Text("请输入要加密的文本")) + return + } + ctx.SendChain(encodeQQEmoji(text)...) +} + +func qqEmojiDecryptHandler(ctx *zero.Ctx) { + faceIDs := extractFaceIDs(ctx.Event.Message) + if len(faceIDs) == 0 { + faceIDs = getReplyFaceIDs(ctx) + } + if len(faceIDs) == 0 { + ctx.SendChain(message.Text("请回复QQ表情加密消息进行解密")) + return + } + ctx.SendChain(deserializeMsg(decodeQQEmoji(faceIDs))...) } diff --git a/plugin/crypter/main.go b/plugin/crypter/main.go index caf38668af..c1c539bac8 100644 --- a/plugin/crypter/main.go +++ b/plugin/crypter/main.go @@ -17,15 +17,25 @@ func init() { "- 齁语解密 [密文] 或 h解密 [密文]\n\n" + "- Fumo语加解密:\n" + "- fumo加密 [文本]\n" + - "- fumo解密 [密文]\n\n", + "- fumo解密 [密文]\n\n" + + "- QQ表情加解密:\n" + + "- qq加密 [文本]\n" + + "- qq解密 [密文]\n\n" + + "注意:QQ表情解密建议使用回复,尽量不要复制粘贴\n\n", PublicDataFolder: "Crypter", }) + re := `(?:\[CQ:reply,id=-?\d+\])?` + // hou - engine.OnRegex(`^(?:齁语加密|h加密)\s*(.+)$`).SetBlock(true).Handle(houEncryptHandler) - engine.OnRegex(`^(?:齁语解密|h解密)\s*(.+)$`).SetBlock(true).Handle(houDecryptHandler) + engine.OnRegex(re + `^(?:齁语加密|h加密)\s*(.+)$`).SetBlock(true).Handle(houEncryptHandler) + engine.OnRegex(re + `(?:齁语解密|h解密)\s*(.*)$`).SetBlock(true).Handle(houDecryptHandler) // Fumo - engine.OnRegex(`^fumo加密\s*(.+)$`).SetBlock(true).Handle(fumoEncryptHandler) - engine.OnRegex(`^fumo解密\s*(.+)$`).SetBlock(true).Handle(fumoDecryptHandler) + engine.OnRegex(re + `^fumo加密\s*(.+)$`).SetBlock(true).Handle(fumoEncryptHandler) + engine.OnRegex(re + `fumo解密\s*(.*)$`).SetBlock(true).Handle(fumoDecryptHandler) + + // QQ表情 + engine.OnRegex(re + `^qq加密\s*(.+)$`).SetBlock(true).Handle(qqEmojiEncryptHandler) + engine.OnRegex(re + `qq解密`).SetBlock(true).Handle(qqEmojiDecryptHandler) } diff --git a/plugin/crypter/qqemoji.go b/plugin/crypter/qqemoji.go new file mode 100644 index 0000000000..7aebd02db7 --- /dev/null +++ b/plugin/crypter/qqemoji.go @@ -0,0 +1,66 @@ +// Package crypter QQ表情加解密 +package crypter + +import ( + "fmt" + "strings" + "unicode/utf8" + + "github.com/wdvxdr1123/ZeroBot/message" +) + +const ( + emojiZeroID = 297 + emojiOneID = 424 +) + +func encodeQQEmoji(text string) message.Message { + if text == "" { + return message.Message{message.Text("请输入要加密的文本")} + } + + var bin strings.Builder + for _, b := range []byte(text) { + fmt.Fprintf(&bin, "%08b", b) + } + + s := bin.String() + msg := make(message.Message, 0, len(s)) + for _, bit := range s { + if bit == '0' { + msg = append(msg, message.Face(emojiZeroID)) + } else { + msg = append(msg, message.Face(emojiOneID)) + } + } + return msg +} + +func decodeQQEmoji(faceIDs []int) string { + var bin strings.Builder + for _, id := range faceIDs { + if id == emojiZeroID { + bin.WriteByte('0') + } else if id == emojiOneID { + bin.WriteByte('1') + } + } + binary := bin.String() + if len(binary) == 0 || len(binary)%8 != 0 { + return "QQ表情密文格式错误" + } + + data := make([]byte, len(binary)/8) + for i := range data { + for j := 0; j < 8; j++ { + if binary[i*8+j] == '1' { + data[i] |= 1 << (7 - j) + } + } + } + + if !utf8.Valid(data) { + return "QQ表情解密失败:结果不是有效文本" + } + return string(data) +}