From 93fa36034a3c5dc7ce2ea86610557c46317dfa7e Mon Sep 17 00:00:00 2001 From: Madray Haven Date: Tue, 8 Nov 2022 09:46:46 +0800 Subject: [PATCH 1/3] fix: daemon mode --- cmd/gocq/main.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/gocq/main.go b/cmd/gocq/main.go index 2177fcd..50699a3 100644 --- a/cmd/gocq/main.go +++ b/cmd/gocq/main.go @@ -55,13 +55,14 @@ func Main() { switch { case base.LittleH: base.Help() - case base.LittleWD != "": + case base.LittleD: + server.Daemon() + } + if base.LittleWD != "" { err := os.Chdir(base.LittleWD) if err != nil { log.Fatalf("重置工作目录时出现错误: %v", err) } - case base.LittleD: - server.Daemon() } base.Init() From 6f2bb1402f6bfd8ec9caca3220c9b15d8f6f33db Mon Sep 17 00:00:00 2001 From: Mrs4s Date: Thu, 1 Dec 2022 17:17:24 +0800 Subject: [PATCH 2/3] update dep --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0de9c8b..3b6bd5b 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/Microsoft/go-winio v0.5.1 - github.com/Mrs4s/MiraiGo v0.0.0-20220828090150-a3c348100dfe + github.com/Mrs4s/MiraiGo v0.0.0-20221201090748-23f637d2954e github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc github.com/fumiama/go-base16384 v1.5.2 diff --git a/go.sum b/go.sum index 47b2da4..9550d9c 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Mrs4s/MiraiGo v0.0.0-20220828090150-a3c348100dfe h1:KpRbU5MRL2dplf01Cbgo8m0+ST1V1A+4cFBQkQA/YAk= -github.com/Mrs4s/MiraiGo v0.0.0-20220828090150-a3c348100dfe/go.mod h1:lecSP26qedhinCceWn1x02dLDxGotH5nTFlpIMilmVM= +github.com/Mrs4s/MiraiGo v0.0.0-20221201090748-23f637d2954e h1:PvTvu1c9R8XCDGysBYGF+TSO+UfX347NJkNblifC4C8= +github.com/Mrs4s/MiraiGo v0.0.0-20221201090748-23f637d2954e/go.mod h1:lecSP26qedhinCceWn1x02dLDxGotH5nTFlpIMilmVM= github.com/RomiChan/protobuf v0.1.1-0.20220624030127-3310cba9dbc0 h1:+UGPBYVjssFsdahLJIiNPwpmmwgl/OaVdv1oc5NonC0= github.com/RomiChan/protobuf v0.1.1-0.20220624030127-3310cba9dbc0/go.mod h1:2Ie+hdBFQpQFDHfeklgxoFmQRCE7O+KwFpISeXq7OwA= github.com/RomiChan/syncx v0.0.0-20220404072119-d7ea0ae15a4c h1:cNPOdTNiVwxLpROLjXCgbIPvdkE+BwvxDvgmdYmWx6Q= From 0248c86078edc09fa396f5e1bfc8bacc8fca3fd1 Mon Sep 17 00:00:00 2001 From: Mrs4s Date: Thu, 1 Dec 2022 18:09:18 +0800 Subject: [PATCH 3/3] fix #1733 --- coolq/cqcode/element.go | 4 +- coolq/event.go | 6 +- global/quote.go | 146 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 global/quote.go diff --git a/coolq/cqcode/element.go b/coolq/cqcode/element.go index 2605d5a..2788ba2 100644 --- a/coolq/cqcode/element.go +++ b/coolq/cqcode/element.go @@ -2,10 +2,10 @@ package cqcode import ( "bytes" - "strconv" "strings" "github.com/Mrs4s/MiraiGo/binary" + "github.com/Mrs4s/go-cqhttp/global" ) // Element single message @@ -60,7 +60,7 @@ func (e *Element) MarshalJSON() ([]byte, error) { buf.WriteByte('"') buf.WriteString(data.K) buf.WriteString(`":`) - buf.WriteString(strconv.Quote(data.V)) + buf.WriteString(global.Quote(data.V)) } buf.WriteString(`}}`) }), nil diff --git a/coolq/event.go b/coolq/event.go index 34500e2..02c4da6 100644 --- a/coolq/event.go +++ b/coolq/event.go @@ -61,7 +61,11 @@ func (ev *event) MarshalJSON() ([]byte, error) { fmt.Fprintf(buf, `,"sub_type":"%s"`, ev.SubType) } for k, v := range ev.Others { - v, _ := json.Marshal(v) + v, err := json.Marshal(v) + if err != nil { + log.Warnf("marshal message payload error: %v", err) + return nil, err + } fmt.Fprintf(buf, `,"%s":%s`, k, v) } buf.WriteByte('}') diff --git a/global/quote.go b/global/quote.go new file mode 100644 index 0000000..bad54b9 --- /dev/null +++ b/global/quote.go @@ -0,0 +1,146 @@ +package global + +import ( + "strconv" + "unicode/utf8" +) + +const ( + lowerhex = "0123456789abcdef" + upperhex = "0123456789ABCDEF" +) + +// Quote returns a double-quoted Go string literal representing s. The +// returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for +// control characters and non-printable characters as defined by +// IsPrint. +func Quote(s string) string { + return quoteWith(s, '"', false, false) +} + +func quoteWith(s string, quote byte, ASCIIonly, graphicOnly bool) string { + return string(appendQuotedWith(make([]byte, 0, 3*len(s)/2), s, quote, ASCIIonly, graphicOnly)) +} + +func appendQuotedWith(buf []byte, s string, quote byte, ASCIIonly, graphicOnly bool) []byte { + // Often called with big strings, so preallocate. If there's quoting, + // this is conservative but still helps a lot. + if cap(buf)-len(buf) < len(s) { + nBuf := make([]byte, len(buf), len(buf)+1+len(s)+1) + copy(nBuf, buf) + buf = nBuf + } + buf = append(buf, quote) + for width := 0; len(s) > 0; s = s[width:] { + r := rune(s[0]) + width = 1 + if r >= utf8.RuneSelf { + r, width = utf8.DecodeRuneInString(s) + } + if width == 1 && r == utf8.RuneError { + buf = append(buf, `\x`...) + buf = append(buf, lowerhex[s[0]>>4]) + buf = append(buf, lowerhex[s[0]&0xF]) + continue + } + buf = appendEscapedRune(buf, r, quote, ASCIIonly, graphicOnly) + } + buf = append(buf, quote) + return buf +} +func appendEscapedRune(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bool) []byte { + var runeTmp [utf8.UTFMax]byte + if r == rune(quote) || r == '\\' { // always backslashed + buf = append(buf, '\\') + buf = append(buf, byte(r)) + return buf + } + if ASCIIonly { + if r < utf8.RuneSelf && strconv.IsPrint(r) { + buf = append(buf, byte(r)) + return buf + } + } else if strconv.IsPrint(r) || graphicOnly && isInGraphicList(r) { + n := utf8.EncodeRune(runeTmp[:], r) + buf = append(buf, runeTmp[:n]...) + return buf + } + switch r { + case '\a': + buf = append(buf, `\a`...) + case '\b': + buf = append(buf, `\b`...) + case '\f': + buf = append(buf, `\f`...) + case '\n': + buf = append(buf, `\n`...) + case '\r': + buf = append(buf, `\r`...) + case '\t': + buf = append(buf, `\t`...) + case '\v': + buf = append(buf, `\v`...) + default: + switch { + case !utf8.ValidRune(r): + r = 0xFFFD + fallthrough + case r < 0x10000: + buf = append(buf, `\u`...) + for s := 12; s >= 0; s -= 4 { + buf = append(buf, lowerhex[r>>uint(s)&0xF]) + } + default: + buf = append(buf, `\U`...) + for s := 28; s >= 0; s -= 4 { + buf = append(buf, lowerhex[r>>uint(s)&0xF]) + } + } + } + return buf +} + +func isInGraphicList(r rune) bool { + // We know r must fit in 16 bits - see makeisprint.go. + if r > 0xFFFF { + return false + } + rr := uint16(r) + i := bsearch16(isGraphic, rr) + return i < len(isGraphic) && rr == isGraphic[i] +} + +// bsearch16 returns the smallest i such that a[i] >= x. +// If there is no such i, bsearch16 returns len(a). +func bsearch16(a []uint16, x uint16) int { + i, j := 0, len(a) + for i < j { + h := i + (j-i)>>1 + if a[h] < x { + i = h + 1 + } else { + j = h + } + } + return i +} + +// isGraphic lists the graphic runes not matched by IsPrint. +var isGraphic = []uint16{ + 0x00a0, + 0x1680, + 0x2000, + 0x2001, + 0x2002, + 0x2003, + 0x2004, + 0x2005, + 0x2006, + 0x2007, + 0x2008, + 0x2009, + 0x200a, + 0x202f, + 0x205f, + 0x3000, +}