mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-05 19:43:49 +08:00
167 lines
3.6 KiB
Go
167 lines
3.6 KiB
Go
package coolq
|
|
|
|
import (
|
|
"bufio"
|
|
"github.com/Mrs4s/MiraiGo/message"
|
|
log "github.com/sirupsen/logrus"
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type CQCodeConverter struct {
|
|
message []rune
|
|
bot *CQBot
|
|
group bool
|
|
|
|
index int
|
|
stat state
|
|
elements []message.IMessageElement
|
|
tempText []rune
|
|
cqCode []rune
|
|
}
|
|
|
|
type state uint8
|
|
|
|
const (
|
|
S0 state = iota
|
|
S1
|
|
)
|
|
|
|
func newCQCodeConverter(message string, bot *CQBot, group bool) *CQCodeConverter {
|
|
return &CQCodeConverter{message: []rune(message), bot: bot, group: group, stat: S0}
|
|
}
|
|
|
|
func (c *CQCodeConverter) hasNext() bool {
|
|
return c.index < len(c.message)
|
|
}
|
|
|
|
func (c *CQCodeConverter) next() rune {
|
|
r := c.message[c.index]
|
|
c.index++
|
|
return r
|
|
}
|
|
|
|
func (c *CQCodeConverter) move(steps int) {
|
|
c.index += steps
|
|
}
|
|
|
|
func (c *CQCodeConverter) peek(idx int) rune {
|
|
return c.message[idx]
|
|
}
|
|
|
|
func (c *CQCodeConverter) peekN(count int) string {
|
|
lastIdx := int(math.Min(float64(c.index+count), float64(len(c.message)-1)))
|
|
return string(c.message[c.index:lastIdx])
|
|
}
|
|
|
|
func (c *CQCodeConverter) isCQCodeBegin(r rune) bool {
|
|
return r == '[' && c.peekN(3) == "CQ:"
|
|
}
|
|
|
|
func (c *CQCodeConverter) saveTempText() {
|
|
if len(c.tempText) != 0 {
|
|
c.elements = append(c.elements, message.NewText(CQCodeUnescapeValue(string(c.tempText))))
|
|
}
|
|
c.tempText = []rune{}
|
|
c.cqCode = []rune{}
|
|
}
|
|
|
|
func (c *CQCodeConverter) saveCQCode() {
|
|
defer func() {
|
|
c.cqCode = []rune{}
|
|
c.tempText = []rune{}
|
|
}()
|
|
reader := strings.NewReader(string(c.cqCode))
|
|
buf := bufio.NewReader(reader)
|
|
t, _ := buf.ReadString(',')
|
|
t = t[0 : len(t)-1]
|
|
params := make(map[string]string)
|
|
for buf.Buffered() > 0 {
|
|
p, _ := buf.ReadString(',')
|
|
if strings.HasSuffix(p, ",") {
|
|
p = p[0 : len(p)-1]
|
|
}
|
|
p = strings.TrimSpace(p)
|
|
if p == "" {
|
|
continue
|
|
}
|
|
data := strings.SplitN(p, "=", 2)
|
|
if len(data) == 2 {
|
|
params[data[0]] = data[1]
|
|
} else {
|
|
params[p] = ""
|
|
}
|
|
}
|
|
if t == "reply" { // reply 特殊处理
|
|
if len(c.elements) > 0 {
|
|
if _, ok := c.elements[0].(*message.ReplyElement); ok {
|
|
log.Warnf("警告: 一条信息只能包含一个 Reply 元素.")
|
|
return
|
|
}
|
|
}
|
|
mid, err := strconv.Atoi(params["id"])
|
|
if err == nil {
|
|
org := c.bot.GetMessage(int32(mid))
|
|
if org != nil {
|
|
c.elements = append([]message.IMessageElement{
|
|
&message.ReplyElement{
|
|
ReplySeq: org["message-id"].(int32),
|
|
Sender: org["sender"].(message.Sender).Uin,
|
|
Time: org["time"].(int32),
|
|
Elements: c.bot.ConvertStringMessage(org["message"].(string), c.group),
|
|
},
|
|
}, c.elements...)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
elem, err := c.bot.ToElement(t, params, c.group)
|
|
if err != nil {
|
|
org := "[" + string(c.cqCode) + "]"
|
|
if !IgnoreInvalidCQCode {
|
|
log.Warnf("转换CQ码 %v 时出现错误: %v 将原样发送.", org, err)
|
|
c.elements = append(c.elements, message.NewText(org))
|
|
} else {
|
|
log.Warnf("转换CQ码 %v 时出现错误: %v 将忽略.", org, err)
|
|
}
|
|
return
|
|
}
|
|
switch i := elem.(type) {
|
|
case message.IMessageElement:
|
|
c.elements = append(c.elements, i)
|
|
case []message.IMessageElement:
|
|
c.elements = append(c.elements, i...)
|
|
}
|
|
}
|
|
|
|
func (c *CQCodeConverter) convert() []message.IMessageElement {
|
|
for c.hasNext() {
|
|
ch := c.next()
|
|
switch c.stat {
|
|
case S0:
|
|
if c.isCQCodeBegin(ch) {
|
|
c.saveTempText()
|
|
c.tempText = append(c.tempText, []rune("[CQ:")...)
|
|
c.move(3)
|
|
c.stat = S1
|
|
} else {
|
|
c.tempText = append(c.tempText, ch)
|
|
}
|
|
case S1:
|
|
if c.isCQCodeBegin(ch) {
|
|
c.move(-1)
|
|
c.stat = S0
|
|
} else if ch == ']' {
|
|
c.saveCQCode()
|
|
c.stat = S0
|
|
} else {
|
|
c.cqCode = append(c.cqCode, ch)
|
|
c.tempText = append(c.tempText, ch)
|
|
}
|
|
}
|
|
}
|
|
c.saveTempText()
|
|
return c.elements
|
|
}
|