mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-06-30 20:03:24 +00:00
Compare commits
38 Commits
v1.0.0-rc4
...
onebot.v12
Author | SHA1 | Date | |
---|---|---|---|
59ed726c6a | |||
a7c003d404 | |||
0a4f849154 | |||
17420feeac | |||
2af671cec9 | |||
0f0ccf459f | |||
2483eb09c4 | |||
a8bed3fc03 | |||
bbef330069 | |||
d96f840d7f | |||
fc0845b16d | |||
f3da083be9 | |||
06450c66a2 | |||
4ed04443c5 | |||
0be18fb221 | |||
20c62111f5 | |||
84e061f321 | |||
4d064e145f | |||
64653a6815 | |||
4497053fb9 | |||
e050fd6885 | |||
43004e2496 | |||
7d5f1d6843 | |||
960f7ab79b | |||
4cddc5051f | |||
4a80441a5c | |||
a5b51051e6 | |||
311a254b9c | |||
008e139c27 | |||
524debbfda | |||
2a4ea28f4d | |||
4061904945 | |||
37a8901061 | |||
aec0ef66be | |||
86f5b7f5f5 | |||
672dafdb9d | |||
847ef6d415 | |||
f900fd62fb |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
|||||||
- name: Setup Go environment
|
- name: Setup Go environment
|
||||||
uses: actions/setup-go@v2.1.3
|
uses: actions/setup-go@v2.1.3
|
||||||
with:
|
with:
|
||||||
go-version: 1.19
|
go-version: '1.20'
|
||||||
- name: Cache downloaded module
|
- name: Cache downloaded module
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
@ -44,7 +44,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
if [ $GOOS = "windows" ]; then export BINARY_SUFFIX="$BINARY_SUFFIX.exe"; fi
|
if [ $GOOS = "windows" ]; then export BINARY_SUFFIX="$BINARY_SUFFIX.exe"; fi
|
||||||
if $IS_PR ; then echo $PR_PROMPT; fi
|
if $IS_PR ; then echo $PR_PROMPT; fi
|
||||||
export BINARY_NAME="$BINARY_PREFIX$GOOS_$GOARCH$BINARY_SUFFIX"
|
export BINARY_NAME="$BINARY_PREFIX"$GOOS"_$GOARCH$BINARY_SUFFIX"
|
||||||
export CGO_ENABLED=0
|
export CGO_ENABLED=0
|
||||||
export LD_FLAGS="-w -s -X github.com/Mrs4s/go-cqhttp/internal/base.Version=${COMMIT_ID::7}"
|
export LD_FLAGS="-w -s -X github.com/Mrs4s/go-cqhttp/internal/base.Version=${COMMIT_ID::7}"
|
||||||
go build -o "output/$BINARY_NAME" -trimpath -ldflags "$LD_FLAGS" .
|
go build -o "output/$BINARY_NAME" -trimpath -ldflags "$LD_FLAGS" .
|
||||||
|
2
.github/workflows/golint.yml
vendored
2
.github/workflows/golint.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
- name: Setup Go environment
|
- name: Setup Go environment
|
||||||
uses: actions/setup-go@v2.1.3
|
uses: actions/setup-go@v2.1.3
|
||||||
with:
|
with:
|
||||||
go-version: 1.19
|
go-version: '1.20'
|
||||||
|
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v2
|
uses: golangci/golangci-lint-action@v2
|
||||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: '1.19'
|
go-version: '1.20'
|
||||||
|
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v2
|
uses: goreleaser/goreleaser-action@v2
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.19-alpine AS builder
|
FROM golang:1.20-alpine AS builder
|
||||||
|
|
||||||
RUN go env -w GO111MODULE=auto \
|
RUN go env -w GO111MODULE=auto \
|
||||||
&& go env -w CGO_ENABLED=0 \
|
&& go env -w CGO_ENABLED=0 \
|
||||||
|
@ -23,7 +23,10 @@ type Param struct {
|
|||||||
|
|
||||||
type Router struct {
|
type Router struct {
|
||||||
Func string
|
Func string
|
||||||
|
Version []uint16
|
||||||
Path []string
|
Path []string
|
||||||
|
PathV11 []string // v11 only
|
||||||
|
PathV12 []string // v12 only
|
||||||
Params []Param
|
Params []Param
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,29 +34,93 @@ type generator struct {
|
|||||||
out io.Writer
|
out io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
PathAll = 0
|
||||||
|
PathV11 = 11
|
||||||
|
PathV12 = 12
|
||||||
|
)
|
||||||
|
|
||||||
func (g *generator) WriteString(s string) {
|
func (g *generator) WriteString(s string) {
|
||||||
io.WriteString(g.out, s)
|
io.WriteString(g.out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *generator) generate(routers []Router) {
|
func (g *generator) generate(routers []Router) {
|
||||||
|
var actions []string // for onebot v12 get_supported_actions
|
||||||
|
for _, router := range routers {
|
||||||
|
if len(router.PathV12) > 0 {
|
||||||
|
actions = append(actions, router.PathV12...)
|
||||||
|
}
|
||||||
|
if len(router.Path) > 0 {
|
||||||
|
actions = append(actions, router.Path...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := range actions {
|
||||||
|
actions[i] = `"` + actions[i] + `"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: v12 和 all 的 switch-case 由常量改为数组寻址, 以利用 get_supported_actions
|
||||||
g.WriteString("// Code generated by cmd/api-generator. DO NOT EDIT.\n\n")
|
g.WriteString("// Code generated by cmd/api-generator. DO NOT EDIT.\n\n")
|
||||||
g.WriteString("package api\n\nimport (\n\n")
|
g.WriteString("package api\n\nimport (\n\n")
|
||||||
g.WriteString("\"github.com/Mrs4s/go-cqhttp/coolq\"\n")
|
g.WriteString("\"github.com/Mrs4s/go-cqhttp/coolq\"\n")
|
||||||
g.WriteString("\"github.com/Mrs4s/go-cqhttp/global\"\n")
|
g.WriteString("\"github.com/Mrs4s/go-cqhttp/global\"\n")
|
||||||
g.WriteString(")\n\n")
|
g.WriteString(")\n\n")
|
||||||
g.WriteString(`func (c *Caller) call(action string, p Getter) global.MSG {
|
g.WriteString(fmt.Sprintf(`func (c *Caller) call(action string, version uint16, p Getter) global.MSG {
|
||||||
|
var converter coolq.IDConverter = func(id any) any {
|
||||||
|
return coolq.ConvertIDWithVersion(id,version)
|
||||||
|
}
|
||||||
|
if version == 12 {
|
||||||
|
if action == "get_supported_actions" {
|
||||||
|
return coolq.OK([]string{%v})
|
||||||
|
}
|
||||||
switch action {
|
switch action {
|
||||||
default:
|
`, strings.Join(actions, ",")))
|
||||||
return coolq.Failed(404, "API_NOT_FOUND", "API不存在")` + "\n")
|
|
||||||
for _, router := range routers {
|
for _, router := range routers {
|
||||||
g.router(router)
|
g.router(router, PathV12)
|
||||||
}
|
}
|
||||||
io.WriteString(g.out, `}}`)
|
io.WriteString(g.out, `}}`)
|
||||||
|
io.WriteString(g.out, "\n")
|
||||||
|
g.WriteString(`if version == 11 {
|
||||||
|
switch action {
|
||||||
|
`)
|
||||||
|
for _, router := range routers {
|
||||||
|
g.router(router, PathV11)
|
||||||
|
}
|
||||||
|
io.WriteString(g.out, `}}`)
|
||||||
|
io.WriteString(g.out, "\n")
|
||||||
|
io.WriteString(g.out, "switch action {\n")
|
||||||
|
for _, router := range routers {
|
||||||
|
g.router(router, PathAll)
|
||||||
|
}
|
||||||
|
io.WriteString(g.out, `}`)
|
||||||
|
io.WriteString(g.out, "\n")
|
||||||
|
io.WriteString(g.out, "return coolq.Failed(404, \"API_NOT_FOUND\", \"API不存在\")}")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *generator) router(router Router, pathVersion int) {
|
||||||
|
/*
|
||||||
|
checkVersion := func(v uint16) bool {
|
||||||
|
for _, ver := range router.Version {
|
||||||
|
if ver == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
path := router.Path
|
||||||
|
if pathVersion == PathV11 {
|
||||||
|
path = router.PathV11
|
||||||
|
}
|
||||||
|
if pathVersion == PathV12 {
|
||||||
|
path = router.PathV12
|
||||||
|
}
|
||||||
|
if len(path) == 0 {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *generator) router(router Router) {
|
|
||||||
g.WriteString(`case `)
|
g.WriteString(`case `)
|
||||||
for i, p := range router.Path {
|
for i, p := range path {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
g.WriteString(`, `)
|
g.WriteString(`, `)
|
||||||
}
|
}
|
||||||
@ -61,7 +128,19 @@ func (g *generator) router(router Router) {
|
|||||||
}
|
}
|
||||||
g.WriteString(":\n")
|
g.WriteString(":\n")
|
||||||
|
|
||||||
|
if len(router.Version) == 1 { // 目前来说只需要判断一个版本的情况
|
||||||
|
check := make([]string, 0, len(router.Version))
|
||||||
|
for _, ver := range router.Version {
|
||||||
|
check = append(check, fmt.Sprintf("version != %v", ver))
|
||||||
|
}
|
||||||
|
fmt.Fprintf(g.out, "if %v {\n", strings.Join(check, " && "))
|
||||||
|
fmt.Fprintf(g.out, "return coolq.Failed(405, \"VERSION_ERROR\", \"API版本不匹配\")}\n")
|
||||||
|
}
|
||||||
|
|
||||||
for i, p := range router.Params {
|
for i, p := range router.Params {
|
||||||
|
if p.Name == "version" || p.Name == "converter" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if p.Default == "" {
|
if p.Default == "" {
|
||||||
v := "p.Get(" + strconv.Quote(p.Name) + ")"
|
v := "p.Get(" + strconv.Quote(p.Name) + ")"
|
||||||
fmt.Fprintf(g.out, "p%d := %s\n", i, conv(v, p.Type))
|
fmt.Fprintf(g.out, "p%d := %s\n", i, conv(v, p.Type))
|
||||||
@ -73,10 +152,18 @@ func (g *generator) router(router Router) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
g.WriteString("\t\treturn c.bot." + router.Func + "(")
|
g.WriteString("\t\treturn c.bot." + router.Func + "(")
|
||||||
for i := range router.Params {
|
for i, p := range router.Params {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
g.WriteString(", ")
|
g.WriteString(", ")
|
||||||
}
|
}
|
||||||
|
if p.Name == "version" {
|
||||||
|
fmt.Fprintf(g.out, "version")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if p.Name == "converter" {
|
||||||
|
fmt.Fprintf(g.out, "converter")
|
||||||
|
continue
|
||||||
|
}
|
||||||
fmt.Fprintf(g.out, "p%d", i)
|
fmt.Fprintf(g.out, "p%d", i)
|
||||||
}
|
}
|
||||||
g.WriteString(")\n")
|
g.WriteString(")\n")
|
||||||
@ -86,7 +173,7 @@ func conv(v, t string) string {
|
|||||||
switch t {
|
switch t {
|
||||||
default:
|
default:
|
||||||
panic("unknown type: " + t)
|
panic("unknown type: " + t)
|
||||||
case "gjson.Result":
|
case "gjson.Result", "IDConverter":
|
||||||
return v
|
return v
|
||||||
case "int64":
|
case "int64":
|
||||||
return v + ".Int()"
|
return v + ".Int()"
|
||||||
@ -100,6 +187,8 @@ func conv(v, t string) string {
|
|||||||
return v + ".Uint()"
|
return v + ".Uint()"
|
||||||
case "uint32":
|
case "uint32":
|
||||||
return "uint32(" + v + ".Uint())"
|
return "uint32(" + v + ".Uint())"
|
||||||
|
case "uint16":
|
||||||
|
return "uint16(" + v + ".Uint())"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +197,8 @@ func main() {
|
|||||||
src := flag.String("path", "", "source file")
|
src := flag.String("path", "", "source file")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
file, err := parser.ParseFile(fset, *src, nil, parser.ParseComments)
|
for _, s := range strings.Split(*src, ",") {
|
||||||
|
file, err := parser.ParseFile(fset, s, nil, parser.ParseComments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -145,6 +235,14 @@ func main() {
|
|||||||
for _, route := range strings.Split(args, ",") {
|
for _, route := range strings.Split(args, ",") {
|
||||||
router.Path = append(router.Path, unquote(route))
|
router.Path = append(router.Path, unquote(route))
|
||||||
}
|
}
|
||||||
|
case "route11":
|
||||||
|
for _, route := range strings.Split(args, ",") {
|
||||||
|
router.PathV11 = append(router.PathV11, unquote(route))
|
||||||
|
}
|
||||||
|
case "route12":
|
||||||
|
for _, route := range strings.Split(args, ",") {
|
||||||
|
router.PathV12 = append(router.PathV12, unquote(route))
|
||||||
|
}
|
||||||
case "default":
|
case "default":
|
||||||
for name, value := range parseMap(args, "=") {
|
for name, value := range parseMap(args, "=") {
|
||||||
for i, p := range router.Params {
|
for i, p := range router.Params {
|
||||||
@ -161,21 +259,47 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "version":
|
||||||
|
version := strings.Split(args, ",")
|
||||||
|
for _, v := range version {
|
||||||
|
if i, err := strconv.ParseUint(v, 10, 16); err == nil {
|
||||||
|
router.Version = append(router.Version, uint16(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sort.Slice(router.Path, func(i, j int) bool {
|
sort.Slice(router.Path, func(i, j int) bool {
|
||||||
return router.Path[i] < router.Path[j]
|
return router.Path[i] < router.Path[j]
|
||||||
})
|
})
|
||||||
|
sort.Slice(router.PathV11, func(i, j int) bool {
|
||||||
|
return router.PathV11[i] < router.PathV11[j]
|
||||||
|
})
|
||||||
|
sort.Slice(router.PathV12, func(i, j int) bool {
|
||||||
|
return router.PathV12[i] < router.PathV12[j]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if router.Path != nil {
|
if router.Path != nil || router.PathV11 != nil || router.PathV12 != nil {
|
||||||
routers = append(routers, router)
|
routers = append(routers, router)
|
||||||
} else {
|
} else {
|
||||||
println(decl.Name.Name)
|
println(decl.Name.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sort.Slice(routers, func(i, j int) bool {
|
sort.Slice(routers, func(i, j int) bool {
|
||||||
return routers[i].Path[0] < routers[j].Path[0]
|
path := func(r Router) string {
|
||||||
|
if r.Path != nil {
|
||||||
|
return r.Path[0]
|
||||||
|
}
|
||||||
|
if r.PathV11 != nil {
|
||||||
|
return r.PathV11[0]
|
||||||
|
}
|
||||||
|
if r.PathV12 != nil {
|
||||||
|
return r.PathV12[0]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return path(routers[i]) < path(routers[j])
|
||||||
})
|
})
|
||||||
|
|
||||||
out := new(bytes.Buffer)
|
out := new(bytes.Buffer)
|
||||||
|
@ -29,7 +29,7 @@ func readLine() (str string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func readLineTimeout(t time.Duration, de string) (str string) {
|
func readLineTimeout(t time.Duration) {
|
||||||
r := make(chan string)
|
r := make(chan string)
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
select {
|
||||||
@ -37,12 +37,10 @@ func readLineTimeout(t time.Duration, de string) (str string) {
|
|||||||
case <-time.After(t):
|
case <-time.After(t):
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
str = de
|
|
||||||
select {
|
select {
|
||||||
case str = <-r:
|
case <-r:
|
||||||
case <-time.After(t):
|
case <-time.After(t):
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func readIfTTY(de string) (str string) {
|
func readIfTTY(de string) (str string) {
|
||||||
@ -210,7 +208,7 @@ func loginResponseProcessor(res *client.LoginResponse) error {
|
|||||||
case client.UnsafeDeviceError:
|
case client.UnsafeDeviceError:
|
||||||
log.Warnf("账号已开启设备锁,请前往 -> %v <- 验证后重启Bot.", res.VerifyUrl)
|
log.Warnf("账号已开启设备锁,请前往 -> %v <- 验证后重启Bot.", res.VerifyUrl)
|
||||||
log.Infof("按 Enter 或等待 5s 后继续....")
|
log.Infof("按 Enter 或等待 5s 后继续....")
|
||||||
readLineTimeout(time.Second*5, "")
|
readLineTimeout(time.Second * 5)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
case client.OtherLoginError, client.UnknownLoginError, client.TooManySMSRequestError:
|
case client.OtherLoginError, client.UnknownLoginError, client.TooManySMSRequestError:
|
||||||
msg := res.ErrorMessage
|
msg := res.ErrorMessage
|
||||||
@ -221,7 +219,7 @@ func loginResponseProcessor(res *client.LoginResponse) error {
|
|||||||
}
|
}
|
||||||
log.Warnf("登录失败: %v", msg)
|
log.Warnf("登录失败: %v", msg)
|
||||||
log.Infof("按 Enter 或等待 5s 后继续....")
|
log.Infof("按 Enter 或等待 5s 后继续....")
|
||||||
readLineTimeout(time.Second*5, "")
|
readLineTimeout(time.Second * 5)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,7 +252,7 @@ func getTicket(u string) (str string) {
|
|||||||
func fetchCaptcha(id string) string {
|
func fetchCaptcha(id string) string {
|
||||||
g, err := download.Request{URL: "https://captcha.go-cqhttp.org/captcha/ticket?id=" + id}.JSON()
|
g, err := download.Request{URL: "https://captcha.go-cqhttp.org/captcha/ticket?id=" + id}.JSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("获取 Ticket 时出现错误: %v", err)
|
log.Debugf("获取 Ticket 时出现错误: %v", err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if g.Get("ticket").Exists() {
|
if g.Get("ticket").Exists() {
|
||||||
|
76
coolq/api.go
76
coolq/api.go
@ -14,12 +14,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/segmentio/asm/base64"
|
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
"github.com/Mrs4s/MiraiGo/client"
|
"github.com/Mrs4s/MiraiGo/client"
|
||||||
"github.com/Mrs4s/MiraiGo/message"
|
"github.com/Mrs4s/MiraiGo/message"
|
||||||
"github.com/Mrs4s/MiraiGo/utils"
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
|
"github.com/segmentio/asm/base64"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
|
|
||||||
@ -48,7 +47,8 @@ var defaultPageToken = guildMemberPageToken{
|
|||||||
// CQGetLoginInfo 获取登录号信息
|
// CQGetLoginInfo 获取登录号信息
|
||||||
//
|
//
|
||||||
// https://git.io/Jtz1I
|
// https://git.io/Jtz1I
|
||||||
// @route(get_login_info)
|
// @route11(get_login_info)
|
||||||
|
// @route12(get_self_info)
|
||||||
func (bot *CQBot) CQGetLoginInfo() global.MSG {
|
func (bot *CQBot) CQGetLoginInfo() global.MSG {
|
||||||
return OK(global.MSG{"user_id": bot.Client.Uin, "nickname": bot.Client.Nickname})
|
return OK(global.MSG{"user_id": bot.Client.Uin, "nickname": bot.Client.Nickname})
|
||||||
}
|
}
|
||||||
@ -327,13 +327,13 @@ func (bot *CQBot) CQGetTopicChannelFeeds(guildID, channelID uint64) global.MSG {
|
|||||||
//
|
//
|
||||||
// https://git.io/Jtz1L
|
// https://git.io/Jtz1L
|
||||||
// @route(get_friend_list)
|
// @route(get_friend_list)
|
||||||
func (bot *CQBot) CQGetFriendList() global.MSG {
|
func (bot *CQBot) CQGetFriendList(version uint16) global.MSG {
|
||||||
fs := make([]global.MSG, 0, len(bot.Client.FriendList))
|
fs := make([]global.MSG, 0, len(bot.Client.FriendList))
|
||||||
for _, f := range bot.Client.FriendList {
|
for _, f := range bot.Client.FriendList {
|
||||||
fs = append(fs, global.MSG{
|
fs = append(fs, global.MSG{
|
||||||
"nickname": f.Nickname,
|
"nickname": f.Nickname,
|
||||||
"remark": f.Remark,
|
"remark": f.Remark,
|
||||||
"user_id": f.Uin,
|
"user_id": ConvertIDWithVersion(f.Uin, version),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return OK(fs)
|
return OK(fs)
|
||||||
@ -399,14 +399,14 @@ func (bot *CQBot) CQDeleteFriend(uin int64) global.MSG {
|
|||||||
//
|
//
|
||||||
// https://git.io/Jtz1t
|
// https://git.io/Jtz1t
|
||||||
// @route(get_group_list)
|
// @route(get_group_list)
|
||||||
func (bot *CQBot) CQGetGroupList(noCache bool) global.MSG {
|
func (bot *CQBot) CQGetGroupList(noCache bool, converter IDConverter) global.MSG {
|
||||||
gs := make([]global.MSG, 0, len(bot.Client.GroupList))
|
gs := make([]global.MSG, 0, len(bot.Client.GroupList))
|
||||||
if noCache {
|
if noCache {
|
||||||
_ = bot.Client.ReloadGroupList()
|
_ = bot.Client.ReloadGroupList()
|
||||||
}
|
}
|
||||||
for _, g := range bot.Client.GroupList {
|
for _, g := range bot.Client.GroupList {
|
||||||
gs = append(gs, global.MSG{
|
gs = append(gs, global.MSG{
|
||||||
"group_id": g.Code,
|
"group_id": converter(g.Code),
|
||||||
"group_name": g.Name,
|
"group_name": g.Name,
|
||||||
"group_create_time": g.GroupCreateTime,
|
"group_create_time": g.GroupCreateTime,
|
||||||
"group_level": g.GroupLevel,
|
"group_level": g.GroupLevel,
|
||||||
@ -421,7 +421,7 @@ func (bot *CQBot) CQGetGroupList(noCache bool) global.MSG {
|
|||||||
//
|
//
|
||||||
// https://git.io/Jtz1O
|
// https://git.io/Jtz1O
|
||||||
// @route(get_group_info)
|
// @route(get_group_info)
|
||||||
func (bot *CQBot) CQGetGroupInfo(groupID int64, noCache bool) global.MSG {
|
func (bot *CQBot) CQGetGroupInfo(groupID int64, noCache bool, converter IDConverter) global.MSG {
|
||||||
group := bot.Client.FindGroup(groupID)
|
group := bot.Client.FindGroup(groupID)
|
||||||
if group == nil || noCache {
|
if group == nil || noCache {
|
||||||
group, _ = bot.Client.GetGroupInfo(groupID)
|
group, _ = bot.Client.GetGroupInfo(groupID)
|
||||||
@ -435,7 +435,7 @@ func (bot *CQBot) CQGetGroupInfo(groupID int64, noCache bool) global.MSG {
|
|||||||
for _, g := range info {
|
for _, g := range info {
|
||||||
if g.Code == groupID {
|
if g.Code == groupID {
|
||||||
return OK(global.MSG{
|
return OK(global.MSG{
|
||||||
"group_id": g.Code,
|
"group_id": converter(g.Code),
|
||||||
"group_name": g.Name,
|
"group_name": g.Name,
|
||||||
"group_memo": g.Memo,
|
"group_memo": g.Memo,
|
||||||
"group_create_time": 0,
|
"group_create_time": 0,
|
||||||
@ -447,7 +447,7 @@ func (bot *CQBot) CQGetGroupInfo(groupID int64, noCache bool) global.MSG {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return OK(global.MSG{
|
return OK(global.MSG{
|
||||||
"group_id": group.Code,
|
"group_id": converter(group.Code),
|
||||||
"group_name": group.Name,
|
"group_name": group.Name,
|
||||||
"group_create_time": group.GroupCreateTime,
|
"group_create_time": group.GroupCreateTime,
|
||||||
"group_level": group.GroupLevel,
|
"group_level": group.GroupLevel,
|
||||||
@ -693,7 +693,7 @@ func (bot *CQBot) CQGetWordSlices(content string) global.MSG {
|
|||||||
|
|
||||||
// CQSendMessage 发送消息
|
// CQSendMessage 发送消息
|
||||||
//
|
//
|
||||||
// @route(send_msg)
|
// @route11(send_msg)
|
||||||
// @rename(m->message)
|
// @rename(m->message)
|
||||||
func (bot *CQBot) CQSendMessage(groupID, userID int64, m gjson.Result, messageType string, autoEscape bool) global.MSG {
|
func (bot *CQBot) CQSendMessage(groupID, userID int64, m gjson.Result, messageType string, autoEscape bool) global.MSG {
|
||||||
switch {
|
switch {
|
||||||
@ -711,7 +711,7 @@ func (bot *CQBot) CQSendMessage(groupID, userID int64, m gjson.Result, messageTy
|
|||||||
|
|
||||||
// CQSendForwardMessage 发送合并转发消息
|
// CQSendForwardMessage 发送合并转发消息
|
||||||
//
|
//
|
||||||
// @route(send_forward_msg)
|
// @route11(send_forward_msg)
|
||||||
// @rename(m->messages)
|
// @rename(m->messages)
|
||||||
func (bot *CQBot) CQSendForwardMessage(groupID, userID int64, m gjson.Result, messageType string) global.MSG {
|
func (bot *CQBot) CQSendForwardMessage(groupID, userID int64, m gjson.Result, messageType string) global.MSG {
|
||||||
switch {
|
switch {
|
||||||
@ -730,7 +730,7 @@ func (bot *CQBot) CQSendForwardMessage(groupID, userID int64, m gjson.Result, me
|
|||||||
// CQSendGroupMessage 发送群消息
|
// CQSendGroupMessage 发送群消息
|
||||||
//
|
//
|
||||||
// https://git.io/Jtz1c
|
// https://git.io/Jtz1c
|
||||||
// @route(send_group_msg)
|
// @route11(send_group_msg)
|
||||||
// @rename(m->message)
|
// @rename(m->message)
|
||||||
func (bot *CQBot) CQSendGroupMessage(groupID int64, m gjson.Result, autoEscape bool) global.MSG {
|
func (bot *CQBot) CQSendGroupMessage(groupID int64, m gjson.Result, autoEscape bool) global.MSG {
|
||||||
group := bot.Client.FindGroup(groupID)
|
group := bot.Client.FindGroup(groupID)
|
||||||
@ -962,7 +962,7 @@ func (bot *CQBot) uploadForwardElement(m gjson.Result, target int64, sourceType
|
|||||||
// CQSendGroupForwardMessage 扩展API-发送合并转发(群)
|
// CQSendGroupForwardMessage 扩展API-发送合并转发(群)
|
||||||
//
|
//
|
||||||
// https://docs.go-cqhttp.org/api/#%E5%8F%91%E9%80%81%E5%90%88%E5%B9%B6%E8%BD%AC%E5%8F%91-%E7%BE%A4
|
// https://docs.go-cqhttp.org/api/#%E5%8F%91%E9%80%81%E5%90%88%E5%B9%B6%E8%BD%AC%E5%8F%91-%E7%BE%A4
|
||||||
// @route(send_group_forward_msg)
|
// @route11(send_group_forward_msg)
|
||||||
// @rename(m->messages)
|
// @rename(m->messages)
|
||||||
func (bot *CQBot) CQSendGroupForwardMessage(groupID int64, m gjson.Result) global.MSG {
|
func (bot *CQBot) CQSendGroupForwardMessage(groupID int64, m gjson.Result) global.MSG {
|
||||||
if m.Type != gjson.JSON {
|
if m.Type != gjson.JSON {
|
||||||
@ -989,7 +989,7 @@ func (bot *CQBot) CQSendGroupForwardMessage(groupID int64, m gjson.Result) globa
|
|||||||
// CQSendPrivateForwardMessage 扩展API-发送合并转发(好友)
|
// CQSendPrivateForwardMessage 扩展API-发送合并转发(好友)
|
||||||
//
|
//
|
||||||
// https://docs.go-cqhttp.org/api/#%E5%8F%91%E9%80%81%E5%90%88%E5%B9%B6%E8%BD%AC%E5%8F%91-%E7%BE%A4
|
// https://docs.go-cqhttp.org/api/#%E5%8F%91%E9%80%81%E5%90%88%E5%B9%B6%E8%BD%AC%E5%8F%91-%E7%BE%A4
|
||||||
// @route(send_private_forward_msg)
|
// @route11(send_private_forward_msg)
|
||||||
// @rename(m->messages)
|
// @rename(m->messages)
|
||||||
func (bot *CQBot) CQSendPrivateForwardMessage(userID int64, m gjson.Result) global.MSG {
|
func (bot *CQBot) CQSendPrivateForwardMessage(userID int64, m gjson.Result) global.MSG {
|
||||||
if m.Type != gjson.JSON {
|
if m.Type != gjson.JSON {
|
||||||
@ -1014,7 +1014,7 @@ func (bot *CQBot) CQSendPrivateForwardMessage(userID int64, m gjson.Result) glob
|
|||||||
// CQSendPrivateMessage 发送私聊消息
|
// CQSendPrivateMessage 发送私聊消息
|
||||||
//
|
//
|
||||||
// https://git.io/Jtz1l
|
// https://git.io/Jtz1l
|
||||||
// @route(send_private_msg)
|
// @route11(send_private_msg)
|
||||||
// @rename(m->message)
|
// @rename(m->message)
|
||||||
func (bot *CQBot) CQSendPrivateMessage(userID int64, groupID int64, m gjson.Result, autoEscape bool) global.MSG {
|
func (bot *CQBot) CQSendPrivateMessage(userID int64, groupID int64, m gjson.Result, autoEscape bool) global.MSG {
|
||||||
var elem []message.IMessageElement
|
var elem []message.IMessageElement
|
||||||
@ -1107,12 +1107,12 @@ func (bot *CQBot) CQSetGroupMemo(groupID int64, msg, img string) global.MSG {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Failed(100, "IMAGE_NOT_FOUND", "图片未找到")
|
return Failed(100, "IMAGE_NOT_FOUND", "图片未找到")
|
||||||
}
|
}
|
||||||
err = bot.Client.AddGroupNoticeWithPic(groupID, msg, data)
|
_, err = bot.Client.AddGroupNoticeWithPic(groupID, msg, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Failed(100, "SEND_NOTICE_ERROR", err.Error())
|
return Failed(100, "SEND_NOTICE_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err := bot.Client.AddGroupNoticeSimple(groupID, msg)
|
_, err := bot.Client.AddGroupNoticeSimple(groupID, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Failed(100, "SEND_NOTICE_ERROR", err.Error())
|
return Failed(100, "SEND_NOTICE_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
@ -1167,7 +1167,7 @@ func (bot *CQBot) CQSetGroupBan(groupID, userID int64, duration uint32) global.M
|
|||||||
if m := g.FindMember(userID); m != nil {
|
if m := g.FindMember(userID); m != nil {
|
||||||
err := m.Mute(duration)
|
err := m.Mute(duration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if duration > 2592000 {
|
if duration >= 2592000 {
|
||||||
return Failed(100, "DURATION_IS_NOT_IN_RANGE", "非法的禁言时长")
|
return Failed(100, "DURATION_IS_NOT_IN_RANGE", "非法的禁言时长")
|
||||||
}
|
}
|
||||||
return Failed(100, "NOT_MANAGEABLE", "机器人权限不足")
|
return Failed(100, "NOT_MANAGEABLE", "机器人权限不足")
|
||||||
@ -1338,6 +1338,19 @@ func (bot *CQBot) CQSetGroupAdmin(groupID, userID int64, enable bool) global.MSG
|
|||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CQSetGroupAnonymous 群组匿名
|
||||||
|
//
|
||||||
|
// https://beautyyu.one
|
||||||
|
// @route(set_group_anonymous)
|
||||||
|
// @default(enable=true)
|
||||||
|
func (bot *CQBot) CQSetGroupAnonymous(groupID int64, enable bool) global.MSG {
|
||||||
|
if g := bot.Client.FindGroup(groupID); g != nil {
|
||||||
|
g.SetAnonymous(enable)
|
||||||
|
return OK(nil)
|
||||||
|
}
|
||||||
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
|
}
|
||||||
|
|
||||||
// CQGetGroupHonorInfo 获取群荣誉信息
|
// CQGetGroupHonorInfo 获取群荣誉信息
|
||||||
//
|
//
|
||||||
// https://git.io/Jtz1H
|
// https://git.io/Jtz1H
|
||||||
@ -1400,7 +1413,8 @@ func (bot *CQBot) CQGetGroupHonorInfo(groupID int64, t string) global.MSG {
|
|||||||
// CQGetStrangerInfo 获取陌生人信息
|
// CQGetStrangerInfo 获取陌生人信息
|
||||||
//
|
//
|
||||||
// https://git.io/Jtz17
|
// https://git.io/Jtz17
|
||||||
// @route(get_stranger_info)
|
// @route11(get_stranger_info)
|
||||||
|
// @route12(get_user_info)
|
||||||
func (bot *CQBot) CQGetStrangerInfo(userID int64) global.MSG {
|
func (bot *CQBot) CQGetStrangerInfo(userID int64) global.MSG {
|
||||||
info, err := bot.Client.GetSummaryInfo(userID)
|
info, err := bot.Client.GetSummaryInfo(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1419,6 +1433,7 @@ func (bot *CQBot) CQGetStrangerInfo(userID int64) global.MSG {
|
|||||||
// unknown = 0x2
|
// unknown = 0x2
|
||||||
return "unknown"
|
return "unknown"
|
||||||
}(),
|
}(),
|
||||||
|
"sign": info.Sign,
|
||||||
"age": info.Age,
|
"age": info.Age,
|
||||||
"level": info.Level,
|
"level": info.Level,
|
||||||
"login_days": info.LoginDays,
|
"login_days": info.LoginDays,
|
||||||
@ -1811,7 +1826,7 @@ func (bot *CQBot) CQGetOnlineClients(noCache bool) global.MSG {
|
|||||||
// CQCanSendImage 检查是否可以发送图片(此处永远返回true)
|
// CQCanSendImage 检查是否可以发送图片(此处永远返回true)
|
||||||
//
|
//
|
||||||
// https://git.io/Jtz1N
|
// https://git.io/Jtz1N
|
||||||
// @route(can_send_image)
|
// @route11(can_send_image)
|
||||||
func (bot *CQBot) CQCanSendImage() global.MSG {
|
func (bot *CQBot) CQCanSendImage() global.MSG {
|
||||||
return OK(global.MSG{"yes": true})
|
return OK(global.MSG{"yes": true})
|
||||||
}
|
}
|
||||||
@ -1819,7 +1834,7 @@ func (bot *CQBot) CQCanSendImage() global.MSG {
|
|||||||
// CQCanSendRecord 检查是否可以发送语音(此处永远返回true)
|
// CQCanSendRecord 检查是否可以发送语音(此处永远返回true)
|
||||||
//
|
//
|
||||||
// https://git.io/Jtz1x
|
// https://git.io/Jtz1x
|
||||||
// @route(can_send_record)
|
// @route11(can_send_record)
|
||||||
func (bot *CQBot) CQCanSendRecord() global.MSG {
|
func (bot *CQBot) CQCanSendRecord() global.MSG {
|
||||||
return OK(global.MSG{"yes": true})
|
return OK(global.MSG{"yes": true})
|
||||||
}
|
}
|
||||||
@ -1887,7 +1902,8 @@ func (bot *CQBot) CQSetGroupAnonymousBan(groupID int64, flag string, duration in
|
|||||||
//
|
//
|
||||||
// https://git.io/JtzMe
|
// https://git.io/JtzMe
|
||||||
// @route(get_status)
|
// @route(get_status)
|
||||||
func (bot *CQBot) CQGetStatus() global.MSG {
|
func (bot *CQBot) CQGetStatus(version uint16) global.MSG {
|
||||||
|
if version == 11 {
|
||||||
return OK(global.MSG{
|
return OK(global.MSG{
|
||||||
"app_initialized": true,
|
"app_initialized": true,
|
||||||
"app_enabled": true,
|
"app_enabled": true,
|
||||||
@ -1898,6 +1914,12 @@ func (bot *CQBot) CQGetStatus() global.MSG {
|
|||||||
"stat": bot.Client.GetStatistics(),
|
"stat": bot.Client.GetStatistics(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
return OK(global.MSG{
|
||||||
|
"online": bot.Client.Online.Load(),
|
||||||
|
"good": bot.Client.Online.Load(),
|
||||||
|
"stat": bot.Client.GetStatistics(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// CQSetEssenceMessage 扩展API-设置精华消息
|
// CQSetEssenceMessage 扩展API-设置精华消息
|
||||||
//
|
//
|
||||||
@ -1973,7 +1995,7 @@ func (bot *CQBot) CQCheckURLSafely(url string) global.MSG {
|
|||||||
// CQGetVersionInfo 获取版本信息
|
// CQGetVersionInfo 获取版本信息
|
||||||
//
|
//
|
||||||
// https://git.io/JtwUs
|
// https://git.io/JtwUs
|
||||||
// @route(get_version_info)
|
// @route11(get_version_info)
|
||||||
func (bot *CQBot) CQGetVersionInfo() global.MSG {
|
func (bot *CQBot) CQGetVersionInfo() global.MSG {
|
||||||
wd, _ := os.Getwd()
|
wd, _ := os.Getwd()
|
||||||
return OK(global.MSG{
|
return OK(global.MSG{
|
||||||
@ -2084,8 +2106,8 @@ func (bot *CQBot) CQReloadEventFilter(file string) global.MSG {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OK 生成成功返回值
|
// OK 生成成功返回值
|
||||||
func OK(data interface{}) global.MSG {
|
func OK(data any) global.MSG {
|
||||||
return global.MSG{"data": data, "retcode": 0, "status": "ok"}
|
return global.MSG{"data": data, "retcode": 0, "status": "ok", "message": ""}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed 生成失败返回值
|
// Failed 生成失败返回值
|
||||||
@ -2097,7 +2119,7 @@ func Failed(code int, msg ...string) global.MSG {
|
|||||||
if len(msg) > 1 {
|
if len(msg) > 1 {
|
||||||
w = msg[1]
|
w = msg[1]
|
||||||
}
|
}
|
||||||
return global.MSG{"data": nil, "retcode": code, "msg": m, "wording": w, "status": "failed"}
|
return global.MSG{"data": nil, "retcode": code, "msg": m, "wording": w, "message": w, "status": "failed"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func limitedString(str string) string {
|
func limitedString(str string) string {
|
||||||
|
32
coolq/api_v12.go
Normal file
32
coolq/api_v12.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package coolq
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
|
"github.com/Mrs4s/go-cqhttp/internal/base"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CQGetVersion 获取版本信息 OneBotV12
|
||||||
|
//
|
||||||
|
// https://git.io/JtwUs
|
||||||
|
// @route12(get_version)
|
||||||
|
func (bot *CQBot) CQGetVersion() global.MSG {
|
||||||
|
return OK(global.MSG{
|
||||||
|
"impl": "go_cqhttp",
|
||||||
|
"platform": "qq",
|
||||||
|
"version": base.Version,
|
||||||
|
"onebot_version": 12,
|
||||||
|
"runtime_version": runtime.Version(),
|
||||||
|
"runtime_os": runtime.GOOS,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CQSendMessageV12 发送消息
|
||||||
|
//
|
||||||
|
// @route12(send_message)
|
||||||
|
// @rename(m->message)
|
||||||
|
func (bot *CQBot) CQSendMessageV12(groupID, userID, detailType string, m gjson.Result) global.MSG {
|
||||||
|
return OK(nil)
|
||||||
|
}
|
19
coolq/bot.go
19
coolq/bot.go
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image/png"
|
||||||
"os"
|
"os"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
@ -19,6 +20,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/segmentio/asm/base64"
|
"github.com/segmentio/asm/base64"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/image/webp"
|
||||||
|
|
||||||
"github.com/Mrs4s/go-cqhttp/db"
|
"github.com/Mrs4s/go-cqhttp/db"
|
||||||
"github.com/Mrs4s/go-cqhttp/global"
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
@ -112,7 +114,7 @@ func NewQQBot(cli *client.QQClient) *CQBot {
|
|||||||
for {
|
for {
|
||||||
<-t.C
|
<-t.C
|
||||||
bot.dispatchEvent("meta_event/heartbeat", global.MSG{
|
bot.dispatchEvent("meta_event/heartbeat", global.MSG{
|
||||||
"status": bot.CQGetStatus()["data"],
|
"status": bot.CQGetStatus(11)["data"],
|
||||||
"interval": base.HeartbeatInterval.Milliseconds(),
|
"interval": base.HeartbeatInterval.Milliseconds(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -153,9 +155,22 @@ func (bot *CQBot) uploadLocalImage(target message.Source, img *LocalImageElement
|
|||||||
defer func() { _ = f.Close() }()
|
defer func() { _ = f.Close() }()
|
||||||
img.Stream = f
|
img.Stream = f
|
||||||
}
|
}
|
||||||
if mt, ok := mime.CheckImage(img.Stream); !ok {
|
mt, ok := mime.CheckImage(img.Stream)
|
||||||
|
if !ok {
|
||||||
return nil, errors.New("image type error: " + mt)
|
return nil, errors.New("image type error: " + mt)
|
||||||
}
|
}
|
||||||
|
if mt == "image/webp" && base.ConvertWebpImage {
|
||||||
|
img0, err := webp.Decode(img.Stream)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "decode webp error")
|
||||||
|
}
|
||||||
|
stream := bytes.NewBuffer(nil)
|
||||||
|
err = png.Encode(stream, img0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "encode png error")
|
||||||
|
}
|
||||||
|
img.Stream = bytes.NewReader(stream.Bytes())
|
||||||
|
}
|
||||||
i, err := bot.Client.UploadImage(target, img.Stream, 4)
|
i, err := bot.Client.UploadImage(target, img.Stream, 4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
package coolq
|
package coolq
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/topic"
|
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/client"
|
"github.com/Mrs4s/MiraiGo/client"
|
||||||
"github.com/Mrs4s/MiraiGo/message"
|
"github.com/Mrs4s/MiraiGo/message"
|
||||||
|
"github.com/Mrs4s/MiraiGo/topic"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/Mrs4s/go-cqhttp/global"
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type IDConverter func(id any) any
|
||||||
|
|
||||||
func convertGroupMemberInfo(groupID int64, m *client.GroupMemberInfo) global.MSG {
|
func convertGroupMemberInfo(groupID int64, m *client.GroupMemberInfo) global.MSG {
|
||||||
sex := "unknown"
|
sex := "unknown"
|
||||||
if m.Gender == 1 { // unknown = 0xff
|
if m.Gender == 1 { // unknown = 0xff
|
||||||
@ -221,3 +223,10 @@ func toStringMessage(m []message.IMessageElement, source message.Source) string
|
|||||||
func fU64(v uint64) string {
|
func fU64(v uint64) string {
|
||||||
return strconv.FormatUint(v, 10)
|
return strconv.FormatUint(v, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ConvertIDWithVersion(v any, version uint16) any {
|
||||||
|
if version == 12 {
|
||||||
|
return fmt.Sprint(v)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
@ -282,6 +282,18 @@ func toElements(e []message.IMessageElement, source message.Source) (r []cqcode.
|
|||||||
{K: "type", V: "sticker"},
|
{K: "type", V: "sticker"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
case *LocalImageElement:
|
||||||
|
data := pairs{
|
||||||
|
{K: "file", V: o.File},
|
||||||
|
{K: "url", V: o.URL},
|
||||||
|
}
|
||||||
|
if o.Flash {
|
||||||
|
data = append(data, pair{K: "type", V: "flash"})
|
||||||
|
}
|
||||||
|
m = cqcode.Element{
|
||||||
|
Type: "image",
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -807,7 +819,7 @@ func (bot *CQBot) ConvertContentMessage(content []global.MSG, sourceType message
|
|||||||
// 返回 interface{} 存在三种类型
|
// 返回 interface{} 存在三种类型
|
||||||
//
|
//
|
||||||
// message.IMessageElement []message.IMessageElement nil
|
// message.IMessageElement []message.IMessageElement nil
|
||||||
func (bot *CQBot) ToElement(t string, d map[string]string, sourceType message.SourceType) (m interface{}, err error) {
|
func (bot *CQBot) ToElement(t string, d map[string]string, sourceType message.SourceType) (m any, err error) {
|
||||||
switch t {
|
switch t {
|
||||||
case "text":
|
case "text":
|
||||||
if base.SplitURL {
|
if base.SplitURL {
|
||||||
@ -864,7 +876,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, sourceType message.So
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &message.VoiceElement{Data: base.ResampleSilk(data)}, nil
|
return &message.VoiceElement{Data: base.ResampleSilk(data)}, nil
|
||||||
case "record":
|
case "record", "audio":
|
||||||
f := d["file"]
|
f := d["file"]
|
||||||
data, err := global.FindFile(f, d["cache"], global.VoicePath)
|
data, err := global.FindFile(f, d["cache"], global.VoicePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -890,7 +902,10 @@ func (bot *CQBot) ToElement(t string, d map[string]string, sourceType message.So
|
|||||||
return &message.AnimatedSticker{ID: int32(id)}, nil
|
return &message.AnimatedSticker{ID: int32(id)}, nil
|
||||||
}
|
}
|
||||||
return message.NewFace(int32(id)), nil
|
return message.NewFace(int32(id)), nil
|
||||||
case "at":
|
case "mention_all":
|
||||||
|
d["qq"] = "all"
|
||||||
|
fallthrough
|
||||||
|
case "at", "mention":
|
||||||
qq := d["qq"]
|
qq := d["qq"]
|
||||||
if qq == "all" {
|
if qq == "all" {
|
||||||
return message.AtAll(), nil
|
return message.AtAll(), nil
|
||||||
|
32
coolq/cqcode/all_test.go
Normal file
32
coolq/cqcode/all_test.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package cqcode
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func jsonMarshal(s string) string {
|
||||||
|
b, err := json.Marshal(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_quote(t *testing.T) {
|
||||||
|
testcase := []string{
|
||||||
|
"\u0005", // issue 1773
|
||||||
|
"\v",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, input := range testcase {
|
||||||
|
var b bytes.Buffer
|
||||||
|
writeQuote(&b, input)
|
||||||
|
got := b.String()
|
||||||
|
expected := jsonMarshal(input)
|
||||||
|
if got != expected {
|
||||||
|
t.Errorf("want %v but got %v", expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,9 @@ package cqcode
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
"github.com/Mrs4s/go-cqhttp/global"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Element single message
|
// Element single message
|
||||||
@ -60,8 +60,95 @@ func (e *Element) MarshalJSON() ([]byte, error) {
|
|||||||
buf.WriteByte('"')
|
buf.WriteByte('"')
|
||||||
buf.WriteString(data.K)
|
buf.WriteString(data.K)
|
||||||
buf.WriteString(`":`)
|
buf.WriteString(`":`)
|
||||||
buf.WriteString(global.Quote(data.V))
|
writeQuote(buf, data.V)
|
||||||
}
|
}
|
||||||
buf.WriteString(`}}`)
|
buf.WriteString(`}}`)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hex = "0123456789abcdef"
|
||||||
|
|
||||||
|
func writeQuote(b *bytes.Buffer, s string) {
|
||||||
|
i, j := 0, 0
|
||||||
|
|
||||||
|
b.WriteByte('"')
|
||||||
|
for j < len(s) {
|
||||||
|
c := s[j]
|
||||||
|
|
||||||
|
if c >= 0x20 && c <= 0x7f && c != '\\' && c != '"' {
|
||||||
|
// fast path: most of the time, printable ascii characters are used
|
||||||
|
j++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c {
|
||||||
|
case '\\', '"', '\n', '\r', '\t':
|
||||||
|
b.WriteString(s[i:j])
|
||||||
|
b.WriteByte('\\')
|
||||||
|
switch c {
|
||||||
|
case '\n':
|
||||||
|
c = 'n'
|
||||||
|
case '\r':
|
||||||
|
c = 'r'
|
||||||
|
case '\t':
|
||||||
|
c = 't'
|
||||||
|
}
|
||||||
|
b.WriteByte(c)
|
||||||
|
j++
|
||||||
|
i = j
|
||||||
|
continue
|
||||||
|
|
||||||
|
case '<', '>', '&':
|
||||||
|
b.WriteString(s[i:j])
|
||||||
|
b.WriteString(`\u00`)
|
||||||
|
b.WriteByte(hex[c>>4])
|
||||||
|
b.WriteByte(hex[c&0xF])
|
||||||
|
j++
|
||||||
|
i = j
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// This encodes bytes < 0x20 except for \t, \n and \r.
|
||||||
|
if c < 0x20 {
|
||||||
|
b.WriteString(s[i:j])
|
||||||
|
b.WriteString(`\u00`)
|
||||||
|
b.WriteByte(hex[c>>4])
|
||||||
|
b.WriteByte(hex[c&0xF])
|
||||||
|
j++
|
||||||
|
i = j
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r, size := utf8.DecodeRuneInString(s[j:])
|
||||||
|
|
||||||
|
if r == utf8.RuneError && size == 1 {
|
||||||
|
b.WriteString(s[i:j])
|
||||||
|
b.WriteString(`\ufffd`)
|
||||||
|
j += size
|
||||||
|
i = j
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch r {
|
||||||
|
case '\u2028', '\u2029':
|
||||||
|
// U+2028 is LINE SEPARATOR.
|
||||||
|
// U+2029 is PARAGRAPH SEPARATOR.
|
||||||
|
// They are both technically valid characters in JSON strings,
|
||||||
|
// but don't work in JSONP, which has to be evaluated as JavaScript,
|
||||||
|
// and can lead to security holes there. It is valid JSON to
|
||||||
|
// escape them, so we do so unconditionally.
|
||||||
|
// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
|
||||||
|
b.WriteString(s[i:j])
|
||||||
|
b.WriteString(`\u202`)
|
||||||
|
b.WriteByte(hex[r&0xF])
|
||||||
|
j += size
|
||||||
|
i = j
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
j += size
|
||||||
|
}
|
||||||
|
|
||||||
|
b.WriteString(s[i:])
|
||||||
|
b.WriteByte('"')
|
||||||
|
}
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ToFormattedMessage 将给定[]message.IMessageElement转换为通过coolq.SetMessageFormat所定义的消息上报格式
|
// ToFormattedMessage 将给定[]message.IMessageElement转换为通过coolq.SetMessageFormat所定义的消息上报格式
|
||||||
func ToFormattedMessage(e []message.IMessageElement, source message.Source) (r interface{}) {
|
func ToFormattedMessage(e []message.IMessageElement, source message.Source) (r any) {
|
||||||
if base.PostFormat == "string" {
|
if base.PostFormat == "string" {
|
||||||
r = toStringMessage(e, source)
|
r = toStringMessage(e, source)
|
||||||
} else if base.PostFormat == "array" {
|
} else if base.PostFormat == "array" {
|
||||||
@ -144,7 +144,10 @@ func (bot *CQBot) tempMessageEvent(c *client.QQClient, e *client.TempMessageEven
|
|||||||
PrimaryID: e.Session.Sender,
|
PrimaryID: e.Session.Sender,
|
||||||
}
|
}
|
||||||
cqm := toStringMessage(m.Elements, source)
|
cqm := toStringMessage(m.Elements, source)
|
||||||
|
if base.AllowTempSession {
|
||||||
bot.tempSessionCache.Store(m.Sender.Uin, e.Session)
|
bot.tempSessionCache.Store(m.Sender.Uin, e.Session)
|
||||||
|
}
|
||||||
|
|
||||||
id := m.Id
|
id := m.Id
|
||||||
// todo(Mrs4s)
|
// todo(Mrs4s)
|
||||||
// if bot.db != nil { // nolint
|
// if bot.db != nil { // nolint
|
||||||
|
@ -84,7 +84,7 @@ func (r *reader) arrayMsg() []global.MSG {
|
|||||||
return msgs
|
return msgs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *reader) obj() interface{} {
|
func (r *reader) obj() any {
|
||||||
switch coder := r.coder(); coder {
|
switch coder := r.coder(); coder {
|
||||||
case coderNil:
|
case coderNil:
|
||||||
return nil
|
return nil
|
||||||
|
@ -96,7 +96,7 @@ func (w *writer) arrayMsg(a []global.MSG) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *writer) obj(o interface{}) {
|
func (w *writer) obj(o any) {
|
||||||
switch x := o.(type) {
|
switch x := o.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
w.nil()
|
w.nil()
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
注意: 与客户端建立连接的握手事件**不会**经过事件过滤器
|
注意: 与客户端建立连接的握手事件**不会**经过事件过滤器
|
||||||
|
|
||||||
|
> 注意, 最新文档已经移动到 [go-cqhttp-docs](https://github.com/ishkong/go-cqhttp-docs), 当前文档只做兼容性保留, 所以内容可能有不足.
|
||||||
|
|
||||||
## 示例
|
## 示例
|
||||||
|
|
||||||
这节首先给出一些示例,演示过滤器的基本用法,下一节将给出具体语法说明。
|
这节首先给出一些示例,演示过滤器的基本用法,下一节将给出具体语法说明。
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# 常见问题
|
# 常见问题
|
||||||
|
|
||||||
|
> 注意, 最新文档已经移动到 [go-cqhttp-docs](https://github.com/ishkong/go-cqhttp-docs), 当前文档只做兼容性保留, 所以内容可能有不足.
|
||||||
|
|
||||||
### Q: 为什么挂一段时间后就会出现 `消息发送失败,账号可能被风控`?
|
### Q: 为什么挂一段时间后就会出现 `消息发送失败,账号可能被风控`?
|
||||||
|
|
||||||
### A: 如果你刚开始使用 go-cqhttp 建议挂机3-7天,即可解除风控
|
### A: 如果你刚开始使用 go-cqhttp 建议挂机3-7天,即可解除风控
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# 配置
|
# 配置
|
||||||
|
|
||||||
|
> 注意, 最新文档已经移动到 [go-cqhttp-docs](https://github.com/ishkong/go-cqhttp-docs), 当前文档只做兼容性保留, 所以内容可能有不足.
|
||||||
|
|
||||||
go-cqhttp 包含 `config.yml` 和 `device.json` 两个配置文件, 其中 `config.yml` 为运行配置 `device.json` 为虚拟设备信息.
|
go-cqhttp 包含 `config.yml` 和 `device.json` 两个配置文件, 其中 `config.yml` 为运行配置 `device.json` 为虚拟设备信息.
|
||||||
|
|
||||||
## 配置信息
|
## 配置信息
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
# 拓展API
|
# 拓展API
|
||||||
|
|
||||||
由于部分 api 原版 CQHTTP 并未实现,go-cqhttp 修改并增加了一些拓展 api .
|
由于部分 api 原版 CQHTTP 并未实现,go-cqhttp 修改并增加了一些拓展 api
|
||||||
|
|
||||||
|
> 注意, 最新文档已经移动到 [go-cqhttp-docs](https://github.com/ishkong/go-cqhttp-docs), 当前文档只做兼容性保留, 所以内容可能有不足..
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>目录</summary>
|
<summary>目录</summary>
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
QQ频道相关功能的事件以及API
|
QQ频道相关功能的事件以及API
|
||||||
|
|
||||||
|
> 注意, 最新文档已经移动到 [go-cqhttp-docs](https://github.com/ishkong/go-cqhttp-docs), 当前文档只做兼容性保留, 所以内容可能有不足.
|
||||||
|
|
||||||
## 命名说明
|
## 命名说明
|
||||||
|
|
||||||
API以及字段相关命名均为参考QQ官方命名或相似产品命名规则, 由于QQ频道的账号系统独立于QQ本体, 所以各个 `ID` 并不能和QQ通用.也无法通过 `tiny_id` 获取到 `QQ号`
|
API以及字段相关命名均为参考QQ官方命名或相似产品命名规则, 由于QQ频道的账号系统独立于QQ本体, 所以各个 `ID` 并不能和QQ通用.也无法通过 `tiny_id` 获取到 `QQ号`
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
欢迎来到 go-cqhttp 文档 目前还在咕
|
欢迎来到 go-cqhttp 文档 目前还在咕
|
||||||
|
|
||||||
|
> 注意, 最新文档已经移动到 [go-cqhttp-docs](https://github.com/ishkong/go-cqhttp-docs), 当前文档只做兼容性保留, 所以内容可能有不足.
|
||||||
|
|
||||||
# 基础教程
|
# 基础教程
|
||||||
## 下载
|
## 下载
|
||||||
从[release](https://github.com/Mrs4s/go-cqhttp/releases)界面下载最新版本的go-cqhttp
|
从[release](https://github.com/Mrs4s/go-cqhttp/releases)界面下载最新版本的go-cqhttp
|
||||||
|
@ -88,6 +88,7 @@ func FindFile(file, cache, p string) (data []byte, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return os.ReadFile(cacheFile)
|
||||||
case strings.HasPrefix(file, "base64"):
|
case strings.HasPrefix(file, "base64"):
|
||||||
data, err = base64.StdEncoding.DecodeString(strings.TrimPrefix(file, "base64://"))
|
data, err = base64.StdEncoding.DecodeString(strings.TrimPrefix(file, "base64://"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -108,7 +108,7 @@ func (hook *LocalHook) SetPath(path string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewLocalHook 初始化本地日志钩子实现
|
// NewLocalHook 初始化本地日志钩子实现
|
||||||
func NewLocalHook(args interface{}, consoleFormatter, fileFormatter logrus.Formatter, levels ...logrus.Level) *LocalHook {
|
func NewLocalHook(args any, consoleFormatter, fileFormatter logrus.Formatter, levels ...logrus.Level) *LocalHook {
|
||||||
hook := &LocalHook{
|
hook := &LocalHook{
|
||||||
lock: new(sync.Mutex),
|
lock: new(sync.Mutex),
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// MSG 消息Map
|
// MSG 消息Map
|
||||||
type MSG = map[string]interface{}
|
type MSG = map[string]any
|
||||||
|
|
||||||
// VersionNameCompare 检查版本名是否需要更新, 仅适用于 go-cqhttp 的版本命名规则
|
// VersionNameCompare 检查版本名是否需要更新, 仅适用于 go-cqhttp 的版本命名规则
|
||||||
//
|
//
|
||||||
|
146
global/quote.go
146
global/quote.go
@ -1,146 +0,0 @@
|
|||||||
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,
|
|
||||||
}
|
|
11
go.mod
11
go.mod
@ -1,11 +1,11 @@
|
|||||||
module github.com/Mrs4s/go-cqhttp
|
module github.com/Mrs4s/go-cqhttp
|
||||||
|
|
||||||
go 1.19
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/FloatTech/sqlite v1.5.7
|
github.com/FloatTech/sqlite v1.5.7
|
||||||
github.com/Microsoft/go-winio v0.6.0
|
github.com/Microsoft/go-winio v0.6.0
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20221202060717-4658474c60dd
|
github.com/Mrs4s/MiraiGo v0.0.0-20230213132655-3ff1fee1b645
|
||||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
|
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
|
||||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc
|
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc
|
||||||
github.com/fumiama/go-base16384 v1.6.1
|
github.com/fumiama/go-base16384 v1.6.1
|
||||||
@ -21,16 +21,17 @@ require (
|
|||||||
github.com/wdvxdr1123/go-silk v0.0.0-20210316130616-d47b553def60
|
github.com/wdvxdr1123/go-silk v0.0.0-20210316130616-d47b553def60
|
||||||
go.mongodb.org/mongo-driver v1.11.0
|
go.mongodb.org/mongo-driver v1.11.0
|
||||||
golang.org/x/crypto v0.3.0
|
golang.org/x/crypto v0.3.0
|
||||||
|
golang.org/x/image v0.3.0
|
||||||
golang.org/x/sys v0.2.0
|
golang.org/x/sys v0.2.0
|
||||||
golang.org/x/term v0.2.0
|
golang.org/x/term v0.2.0
|
||||||
golang.org/x/time v0.2.0
|
golang.org/x/time v0.2.0
|
||||||
gopkg.ilharper.com/x/isatty v1.1.0
|
gopkg.ilharper.com/x/isatty v1.1.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b // indirect
|
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b // indirect
|
||||||
github.com/RomiChan/protobuf v0.0.0-20220624030127-3310cba9dbc0 // indirect
|
github.com/RomiChan/protobuf v0.1.1-0.20230204044148-2ed269a2e54d // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/fumiama/imgsz v0.0.2 // indirect
|
github.com/fumiama/imgsz v0.0.2 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
@ -52,7 +53,7 @@ require (
|
|||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
||||||
golang.org/x/text v0.4.0 // indirect
|
golang.org/x/text v0.6.0 // indirect
|
||||||
golang.org/x/tools v0.1.12 // indirect
|
golang.org/x/tools v0.1.12 // indirect
|
||||||
lukechampine.com/uint128 v1.2.0 // indirect
|
lukechampine.com/uint128 v1.2.0 // indirect
|
||||||
modernc.org/cc/v3 v3.40.0 // indirect
|
modernc.org/cc/v3 v3.40.0 // indirect
|
||||||
|
33
go.sum
33
go.sum
@ -4,10 +4,10 @@ github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJG
|
|||||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs=
|
||||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20221202060717-4658474c60dd h1:rzAbPc++5CJ1VZDjq/eORXOWMMGsDN3DMAPMXfI7Fvs=
|
github.com/Mrs4s/MiraiGo v0.0.0-20230213132655-3ff1fee1b645 h1:KHWuWmhF2nacb2mKqA3OJorerCEo9n6BNizMuBACa38=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20221202060717-4658474c60dd/go.mod h1:lecSP26qedhinCceWn1x02dLDxGotH5nTFlpIMilmVM=
|
github.com/Mrs4s/MiraiGo v0.0.0-20230213132655-3ff1fee1b645/go.mod h1:mU3fBFU+7eO0kaGes7YRKtzIDtwIU84nSSwTV7NK2b0=
|
||||||
github.com/RomiChan/protobuf v0.0.0-20220624030127-3310cba9dbc0 h1:GEwcB4dL9vc4veW1fLNt0Fby3wspVflAn5v9/HbUwDM=
|
github.com/RomiChan/protobuf v0.1.1-0.20230204044148-2ed269a2e54d h1:/Xuj3fIiMY2ls1TwvPKmaqQrtJsPY+c9s+0lOScVHd8=
|
||||||
github.com/RomiChan/protobuf v0.0.0-20220624030127-3310cba9dbc0/go.mod h1:2Ie+hdBFQpQFDHfeklgxoFmQRCE7O+KwFpISeXq7OwA=
|
github.com/RomiChan/protobuf v0.1.1-0.20230204044148-2ed269a2e54d/go.mod h1:2Ie+hdBFQpQFDHfeklgxoFmQRCE7O+KwFpISeXq7OwA=
|
||||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA=
|
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA=
|
||||||
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
|
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w=
|
||||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc h1:AAx50/fb/xS4lvsdQg+bFbGvqSDhyV1MF+p2PLCamZ0=
|
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc h1:AAx50/fb/xS4lvsdQg+bFbGvqSDhyV1MF+p2PLCamZ0=
|
||||||
@ -52,8 +52,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
|
|||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
@ -86,7 +86,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
|
||||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
@ -120,23 +119,32 @@ github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCO
|
|||||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE=
|
go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE=
|
||||||
go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
|
go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
|
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
|
||||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
|
golang.org/x/image v0.3.0 h1:HTDXbdK9bjfSWkPzDJIw89W8CAtfFGduujWs33NLLsg=
|
||||||
|
golang.org/x/image v0.3.0/go.mod h1:fXd9211C/0VTlYuAcOhW8dY/RtEJqODXOWBDpmYBf+A=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -154,11 +162,14 @@ golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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=
|
||||||
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -166,13 +177,15 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
|
golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
|
||||||
golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -182,8 +195,8 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
|
|||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
gopkg.ilharper.com/x/isatty v1.1.0 h1:slOK6hP9/y9mJWyCInMwnT432NExfWyYV2SsebdYOCY=
|
gopkg.ilharper.com/x/isatty v1.1.1 h1:RAg32Pxq/nIK4AVtdm9RBqxsxZZX1uRKRSS21E5SHMk=
|
||||||
gopkg.ilharper.com/x/isatty v1.1.0/go.mod h1:ofpv77Td5qQO6R1dmDd3oNt8TZdRo+l5gYAMxopRyS0=
|
gopkg.ilharper.com/x/isatty v1.1.1/go.mod h1:ofpv77Td5qQO6R1dmDd3oNt8TZdRo+l5gYAMxopRyS0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
@ -30,6 +30,7 @@ var (
|
|||||||
SplitURL bool // 是否分割URL
|
SplitURL bool // 是否分割URL
|
||||||
ForceFragmented bool // 是否启用强制分片
|
ForceFragmented bool // 是否启用强制分片
|
||||||
SkipMimeScan bool // 是否跳过Mime扫描
|
SkipMimeScan bool // 是否跳过Mime扫描
|
||||||
|
ConvertWebpImage bool // 是否转换Webp图片
|
||||||
ReportSelfMessage bool // 是否上报自身消息
|
ReportSelfMessage bool // 是否上报自身消息
|
||||||
UseSSOAddress bool // 是否使用服务器下发的新地址进行重连
|
UseSSOAddress bool // 是否使用服务器下发的新地址进行重连
|
||||||
LogForceNew bool // 是否在每次启动时强制创建全新的文件储存日志
|
LogForceNew bool // 是否在每次启动时强制创建全新的文件储存日志
|
||||||
@ -79,6 +80,7 @@ func Init() {
|
|||||||
ExtraReplyData = conf.Message.ExtraReplyData
|
ExtraReplyData = conf.Message.ExtraReplyData
|
||||||
ForceFragmented = conf.Message.ForceFragment
|
ForceFragmented = conf.Message.ForceFragment
|
||||||
SkipMimeScan = conf.Message.SkipMimeScan
|
SkipMimeScan = conf.Message.SkipMimeScan
|
||||||
|
ConvertWebpImage = conf.Message.ConvertWebpImage
|
||||||
ReportSelfMessage = conf.Message.ReportSelfMessage
|
ReportSelfMessage = conf.Message.ReportSelfMessage
|
||||||
UseSSOAddress = conf.Account.UseSSOAddress
|
UseSSOAddress = conf.Account.UseSSOAddress
|
||||||
AllowTempSession = conf.Account.AllowTempSession
|
AllowTempSession = conf.Account.AllowTempSession
|
||||||
|
@ -111,6 +111,7 @@ func writeToFile(reader io.ReadCloser, path string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer func() { _ = file.Close() }()
|
||||||
_, err = file.ReadFrom(reader)
|
_, err = file.ReadFrom(reader)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ import (
|
|||||||
// type gjson.True or gjson.False
|
// type gjson.True or gjson.False
|
||||||
//
|
//
|
||||||
// type string "true","yes","1" or "false","no","0" (case insensitive)
|
// type string "true","yes","1" or "false","no","0" (case insensitive)
|
||||||
func EnsureBool(p interface{}, defaultVal bool) bool {
|
func EnsureBool(p any, defaultVal bool) bool {
|
||||||
var str string
|
var str string
|
||||||
if b, ok := p.(bool); ok {
|
if b, ok := p.(bool); ok {
|
||||||
return b
|
return b
|
||||||
|
@ -7,10 +7,78 @@ import (
|
|||||||
"github.com/Mrs4s/go-cqhttp/global"
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Caller) call(action string, p Getter) global.MSG {
|
func (c *Caller) call(action string, version uint16, p Getter) global.MSG {
|
||||||
|
var converter coolq.IDConverter = func(id any) any {
|
||||||
|
return coolq.ConvertIDWithVersion(id, version)
|
||||||
|
}
|
||||||
|
if version == 12 {
|
||||||
|
if action == "get_supported_actions" {
|
||||||
|
return coolq.OK([]string{".get_word_slices", ".handle_quick_operation", ".ocr_image", "ocr_image", "_get_group_notice", "_get_model_show", "_send_group_notice", "_set_model_show", "check_url_safely", "create_group_file_folder", "create_guild_role", "delete_essence_msg", "delete_friend", "delete_group_file", "delete_group_folder", "delete_guild_role", "delete_msg", "delete_unidirectional_friend", "download_file", "get_essence_msg_list", "get_forward_msg", "get_friend_list", "get_group_at_all_remain", "get_group_file_system_info", "get_group_file_url", "get_group_files_by_folder", "get_group_honor_info", "get_group_info", "get_group_list", "get_group_member_info", "get_group_member_list", "get_group_msg_history", "get_group_root_files", "get_group_system_msg", "get_guild_channel_list", "get_guild_list", "get_guild_member_list", "get_guild_member_profile", "get_guild_meta_by_guest", "get_guild_msg", "get_guild_roles", "get_guild_service_profile", "get_image", "get_self_info", "get_msg", "get_online_clients", "get_status", "get_user_info", "get_topic_channel_feeds", "get_unidirectional_friend_list", "get_version", "mark_msg_as_read", "qidian_get_account_info", "reload_event_filter", "send_group_sign", "send_guild_channel_msg", "send_message", "set_essence_msg", "set_friend_add_request", "set_group_add_request", "set_group_admin", "set_group_anonymous_ban", "set_group_ban", "set_group_card", "set_group_kick", "set_group_leave", "set_group_name", "set_group_portrait", "set_group_special_title", "set_group_whole_ban", "set_guild_member_role", "set_qq_profile", "update_guild_role", "upload_group_file"})
|
||||||
|
}
|
||||||
|
switch action {
|
||||||
|
case "get_self_info":
|
||||||
|
return c.bot.CQGetLoginInfo()
|
||||||
|
case "get_user_info":
|
||||||
|
p0 := p.Get("user_id").Int()
|
||||||
|
return c.bot.CQGetStrangerInfo(p0)
|
||||||
|
case "get_version":
|
||||||
|
return c.bot.CQGetVersion()
|
||||||
|
case "send_message":
|
||||||
|
p0 := p.Get("group_id").String()
|
||||||
|
p1 := p.Get("user_id").String()
|
||||||
|
p2 := p.Get("detail_type").String()
|
||||||
|
p3 := p.Get("message")
|
||||||
|
return c.bot.CQSendMessageV12(p0, p1, p2, p3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if version == 11 {
|
||||||
|
switch action {
|
||||||
|
case "can_send_image":
|
||||||
|
return c.bot.CQCanSendImage()
|
||||||
|
case "can_send_record":
|
||||||
|
return c.bot.CQCanSendRecord()
|
||||||
|
case "get_login_info":
|
||||||
|
return c.bot.CQGetLoginInfo()
|
||||||
|
case "get_stranger_info":
|
||||||
|
p0 := p.Get("user_id").Int()
|
||||||
|
return c.bot.CQGetStrangerInfo(p0)
|
||||||
|
case "get_version_info":
|
||||||
|
return c.bot.CQGetVersionInfo()
|
||||||
|
case "send_forward_msg":
|
||||||
|
p0 := p.Get("group_id").Int()
|
||||||
|
p1 := p.Get("user_id").Int()
|
||||||
|
p2 := p.Get("messages")
|
||||||
|
p3 := p.Get("message_type").String()
|
||||||
|
return c.bot.CQSendForwardMessage(p0, p1, p2, p3)
|
||||||
|
case "send_group_forward_msg":
|
||||||
|
p0 := p.Get("group_id").Int()
|
||||||
|
p1 := p.Get("messages")
|
||||||
|
return c.bot.CQSendGroupForwardMessage(p0, p1)
|
||||||
|
case "send_group_msg":
|
||||||
|
p0 := p.Get("group_id").Int()
|
||||||
|
p1 := p.Get("message")
|
||||||
|
p2 := p.Get("auto_escape").Bool()
|
||||||
|
return c.bot.CQSendGroupMessage(p0, p1, p2)
|
||||||
|
case "send_msg":
|
||||||
|
p0 := p.Get("group_id").Int()
|
||||||
|
p1 := p.Get("user_id").Int()
|
||||||
|
p2 := p.Get("message")
|
||||||
|
p3 := p.Get("message_type").String()
|
||||||
|
p4 := p.Get("auto_escape").Bool()
|
||||||
|
return c.bot.CQSendMessage(p0, p1, p2, p3, p4)
|
||||||
|
case "send_private_forward_msg":
|
||||||
|
p0 := p.Get("user_id").Int()
|
||||||
|
p1 := p.Get("messages")
|
||||||
|
return c.bot.CQSendPrivateForwardMessage(p0, p1)
|
||||||
|
case "send_private_msg":
|
||||||
|
p0 := p.Get("user_id").Int()
|
||||||
|
p1 := p.Get("group_id").Int()
|
||||||
|
p2 := p.Get("message")
|
||||||
|
p3 := p.Get("auto_escape").Bool()
|
||||||
|
return c.bot.CQSendPrivateMessage(p0, p1, p2, p3)
|
||||||
|
}
|
||||||
|
}
|
||||||
switch action {
|
switch action {
|
||||||
default:
|
|
||||||
return coolq.Failed(404, "API_NOT_FOUND", "API不存在")
|
|
||||||
case ".get_word_slices":
|
case ".get_word_slices":
|
||||||
p0 := p.Get("content").String()
|
p0 := p.Get("content").String()
|
||||||
return c.bot.CQGetWordSlices(p0)
|
return c.bot.CQGetWordSlices(p0)
|
||||||
@ -40,10 +108,6 @@ func (c *Caller) call(action string, p Getter) global.MSG {
|
|||||||
p0 := p.Get("model").String()
|
p0 := p.Get("model").String()
|
||||||
p1 := p.Get("model_show").String()
|
p1 := p.Get("model_show").String()
|
||||||
return c.bot.CQSetModelShow(p0, p1)
|
return c.bot.CQSetModelShow(p0, p1)
|
||||||
case "can_send_image":
|
|
||||||
return c.bot.CQCanSendImage()
|
|
||||||
case "can_send_record":
|
|
||||||
return c.bot.CQCanSendRecord()
|
|
||||||
case "check_url_safely":
|
case "check_url_safely":
|
||||||
p0 := p.Get("url").String()
|
p0 := p.Get("url").String()
|
||||||
return c.bot.CQCheckURLSafely(p0)
|
return c.bot.CQCheckURLSafely(p0)
|
||||||
@ -96,7 +160,7 @@ func (c *Caller) call(action string, p Getter) global.MSG {
|
|||||||
p0 := p.Get("[message_id,id].0").String()
|
p0 := p.Get("[message_id,id].0").String()
|
||||||
return c.bot.CQGetForwardMessage(p0)
|
return c.bot.CQGetForwardMessage(p0)
|
||||||
case "get_friend_list":
|
case "get_friend_list":
|
||||||
return c.bot.CQGetFriendList()
|
return c.bot.CQGetFriendList(version)
|
||||||
case "get_group_at_all_remain":
|
case "get_group_at_all_remain":
|
||||||
p0 := p.Get("group_id").Int()
|
p0 := p.Get("group_id").Int()
|
||||||
return c.bot.CQGetAtAllRemain(p0)
|
return c.bot.CQGetAtAllRemain(p0)
|
||||||
@ -119,10 +183,10 @@ func (c *Caller) call(action string, p Getter) global.MSG {
|
|||||||
case "get_group_info":
|
case "get_group_info":
|
||||||
p0 := p.Get("group_id").Int()
|
p0 := p.Get("group_id").Int()
|
||||||
p1 := p.Get("no_cache").Bool()
|
p1 := p.Get("no_cache").Bool()
|
||||||
return c.bot.CQGetGroupInfo(p0, p1)
|
return c.bot.CQGetGroupInfo(p0, p1, converter)
|
||||||
case "get_group_list":
|
case "get_group_list":
|
||||||
p0 := p.Get("no_cache").Bool()
|
p0 := p.Get("no_cache").Bool()
|
||||||
return c.bot.CQGetGroupList(p0)
|
return c.bot.CQGetGroupList(p0, converter)
|
||||||
case "get_group_member_info":
|
case "get_group_member_info":
|
||||||
p0 := p.Get("group_id").Int()
|
p0 := p.Get("group_id").Int()
|
||||||
p1 := p.Get("user_id").Int()
|
p1 := p.Get("user_id").Int()
|
||||||
@ -170,8 +234,6 @@ func (c *Caller) call(action string, p Getter) global.MSG {
|
|||||||
case "get_image":
|
case "get_image":
|
||||||
p0 := p.Get("file").String()
|
p0 := p.Get("file").String()
|
||||||
return c.bot.CQGetImage(p0)
|
return c.bot.CQGetImage(p0)
|
||||||
case "get_login_info":
|
|
||||||
return c.bot.CQGetLoginInfo()
|
|
||||||
case "get_msg":
|
case "get_msg":
|
||||||
p0 := int32(p.Get("message_id").Int())
|
p0 := int32(p.Get("message_id").Int())
|
||||||
return c.bot.CQGetMessage(p0)
|
return c.bot.CQGetMessage(p0)
|
||||||
@ -179,18 +241,13 @@ func (c *Caller) call(action string, p Getter) global.MSG {
|
|||||||
p0 := p.Get("no_cache").Bool()
|
p0 := p.Get("no_cache").Bool()
|
||||||
return c.bot.CQGetOnlineClients(p0)
|
return c.bot.CQGetOnlineClients(p0)
|
||||||
case "get_status":
|
case "get_status":
|
||||||
return c.bot.CQGetStatus()
|
return c.bot.CQGetStatus(version)
|
||||||
case "get_stranger_info":
|
|
||||||
p0 := p.Get("user_id").Int()
|
|
||||||
return c.bot.CQGetStrangerInfo(p0)
|
|
||||||
case "get_topic_channel_feeds":
|
case "get_topic_channel_feeds":
|
||||||
p0 := p.Get("guild_id").Uint()
|
p0 := p.Get("guild_id").Uint()
|
||||||
p1 := p.Get("channel_id").Uint()
|
p1 := p.Get("channel_id").Uint()
|
||||||
return c.bot.CQGetTopicChannelFeeds(p0, p1)
|
return c.bot.CQGetTopicChannelFeeds(p0, p1)
|
||||||
case "get_unidirectional_friend_list":
|
case "get_unidirectional_friend_list":
|
||||||
return c.bot.CQGetUnidirectionalFriendList()
|
return c.bot.CQGetUnidirectionalFriendList()
|
||||||
case "get_version_info":
|
|
||||||
return c.bot.CQGetVersionInfo()
|
|
||||||
case "mark_msg_as_read":
|
case "mark_msg_as_read":
|
||||||
p0 := int32(p.Get("message_id").Int())
|
p0 := int32(p.Get("message_id").Int())
|
||||||
return c.bot.CQMarkMessageAsRead(p0)
|
return c.bot.CQMarkMessageAsRead(p0)
|
||||||
@ -199,21 +256,6 @@ func (c *Caller) call(action string, p Getter) global.MSG {
|
|||||||
case "reload_event_filter":
|
case "reload_event_filter":
|
||||||
p0 := p.Get("file").String()
|
p0 := p.Get("file").String()
|
||||||
return c.bot.CQReloadEventFilter(p0)
|
return c.bot.CQReloadEventFilter(p0)
|
||||||
case "send_forward_msg":
|
|
||||||
p0 := p.Get("group_id").Int()
|
|
||||||
p1 := p.Get("user_id").Int()
|
|
||||||
p2 := p.Get("messages")
|
|
||||||
p3 := p.Get("message_type").String()
|
|
||||||
return c.bot.CQSendForwardMessage(p0, p1, p2, p3)
|
|
||||||
case "send_group_forward_msg":
|
|
||||||
p0 := p.Get("group_id").Int()
|
|
||||||
p1 := p.Get("messages")
|
|
||||||
return c.bot.CQSendGroupForwardMessage(p0, p1)
|
|
||||||
case "send_group_msg":
|
|
||||||
p0 := p.Get("group_id").Int()
|
|
||||||
p1 := p.Get("message")
|
|
||||||
p2 := p.Get("auto_escape").Bool()
|
|
||||||
return c.bot.CQSendGroupMessage(p0, p1, p2)
|
|
||||||
case "send_group_sign":
|
case "send_group_sign":
|
||||||
p0 := p.Get("group_id").Int()
|
p0 := p.Get("group_id").Int()
|
||||||
return c.bot.CQSendGroupSign(p0)
|
return c.bot.CQSendGroupSign(p0)
|
||||||
@ -223,23 +265,6 @@ func (c *Caller) call(action string, p Getter) global.MSG {
|
|||||||
p2 := p.Get("message")
|
p2 := p.Get("message")
|
||||||
p3 := p.Get("auto_escape").Bool()
|
p3 := p.Get("auto_escape").Bool()
|
||||||
return c.bot.CQSendGuildChannelMessage(p0, p1, p2, p3)
|
return c.bot.CQSendGuildChannelMessage(p0, p1, p2, p3)
|
||||||
case "send_msg":
|
|
||||||
p0 := p.Get("group_id").Int()
|
|
||||||
p1 := p.Get("user_id").Int()
|
|
||||||
p2 := p.Get("message")
|
|
||||||
p3 := p.Get("message_type").String()
|
|
||||||
p4 := p.Get("auto_escape").Bool()
|
|
||||||
return c.bot.CQSendMessage(p0, p1, p2, p3, p4)
|
|
||||||
case "send_private_forward_msg":
|
|
||||||
p0 := p.Get("user_id").Int()
|
|
||||||
p1 := p.Get("messages")
|
|
||||||
return c.bot.CQSendPrivateForwardMessage(p0, p1)
|
|
||||||
case "send_private_msg":
|
|
||||||
p0 := p.Get("user_id").Int()
|
|
||||||
p1 := p.Get("group_id").Int()
|
|
||||||
p2 := p.Get("message")
|
|
||||||
p3 := p.Get("auto_escape").Bool()
|
|
||||||
return c.bot.CQSendPrivateMessage(p0, p1, p2, p3)
|
|
||||||
case "set_essence_msg":
|
case "set_essence_msg":
|
||||||
p0 := int32(p.Get("message_id").Int())
|
p0 := int32(p.Get("message_id").Int())
|
||||||
return c.bot.CQSetEssenceMessage(p0)
|
return c.bot.CQSetEssenceMessage(p0)
|
||||||
@ -267,6 +292,13 @@ func (c *Caller) call(action string, p Getter) global.MSG {
|
|||||||
p2 = pt.Bool()
|
p2 = pt.Bool()
|
||||||
}
|
}
|
||||||
return c.bot.CQSetGroupAdmin(p0, p1, p2)
|
return c.bot.CQSetGroupAdmin(p0, p1, p2)
|
||||||
|
case "set_group_anonymous":
|
||||||
|
p0 := p.Get("group_id").Int()
|
||||||
|
p1 := true
|
||||||
|
if pt := p.Get("enable"); pt.Exists() {
|
||||||
|
p1 = pt.Bool()
|
||||||
|
}
|
||||||
|
return c.bot.CQSetGroupAnonymous(p0, p1)
|
||||||
case "set_group_anonymous_ban":
|
case "set_group_anonymous_ban":
|
||||||
p0 := p.Get("group_id").Int()
|
p0 := p.Get("group_id").Int()
|
||||||
p1 := p.Get("[anonymous_flag,anonymous.flag].0").String()
|
p1 := p.Get("[anonymous_flag,anonymous.flag].0").String()
|
||||||
@ -347,4 +379,5 @@ func (c *Caller) call(action string, p Getter) global.MSG {
|
|||||||
p2 := p.Get("name").String()
|
p2 := p.Get("name").String()
|
||||||
return c.bot.CQUploadPrivateFile(p0, p1, p2)
|
return c.bot.CQUploadPrivateFile(p0, p1, p2)
|
||||||
}
|
}
|
||||||
|
return coolq.Failed(404, "API_NOT_FOUND", "API不存在")
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/Mrs4s/go-cqhttp/global"
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/Mrs4s/go-cqhttp/cmd/api-generator -path=./../../coolq/api.go
|
//go:generate go run github.com/Mrs4s/go-cqhttp/cmd/api-generator -path=./../../coolq/api.go,./../../coolq/api_v12.go
|
||||||
|
|
||||||
// Getter 参数获取
|
// Getter 参数获取
|
||||||
type Getter interface {
|
type Getter interface {
|
||||||
@ -25,13 +25,13 @@ type Caller struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call specific API
|
// Call specific API
|
||||||
func (c *Caller) Call(action string, p Getter) global.MSG {
|
func (c *Caller) Call(action string, version uint16, p Getter) global.MSG {
|
||||||
for _, fn := range c.handlers {
|
for _, fn := range c.handlers {
|
||||||
if ret := fn(action, p); ret != nil {
|
if ret := fn(action, p); ret != nil {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c.call(action, p)
|
return c.call(action, version, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use add handlers to the API caller
|
// Use add handlers to the API caller
|
||||||
|
@ -55,6 +55,7 @@ type Config struct {
|
|||||||
RemoveReplyAt bool `yaml:"remove-reply-at"`
|
RemoveReplyAt bool `yaml:"remove-reply-at"`
|
||||||
ExtraReplyData bool `yaml:"extra-reply-data"`
|
ExtraReplyData bool `yaml:"extra-reply-data"`
|
||||||
SkipMimeScan bool `yaml:"skip-mime-scan"`
|
SkipMimeScan bool `yaml:"skip-mime-scan"`
|
||||||
|
ConvertWebpImage bool `yaml:"convert-webp-image"`
|
||||||
} `yaml:"message"`
|
} `yaml:"message"`
|
||||||
|
|
||||||
Output struct {
|
Output struct {
|
||||||
|
@ -43,6 +43,8 @@ message:
|
|||||||
extra-reply-data: false
|
extra-reply-data: false
|
||||||
# 跳过 Mime 扫描, 忽略错误数据
|
# 跳过 Mime 扫描, 忽略错误数据
|
||||||
skip-mime-scan: false
|
skip-mime-scan: false
|
||||||
|
# 是否自动转换 WebP 图片
|
||||||
|
convert-webp-image: false
|
||||||
|
|
||||||
output:
|
output:
|
||||||
# 日志等级 trace,debug,info,warn,error
|
# 日志等级 trace,debug,info,warn,error
|
||||||
|
@ -34,6 +34,7 @@ import (
|
|||||||
// HTTPServer HTTP通信相关配置
|
// HTTPServer HTTP通信相关配置
|
||||||
type HTTPServer struct {
|
type HTTPServer struct {
|
||||||
Disabled bool `yaml:"disabled"`
|
Disabled bool `yaml:"disabled"`
|
||||||
|
Version uint16 `yaml:"version"`
|
||||||
Address string `yaml:"address"`
|
Address string `yaml:"address"`
|
||||||
Host string `yaml:"host"`
|
Host string `yaml:"host"`
|
||||||
Port int `yaml:"port"`
|
Port int `yaml:"port"`
|
||||||
@ -57,6 +58,7 @@ type httpServerPost struct {
|
|||||||
type httpServer struct {
|
type httpServer struct {
|
||||||
api *api.Caller
|
api *api.Caller
|
||||||
accessToken string
|
accessToken string
|
||||||
|
version uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPClient 反向HTTP上报客户端
|
// HTTPClient 反向HTTP上报客户端
|
||||||
@ -81,6 +83,7 @@ type httpCtx struct {
|
|||||||
const httpDefault = `
|
const httpDefault = `
|
||||||
- http: # HTTP 通信设置
|
- http: # HTTP 通信设置
|
||||||
address: 0.0.0.0:5700 # HTTP监听地址
|
address: 0.0.0.0:5700 # HTTP监听地址
|
||||||
|
version: 11 # OneBot协议版本, 支持 11/12
|
||||||
timeout: 5 # 反向 HTTP 超时时间, 单位秒,<5 时将被忽略
|
timeout: 5 # 反向 HTTP 超时时间, 单位秒,<5 时将被忽略
|
||||||
long-polling: # 长轮询拓展
|
long-polling: # 长轮询拓展
|
||||||
enabled: false # 是否开启
|
enabled: false # 是否开启
|
||||||
@ -104,31 +107,35 @@ func init() {
|
|||||||
|
|
||||||
var joinQuery = regexp.MustCompile(`\[(.+?),(.+?)]\.0`)
|
var joinQuery = regexp.MustCompile(`\[(.+?),(.+?)]\.0`)
|
||||||
|
|
||||||
func (h *httpCtx) get(s string, join bool) gjson.Result {
|
func mayJSONParam(p string) bool {
|
||||||
|
if strings.HasPrefix(p, "{") || strings.HasPrefix(p, "[") {
|
||||||
|
return gjson.Valid(p)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *httpCtx) get(pattern string, join bool) gjson.Result {
|
||||||
// support gjson advanced syntax:
|
// support gjson advanced syntax:
|
||||||
// h.Get("[a,b].0") see usage in http_test.go
|
// h.Get("[a,b].0") see usage in http_test.go. See issue #1241, #1325.
|
||||||
if join && joinQuery.MatchString(s) {
|
if join && strings.HasPrefix(pattern, "[") && joinQuery.MatchString(pattern) {
|
||||||
matched := joinQuery.FindStringSubmatch(s)
|
matched := joinQuery.FindStringSubmatch(pattern)
|
||||||
if r := h.get(matched[1], false); r.Exists() {
|
if r := h.get(matched[1], false); r.Exists() {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
return h.get(matched[2], false)
|
return h.get(matched[2], false)
|
||||||
}
|
}
|
||||||
|
|
||||||
validJSONParam := func(p string) bool {
|
|
||||||
return (strings.HasPrefix(p, "{") || strings.HasPrefix(p, "[")) && gjson.Valid(p)
|
|
||||||
}
|
|
||||||
if h.postForm != nil {
|
if h.postForm != nil {
|
||||||
if form := h.postForm.Get(s); form != "" {
|
if form := h.postForm.Get(pattern); form != "" {
|
||||||
if validJSONParam(form) {
|
if mayJSONParam(form) {
|
||||||
return gjson.Result{Type: gjson.JSON, Raw: form}
|
return gjson.Result{Type: gjson.JSON, Raw: form}
|
||||||
}
|
}
|
||||||
return gjson.Result{Type: gjson.String, Str: form}
|
return gjson.Result{Type: gjson.String, Str: form}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if h.query != nil {
|
if h.query != nil {
|
||||||
if query := h.query.Get(s); query != "" {
|
if query := h.query.Get(pattern); query != "" {
|
||||||
if validJSONParam(query) {
|
if mayJSONParam(query) {
|
||||||
return gjson.Result{Type: gjson.JSON, Raw: query}
|
return gjson.Result{Type: gjson.JSON, Raw: query}
|
||||||
}
|
}
|
||||||
return gjson.Result{Type: gjson.String, Str: query}
|
return gjson.Result{Type: gjson.String, Str: query}
|
||||||
@ -150,6 +157,13 @@ func (s *httpServer) ServeHTTP(writer http.ResponseWriter, request *http.Request
|
|||||||
contentType := request.Header.Get("Content-Type")
|
contentType := request.Header.Get("Content-Type")
|
||||||
switch request.Method {
|
switch request.Method {
|
||||||
case http.MethodPost:
|
case http.MethodPost:
|
||||||
|
// todo: msg pack
|
||||||
|
if s.version == 12 && strings.Contains(contentType, "application/msgpack") {
|
||||||
|
log.Warnf("请求 %v 数据类型暂不支持: MsgPack", request.RequestURI)
|
||||||
|
writer.WriteHeader(http.StatusUnsupportedMediaType)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if strings.Contains(contentType, "application/json") {
|
if strings.Contains(contentType, "application/json") {
|
||||||
body, err := io.ReadAll(request.Body)
|
body, err := io.ReadAll(request.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -190,12 +204,12 @@ func (s *httpServer) ServeHTTP(writer http.ResponseWriter, request *http.Request
|
|||||||
if request.URL.Path == "/" {
|
if request.URL.Path == "/" {
|
||||||
action := strings.TrimSuffix(ctx.Get("action").Str, "_async")
|
action := strings.TrimSuffix(ctx.Get("action").Str, "_async")
|
||||||
log.Debugf("HTTPServer接收到API调用: %v", action)
|
log.Debugf("HTTPServer接收到API调用: %v", action)
|
||||||
response = s.api.Call(action, ctx.Get("params"))
|
response = s.api.Call(action, s.version, ctx.Get("params"))
|
||||||
} else {
|
} else {
|
||||||
action := strings.TrimPrefix(request.URL.Path, "/")
|
action := strings.TrimPrefix(request.URL.Path, "/")
|
||||||
action = strings.TrimSuffix(action, "_async")
|
action = strings.TrimSuffix(action, "_async")
|
||||||
log.Debugf("HTTPServer接收到API调用: %v", action)
|
log.Debugf("HTTPServer接收到API调用: %v", action)
|
||||||
response = s.api.Call(action, &ctx)
|
response = s.api.Call(action, s.version, &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.Header().Set("Content-Type", "application/json; charset=utf-8")
|
writer.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
@ -245,9 +259,11 @@ func runHTTP(bot *coolq.CQBot, node yaml.Node) {
|
|||||||
case conf.Disabled:
|
case conf.Disabled:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if conf.Version != 11 && conf.Version != 12 {
|
||||||
|
conf.Version = 11
|
||||||
|
}
|
||||||
network, addr := "tcp", conf.Address
|
network, addr := "tcp", conf.Address
|
||||||
s := &httpServer{accessToken: conf.AccessToken}
|
s := &httpServer{accessToken: conf.AccessToken, version: conf.Version}
|
||||||
switch {
|
switch {
|
||||||
case conf.Address != "":
|
case conf.Address != "":
|
||||||
uri, err := url.Parse(conf.Address)
|
uri, err := url.Parse(conf.Address)
|
||||||
|
@ -50,7 +50,7 @@ func longPolling(bot *coolq.CQBot, maxSize int) api.Handler {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
ch = make(chan []interface{})
|
ch = make(chan []any)
|
||||||
timeout = time.Duration(p.Get("timeout").Int()) * time.Second
|
timeout = time.Duration(p.Get("timeout").Int()) * time.Second
|
||||||
)
|
)
|
||||||
go func() {
|
go func() {
|
||||||
@ -63,7 +63,7 @@ func longPolling(bot *coolq.CQBot, maxSize int) api.Handler {
|
|||||||
if limit <= 0 || queue.Len() < limit {
|
if limit <= 0 || queue.Len() < limit {
|
||||||
limit = queue.Len()
|
limit = queue.Len()
|
||||||
}
|
}
|
||||||
ret := make([]interface{}, limit)
|
ret := make([]any, limit)
|
||||||
elem := queue.Front()
|
elem := queue.Front()
|
||||||
for i := 0; i < limit; i++ {
|
for i := 0; i < limit; i++ {
|
||||||
ret[i] = elem.Value
|
ret[i] = elem.Value
|
||||||
@ -81,7 +81,7 @@ func longPolling(bot *coolq.CQBot, maxSize int) api.Handler {
|
|||||||
if timeout != 0 {
|
if timeout != 0 {
|
||||||
select {
|
select {
|
||||||
case <-time.After(timeout):
|
case <-time.After(timeout):
|
||||||
return coolq.OK([]interface{}{})
|
return coolq.OK([]any{})
|
||||||
case ret := <-ch:
|
case ret := <-ch:
|
||||||
return coolq.OK(ret)
|
return coolq.OK(ret)
|
||||||
}
|
}
|
||||||
|
@ -191,9 +191,13 @@ func runWSClient(b *coolq.CQBot, node yaml.Node) {
|
|||||||
filter: conf.Filter,
|
filter: conf.Filter,
|
||||||
}
|
}
|
||||||
filter.Add(c.filter)
|
filter.Add(c.filter)
|
||||||
|
|
||||||
if conf.ReconnectInterval != 0 {
|
if conf.ReconnectInterval != 0 {
|
||||||
c.reconnectInterval = time.Duration(conf.ReconnectInterval) * time.Millisecond
|
c.reconnectInterval = time.Duration(conf.ReconnectInterval) * time.Millisecond
|
||||||
|
} else {
|
||||||
|
c.reconnectInterval = time.Second * 5
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.RateLimit.Enabled {
|
if conf.RateLimit.Enabled {
|
||||||
c.limiter = rateLimit(conf.RateLimit.Frequency, conf.RateLimit.Bucket)
|
c.limiter = rateLimit(conf.RateLimit.Frequency, conf.RateLimit.Bucket)
|
||||||
}
|
}
|
||||||
@ -463,14 +467,16 @@ func (s *webSocketServer) listenAPI(c *wsConn) {
|
|||||||
func (c *wsConn) handleRequest(_ *coolq.CQBot, payload []byte) {
|
func (c *wsConn) handleRequest(_ *coolq.CQBot, payload []byte) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
log.Printf("处置WS命令时发生无法恢复的异常:%v\n%s", err, debug.Stack())
|
log.Errorf("处置WS命令时发生无法恢复的异常:%v\n%s", err, debug.Stack())
|
||||||
_ = c.Close()
|
_ = c.Close()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
j := gjson.Parse(utils.B2S(payload))
|
j := gjson.Parse(utils.B2S(payload))
|
||||||
t := strings.TrimSuffix(j.Get("action").Str, "_async")
|
t := strings.TrimSuffix(j.Get("action").Str, "_async")
|
||||||
log.Debugf("WS接收到API调用: %v 参数: %v", t, j.Get("params").Raw)
|
params := j.Get("params")
|
||||||
ret := c.apiCaller.Call(t, j.Get("params"))
|
log.Debugf("WS接收到API调用: %v 参数: %v", t, params.Raw)
|
||||||
|
ret := c.apiCaller.Call(t, 11, params)
|
||||||
if j.Get("echo").Exists() {
|
if j.Get("echo").Exists() {
|
||||||
ret["echo"] = j.Get("echo").Value()
|
ret["echo"] = j.Get("echo").Value()
|
||||||
}
|
}
|
||||||
@ -478,7 +484,11 @@ func (c *wsConn) handleRequest(_ *coolq.CQBot, payload []byte) {
|
|||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
_ = c.conn.SetWriteDeadline(time.Now().Add(time.Second * 15))
|
_ = c.conn.SetWriteDeadline(time.Now().Add(time.Second * 15))
|
||||||
writer, _ := c.conn.NextWriter(websocket.TextMessage)
|
writer, err := c.conn.NextWriter(websocket.TextMessage)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("无法响应API调用(连接已断开?): %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
_ = json.NewEncoder(writer).Encode(ret)
|
_ = json.NewEncoder(writer).Encode(ret)
|
||||||
_ = writer.Close()
|
_ = writer.Close()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user