mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-03-01 10:30:26 +00:00
feat(crypter): 添加qq表情加密并支持回应密文 (#1287)
This commit is contained in:
@@ -655,6 +655,8 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
- [x] 齁语解密 [密文] 或 h解密 [密文]
|
- [x] 齁语解密 [密文] 或 h解密 [密文]
|
||||||
- [x] fumo加密 [文本]
|
- [x] fumo加密 [文本]
|
||||||
- [x] fumo解密 [文本]
|
- [x] fumo解密 [文本]
|
||||||
|
- [x] qq加密 [文本]
|
||||||
|
- [x] qq解密 [密文]
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
|
|||||||
@@ -2,18 +2,104 @@
|
|||||||
package crypter
|
package crypter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/FloatTech/AnimeAPI/airecord"
|
"github.com/FloatTech/AnimeAPI/airecord"
|
||||||
zero "github.com/wdvxdr1123/ZeroBot"
|
zero "github.com/wdvxdr1123/ZeroBot"
|
||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"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
|
// hou
|
||||||
func houEncryptHandler(ctx *zero.Ctx) {
|
func houEncryptHandler(ctx *zero.Ctx) {
|
||||||
text := ctx.State["regex_matched"].([]string)[1]
|
text := getInput(ctx, "h加密", "齁语加密")
|
||||||
result := encodeHou(text)
|
result := encodeHou(text)
|
||||||
recCfg := airecord.GetConfig()
|
recCfg := airecord.GetConfig()
|
||||||
record := ctx.GetAIRecord(recCfg.ModelID, recCfg.Customgid, result)
|
if record := ctx.GetAIRecord(recCfg.ModelID, recCfg.Customgid, result); record != "" {
|
||||||
if record != "" {
|
|
||||||
ctx.SendChain(message.Record(record))
|
ctx.SendChain(message.Record(record))
|
||||||
} else {
|
} else {
|
||||||
ctx.SendChain(message.Text(result))
|
ctx.SendChain(message.Text(result))
|
||||||
@@ -21,20 +107,52 @@ func houEncryptHandler(ctx *zero.Ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func houDecryptHandler(ctx *zero.Ctx) {
|
func houDecryptHandler(ctx *zero.Ctx) {
|
||||||
text := ctx.State["regex_matched"].([]string)[1]
|
text := getInput(ctx, "h解密", "齁语解密")
|
||||||
result := decodeHou(text)
|
if text == "" {
|
||||||
ctx.SendChain(message.Text(result))
|
text = getReplyContent(ctx)
|
||||||
|
}
|
||||||
|
if text == "" {
|
||||||
|
ctx.SendChain(message.Text("请输入密文或回复加密消息"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.SendChain(deserializeMsg(decodeHou(text))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fumo
|
// fumo
|
||||||
func fumoEncryptHandler(ctx *zero.Ctx) {
|
func fumoEncryptHandler(ctx *zero.Ctx) {
|
||||||
text := ctx.State["regex_matched"].([]string)[1]
|
ctx.SendChain(message.Text(encryptFumo(getInput(ctx, "fumo加密"))))
|
||||||
result := encryptFumo(text)
|
|
||||||
ctx.SendChain(message.Text(result))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func fumoDecryptHandler(ctx *zero.Ctx) {
|
func fumoDecryptHandler(ctx *zero.Ctx) {
|
||||||
text := ctx.State["regex_matched"].([]string)[1]
|
text := getInput(ctx, "fumo解密")
|
||||||
result := decryptFumo(text)
|
if text == "" {
|
||||||
ctx.SendChain(message.Text(result))
|
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))...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,15 +17,25 @@ func init() {
|
|||||||
"- 齁语解密 [密文] 或 h解密 [密文]\n\n" +
|
"- 齁语解密 [密文] 或 h解密 [密文]\n\n" +
|
||||||
"- Fumo语加解密:\n" +
|
"- Fumo语加解密:\n" +
|
||||||
"- fumo加密 [文本]\n" +
|
"- fumo加密 [文本]\n" +
|
||||||
"- fumo解密 [密文]\n\n",
|
"- fumo解密 [密文]\n\n" +
|
||||||
|
"- QQ表情加解密:\n" +
|
||||||
|
"- qq加密 [文本]\n" +
|
||||||
|
"- qq解密 [密文]\n\n" +
|
||||||
|
"注意:QQ表情解密建议使用回复,尽量不要复制粘贴\n\n",
|
||||||
PublicDataFolder: "Crypter",
|
PublicDataFolder: "Crypter",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
re := `(?:\[CQ:reply,id=-?\d+\])?`
|
||||||
|
|
||||||
// hou
|
// hou
|
||||||
engine.OnRegex(`^(?:齁语加密|h加密)\s*(.+)$`).SetBlock(true).Handle(houEncryptHandler)
|
engine.OnRegex(re + `^(?:齁语加密|h加密)\s*(.+)$`).SetBlock(true).Handle(houEncryptHandler)
|
||||||
engine.OnRegex(`^(?:齁语解密|h解密)\s*(.+)$`).SetBlock(true).Handle(houDecryptHandler)
|
engine.OnRegex(re + `(?:齁语解密|h解密)\s*(.*)$`).SetBlock(true).Handle(houDecryptHandler)
|
||||||
|
|
||||||
// Fumo
|
// Fumo
|
||||||
engine.OnRegex(`^fumo加密\s*(.+)$`).SetBlock(true).Handle(fumoEncryptHandler)
|
engine.OnRegex(re + `^fumo加密\s*(.+)$`).SetBlock(true).Handle(fumoEncryptHandler)
|
||||||
engine.OnRegex(`^fumo解密\s*(.+)$`).SetBlock(true).Handle(fumoDecryptHandler)
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
66
plugin/crypter/qqemoji.go
Normal file
66
plugin/crypter/qqemoji.go
Normal file
@@ -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)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user