mirror of
https://github.com/Mrs4s/MiraiGo.git
synced 2025-06-19 05:55:05 +08:00
refactor(message): ForwardMessage don't impl IMessageElement interface
use ForwardMessage to upload and get the ForwardElement.
This commit is contained in:
parent
feb482e0e3
commit
cb396f0f56
@ -1,10 +1,8 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
@ -13,6 +11,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
"github.com/Mrs4s/MiraiGo/binary/jce"
|
"github.com/Mrs4s/MiraiGo/binary/jce"
|
||||||
devinfo "github.com/Mrs4s/MiraiGo/client/pb"
|
devinfo "github.com/Mrs4s/MiraiGo/client/pb"
|
||||||
@ -20,8 +21,6 @@ import (
|
|||||||
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
|
"github.com/Mrs4s/MiraiGo/client/pb/oidb"
|
||||||
"github.com/Mrs4s/MiraiGo/message"
|
"github.com/Mrs4s/MiraiGo/message"
|
||||||
"github.com/Mrs4s/MiraiGo/utils"
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -586,12 +585,6 @@ func packUniRequestData(data []byte) (r []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func XmlEscape(c string) string {
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
_ = xml.EscapeText(buf, []byte(c))
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func genForwardTemplate(resID, preview, title, brief, source, summary string, ts int64, items []*msg.PbMultiMsgItem) *message.ForwardElement {
|
func genForwardTemplate(resID, preview, title, brief, source, summary string, ts int64, items []*msg.PbMultiMsgItem) *message.ForwardElement {
|
||||||
template := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8'?><msg serviceID="35" templateID="1" action="viewMultiMsg" brief="%s" m_resid="%s" m_fileName="%d" tSum="3" sourceMsgId="0" url="" flag="3" adverSign="0" multiMsgFlag="0"><item layout="1"><title color="#000000" size="34">%s</title> %s<hr></hr><summary size="26" color="#808080">%s</summary></item><source name="%s"></source></msg>`,
|
template := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8'?><msg serviceID="35" templateID="1" action="viewMultiMsg" brief="%s" m_resid="%s" m_fileName="%d" tSum="3" sourceMsgId="0" url="" flag="3" adverSign="0" multiMsgFlag="0"><item layout="1"><title color="#000000" size="34">%s</title> %s<hr></hr><summary size="26" color="#808080">%s</summary></item><source name="%s"></source></msg>`,
|
||||||
brief, resID, ts, title, preview, summary, source,
|
brief, resID, ts, title, preview, summary, source,
|
||||||
@ -617,7 +610,7 @@ func genLongTemplate(resID, brief string, ts int64) *message.ServiceElement {
|
|||||||
return brief
|
return brief
|
||||||
}()
|
}()
|
||||||
template := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="35" templateID="1" action="viewMultiMsg" brief="%s" m_resid="%s" m_fileName="%d" sourceMsgId="0" url="" flag="3" adverSign="0" multiMsgFlag="1"> <item layout="1"> <title>%s</title> <hr hidden="false" style="0"/> <summary>点击查看完整消息</summary> </item> <source name="聊天记录" icon="" action="" appid="-1"/> </msg>`,
|
template := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="35" templateID="1" action="viewMultiMsg" brief="%s" m_resid="%s" m_fileName="%d" sourceMsgId="0" url="" flag="3" adverSign="0" multiMsgFlag="1"> <item layout="1"> <title>%s</title> <hr hidden="false" style="0"/> <summary>点击查看完整消息</summary> </item> <source name="聊天记录" icon="" action="" appid="-1"/> </msg>`,
|
||||||
XmlEscape(limited), resID, ts, XmlEscape(limited),
|
utils.XmlEscape(limited), resID, ts, utils.XmlEscape(limited),
|
||||||
)
|
)
|
||||||
return &message.ServiceElement{
|
return &message.ServiceElement{
|
||||||
Id: 35,
|
Id: 35,
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/longmsg"
|
"github.com/Mrs4s/MiraiGo/client/pb/longmsg"
|
||||||
@ -53,14 +54,12 @@ func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage,
|
|||||||
ret := c.sendGroupMessage(groupCode, false,
|
ret := c.sendGroupMessage(groupCode, false,
|
||||||
&message.SendingMessage{Elements: []message.IMessageElement{
|
&message.SendingMessage{Elements: []message.IMessageElement{
|
||||||
c.uploadGroupLongMessage(groupCode,
|
c.uploadGroupLongMessage(groupCode,
|
||||||
&message.ForwardMessage{Nodes: []*message.ForwardNode{
|
message.NewForwardMessage().AddNode(&message.ForwardNode{
|
||||||
{
|
|
||||||
SenderId: c.Uin,
|
SenderId: c.Uin,
|
||||||
SenderName: c.Nickname,
|
SenderName: c.Nickname,
|
||||||
Time: int32(time.Now().Unix()),
|
Time: int32(time.Now().Unix()),
|
||||||
Message: m.Elements,
|
Message: m.Elements,
|
||||||
},
|
}),
|
||||||
}},
|
|
||||||
),
|
),
|
||||||
}},
|
}},
|
||||||
)
|
)
|
||||||
@ -71,9 +70,9 @@ func (c *QQClient) SendGroupMessage(groupCode int64, m *message.SendingMessage,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SendGroupForwardMessage 发送群合并转发消息
|
// SendGroupForwardMessage 发送群合并转发消息
|
||||||
func (c *QQClient) SendGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.GroupMessage {
|
func (c *QQClient) SendGroupForwardMessage(groupCode int64, m *message.ForwardElement) *message.GroupMessage {
|
||||||
return c.sendGroupMessage(groupCode, true,
|
return c.sendGroupMessage(groupCode, true,
|
||||||
&message.SendingMessage{Elements: []message.IMessageElement{c.UploadGroupForwardMessage(groupCode, m)}},
|
&message.SendingMessage{Elements: []message.IMessageElement{m}},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +160,7 @@ func (c *QQClient) sendGroupMessage(groupCode int64, forward bool, m *message.Se
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) uploadGroupLongMessage(groupCode int64, m *message.ForwardMessage) *message.ServiceElement {
|
func (c *QQClient) uploadGroupLongMessage(groupCode int64, m *message.ForwardMessage) *message.ServiceElement {
|
||||||
if len(m.Nodes) >= 200 {
|
if m.Length() >= 200 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ts := time.Now().UnixNano()
|
ts := time.Now().UnixNano()
|
||||||
@ -173,25 +172,16 @@ func (c *QQClient) uploadGroupLongMessage(groupCode int64, m *message.ForwardMes
|
|||||||
}
|
}
|
||||||
for i, ip := range rsp.Uint32UpIp {
|
for i, ip := range rsp.Uint32UpIp {
|
||||||
err := c.highwayUpload(uint32(ip), int(rsp.Uint32UpPort[i]), rsp.MsgSig, body, 27)
|
err := c.highwayUpload(uint32(ip), int(rsp.Uint32UpPort[i]), rsp.MsgSig, body, 27)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
bri := func() string {
|
continue
|
||||||
var r string
|
|
||||||
for _, n := range m.Nodes {
|
|
||||||
r += message.ToReadableString(n.Message)
|
|
||||||
if len(r) >= 27 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}()
|
|
||||||
return genLongTemplate(rsp.MsgResid, bri, ts)
|
|
||||||
}
|
}
|
||||||
|
return genLongTemplate(rsp.MsgResid, m.Brief(), ts)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *QQClient) UploadGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.ForwardElement {
|
func (c *QQClient) UploadGroupForwardMessage(groupCode int64, m *message.ForwardMessage) *message.ForwardElement {
|
||||||
if len(m.Nodes) > 200 {
|
if m.Length() > 200 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ts := time.Now().UnixNano()
|
ts := time.Now().UnixNano()
|
||||||
@ -203,13 +193,10 @@ func (c *QQClient) UploadGroupForwardMessage(groupCode int64, m *message.Forward
|
|||||||
}
|
}
|
||||||
for i, ip := range rsp.Uint32UpIp {
|
for i, ip := range rsp.Uint32UpIp {
|
||||||
err := c.highwayUpload(uint32(ip), int(rsp.Uint32UpPort[i]), rsp.MsgSig, body, 27)
|
err := c.highwayUpload(uint32(ip), int(rsp.Uint32UpPort[i]), rsp.MsgSig, body, 27)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
var pv string
|
continue
|
||||||
for i := 0; i < int(math.Min(4, float64(len(m.Nodes)))); i++ {
|
|
||||||
pv += fmt.Sprintf(`<title size="26" color="#777777">%s: %s</title>`, XmlEscape(m.Nodes[i].SenderName), XmlEscape(message.ToReadableString(m.Nodes[i].Message)))
|
|
||||||
}
|
|
||||||
return genForwardTemplate(rsp.MsgResid, pv, "群聊的聊天记录", "[聊天记录]", "聊天记录", fmt.Sprintf("查看 %d 条转发消息", len(m.Nodes)), ts, items)
|
|
||||||
}
|
}
|
||||||
|
return genForwardTemplate(rsp.MsgResid, m.Preview(), "群聊的聊天记录", "[聊天记录]", "聊天记录", fmt.Sprintf("查看 %d 条转发消息", m.Length()), ts, items)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -529,10 +516,11 @@ func (c *QQClient) parseGroupMessage(m *msg.Message) *message.GroupMessage {
|
|||||||
if extInfo != nil && len(extInfo.GroupCard) > 0 && extInfo.GroupCard[0] == 0x0A {
|
if extInfo != nil && len(extInfo.GroupCard) > 0 && extInfo.GroupCard[0] == 0x0A {
|
||||||
buf := oidb.D8FCCommCardNameBuf{}
|
buf := oidb.D8FCCommCardNameBuf{}
|
||||||
if err := proto.Unmarshal(extInfo.GroupCard, &buf); err == nil && len(buf.RichCardName) > 0 {
|
if err := proto.Unmarshal(extInfo.GroupCard, &buf); err == nil && len(buf.RichCardName) > 0 {
|
||||||
groupCard = ""
|
var gcard strings.Builder
|
||||||
for _, e := range buf.RichCardName {
|
for _, e := range buf.RichCardName {
|
||||||
groupCard += string(e.Text)
|
gcard.Write(e.Text)
|
||||||
}
|
}
|
||||||
|
groupCard = gcard.String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m.Head.GroupInfo != nil && groupCard != "" && mem.CardName != groupCard {
|
if m.Head.GroupInfo != nil && groupCard != "" && mem.CardName != groupCard {
|
||||||
|
@ -178,8 +178,7 @@ func NewPrivateReply(m *PrivateMessage) *ReplyElement {
|
|||||||
|
|
||||||
func NewUrlShare(url, title, content, image string) *ServiceElement {
|
func NewUrlShare(url, title, content, image string) *ServiceElement {
|
||||||
template := fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?><msg templateID="12345" action="web" brief="[分享] %s" serviceID="1" url="%s"><item layout="2"><picture cover="%v"/><title>%v</title><summary>%v</summary></item><source/></msg>`,
|
template := fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?><msg templateID="12345" action="web" brief="[分享] %s" serviceID="1" url="%s"><item layout="2"><picture cover="%v"/><title>%v</title><summary>%v</summary></item><source/></msg>`,
|
||||||
title, url, image, title, content,
|
title, url, image, title, content)
|
||||||
)
|
|
||||||
/*
|
/*
|
||||||
template := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes'?><msg templateID="123" url="%s" serviceID="33" action="web" actionData="" brief="【链接】%s" flag="8"><item layout="2"><picture cover="%s"/><title>%s</title><summary>%s</summary></item></msg>`,
|
template := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes'?><msg templateID="123" url="%s" serviceID="33" action="web" actionData="" brief="【链接】%s" flag="8"><item layout="2"><picture cover="%s"/><title>%s</title><summary>%s</summary></item></msg>`,
|
||||||
url, url, image, title, content,
|
url, url, image, title, content,
|
||||||
|
@ -1,18 +1,22 @@
|
|||||||
package message
|
package message
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
"github.com/Mrs4s/MiraiGo/client/pb/msg"
|
"github.com/Mrs4s/MiraiGo/client/pb/msg"
|
||||||
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// *----- Definitions -----* //
|
// *----- Definitions -----* //
|
||||||
|
|
||||||
|
// ForwardMessage 添加 Node 请用 AddNode 方法
|
||||||
type ForwardMessage struct {
|
type ForwardMessage struct {
|
||||||
Nodes []*ForwardNode
|
Nodes []*ForwardNode
|
||||||
|
items []*msg.PbMultiMsgItem
|
||||||
}
|
}
|
||||||
|
|
||||||
type ForwardNode struct {
|
type ForwardNode struct {
|
||||||
@ -36,26 +40,67 @@ func (e *ForwardElement) Type() ElementType {
|
|||||||
return Forward
|
return Forward
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ForwardElement) Pack() (r []*msg.Elem) {
|
func (e *ForwardElement) Pack() []*msg.Elem {
|
||||||
r = []*msg.Elem{}
|
rich := &msg.Elem{
|
||||||
r = append(r, &msg.Elem{
|
|
||||||
RichMsg: &msg.RichMsg{
|
RichMsg: &msg.RichMsg{
|
||||||
Template1: append([]byte{1}, binary.ZlibCompress([]byte(e.Content))...),
|
Template1: append([]byte{1}, binary.ZlibCompress(utils.S2B(e.Content))...),
|
||||||
ServiceId: proto.Int32(35),
|
ServiceId: proto.Int32(35),
|
||||||
MsgResId: []byte{},
|
MsgResId: []byte{},
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
r = append(r, &msg.Elem{
|
txt := &msg.Elem{
|
||||||
Text: &msg.Text{
|
Text: &msg.Text{
|
||||||
Str: proto.String("你的QQ暂不支持查看[转发多条消息],请期待后续版本。"),
|
Str: proto.String("你的QQ暂不支持查看[转发多条消息],请期待后续版本。"),
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
return
|
return []*msg.Elem{rich, txt}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type impl IMessageElement
|
func NewForwardMessage() *ForwardMessage {
|
||||||
func (f *ForwardMessage) Type() ElementType {
|
return &ForwardMessage{}
|
||||||
return Forward
|
}
|
||||||
|
|
||||||
|
// AddNode adds a node to the forward message. return for method chaining.
|
||||||
|
func (f *ForwardMessage) AddNode(node *ForwardNode) *ForwardMessage {
|
||||||
|
f.Nodes = append(f.Nodes, node)
|
||||||
|
for _, item := range node.Message {
|
||||||
|
if item.Type() != Forward { // quick path
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if forward, ok := item.(*ForwardElement); ok {
|
||||||
|
f.items = append(f.items, forward.Items...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Length return the length of Nodes.
|
||||||
|
func (f *ForwardMessage) Length() int { return len(f.Nodes) }
|
||||||
|
|
||||||
|
func (f *ForwardMessage) Brief() string {
|
||||||
|
var brief bytes.Buffer
|
||||||
|
for _, n := range f.Nodes {
|
||||||
|
brief.WriteString(ToReadableString(n.Message))
|
||||||
|
if brief.Len() >= 27 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return brief.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *ForwardMessage) Preview() string {
|
||||||
|
var pv bytes.Buffer
|
||||||
|
for i, node := range f.Nodes {
|
||||||
|
if i >= 4 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
pv.WriteString(`<title size="26" color="#777777">`)
|
||||||
|
pv.WriteString(utils.XmlEscape(node.SenderName))
|
||||||
|
pv.WriteString(": ")
|
||||||
|
pv.WriteString(utils.XmlEscape(ToReadableString(node.Message)))
|
||||||
|
pv.WriteString("</title>")
|
||||||
|
}
|
||||||
|
return pv.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ForwardMessage) CalculateValidationData(seq, random int32, groupCode int64) ([]byte, []byte) {
|
func (f *ForwardMessage) CalculateValidationData(seq, random int32, groupCode int64) ([]byte, []byte) {
|
||||||
@ -81,13 +126,7 @@ func (f *ForwardMessage) CalculateValidationDataForward(seq, random int32, group
|
|||||||
Buffer: &msg.PbMultiMsgNew{Msg: msgs},
|
Buffer: &msg.PbMultiMsgNew{Msg: msgs},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
for _, node := range f.Nodes {
|
trans.PbItemList = append(trans.PbItemList, f.items...)
|
||||||
for _, message := range node.Message {
|
|
||||||
if forwardElement, ok := message.(*ForwardElement); ok {
|
|
||||||
trans.PbItemList = append(trans.PbItemList, forwardElement.Items...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b, _ := proto.Marshal(trans)
|
b, _ := proto.Marshal(trans)
|
||||||
data := binary.GZipCompress(b)
|
data := binary.GZipCompress(b)
|
||||||
hash := md5.Sum(data)
|
hash := md5.Sum(data)
|
||||||
@ -95,9 +134,9 @@ func (f *ForwardMessage) CalculateValidationDataForward(seq, random int32, group
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *ForwardMessage) packForwardMsg(seq int32, random int32, groupCode int64) []*msg.Message {
|
func (f *ForwardMessage) packForwardMsg(seq int32, random int32, groupCode int64) []*msg.Message {
|
||||||
msgs := make([]*msg.Message, 0, len(f.Nodes))
|
ml := make([]*msg.Message, 0, len(f.Nodes))
|
||||||
for _, node := range f.Nodes {
|
for _, node := range f.Nodes {
|
||||||
msgs = append(msgs, &msg.Message{
|
ml = append(ml, &msg.Message{
|
||||||
Head: &msg.MessageHead{
|
Head: &msg.MessageHead{
|
||||||
FromUin: &node.SenderId,
|
FromUin: &node.SenderId,
|
||||||
MsgSeq: &seq,
|
MsgSeq: &seq,
|
||||||
@ -121,5 +160,5 @@ func (f *ForwardMessage) packForwardMsg(seq int32, random int32, groupCode int64
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return msgs
|
return ml
|
||||||
}
|
}
|
||||||
|
@ -418,7 +418,7 @@ func ParseMessageElems(elems []*msg.Elem) []IMessageElement {
|
|||||||
}
|
}
|
||||||
if content != "" {
|
if content != "" {
|
||||||
if elem.RichMsg.GetServiceId() == 35 {
|
if elem.RichMsg.GetServiceId() == 35 {
|
||||||
reg := regexp.MustCompile(`m_resid="(.+)"`)
|
reg := regexp.MustCompile(`m_resid="(.*?)"`)
|
||||||
sub := reg.FindAllStringSubmatch(content, -1)
|
sub := reg.FindAllStringSubmatch(content, -1)
|
||||||
if len(sub) > 0 && len(sub[0]) > 1 {
|
if len(sub) > 0 && len(sub[0]) > 1 {
|
||||||
res = append(res, &ForwardElement{ResId: reg.FindAllStringSubmatch(content, -1)[0][1]})
|
res = append(res, &ForwardElement{ResId: reg.FindAllStringSubmatch(content, -1)[0][1]})
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/xml"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -66,3 +67,10 @@ func S2B(s string) (b []byte) {
|
|||||||
bh.Len = sh.Len
|
bh.Len = sh.Len
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XmlEscape xml escape string
|
||||||
|
func XmlEscape(c string) string {
|
||||||
|
buf := new(strings.Builder)
|
||||||
|
_ = xml.EscapeText(buf, []byte(c))
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user