1
0
mirror of https://github.com/Mrs4s/go-cqhttp.git synced 2025-06-30 11:53:25 +00:00

Compare commits

...

11 Commits

Author SHA1 Message Date
e32137ceeb update MiraiGo. 2020-12-19 02:10:57 +08:00
9dc519ff77 feature fix url & update doc. 2020-12-19 02:09:36 +08:00
3d5cec13d0 update doc. 2020-12-18 23:56:27 +08:00
6ea4bd829e fix issue of get_msg image url empty. #503 2020-12-18 23:47:49 +08:00
6e3501a6f8 fix #501. 2020-12-18 09:10:09 +08:00
289b96f187 update raw. 2020-12-18 08:57:41 +08:00
aa77810491 support old coolq data path. #499 2020-12-17 08:12:57 +08:00
474de6ad3d feature get_group_at_all_remain. 2020-12-16 20:35:15 +08:00
cbbe196f26 update MiraiGo. 2020-12-15 23:48:26 +08:00
00783380b7 update ISSUE_TEMPLATE. 2020-12-14 16:51:16 +08:00
4ef476cb67 update MiraiGo. 2020-12-14 16:44:43 +08:00
16 changed files with 117 additions and 25 deletions

View File

@ -7,11 +7,20 @@ assignees: ''
--- ---
<!--
在提出ISSUE前希望您能花费一定的时间执行以下几个步骤以方便我们定位BUG.
1: 确定没有相同问题的ISSUE已被提出.
2: 准确填写环境信息.
3: 最好能打开DEBUG模式并复现相关问题.
4: 如果涉及内存泄漏/CPU占用异常请打开DEBUG模式并下载pprof性能分析.
-->
**环境信息** **环境信息**
请根据实际使用环境修改以下信息 请根据实际使用环境修改以下信息
go-cqhttp版本: v0.9.10 go-cqhttp版本:
运行环境: windows_amd64 运行环境:
连接方式: 反向WS 连接方式:
使用协议:
**bug内容** **bug内容**
请在这里详细描述bug的内容 请在这里详细描述bug的内容

View File

@ -428,6 +428,17 @@ func (bot *CQBot) CQSetGroupLeave(groupId int64) MSG {
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在") return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
} }
func (bot *CQBot) CQGetAtAllRemain(groupId int64) MSG {
if g := bot.Client.FindGroup(groupId); g != nil {
i, err := bot.Client.GetAtAllRemain(groupId)
if err != nil {
return Failed(100, "GROUP_REMAIN_API_ERROR", err.Error())
}
return OK(i)
}
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
}
// https://cqhttp.cc/docs/4.15/#/API?id=set_friend_add_request-%E5%A4%84%E7%90%86%E5%8A%A0%E5%A5%BD%E5%8F%8B%E8%AF%B7%E6%B1%82 // https://cqhttp.cc/docs/4.15/#/API?id=set_friend_add_request-%E5%A4%84%E7%90%86%E5%8A%A0%E5%A5%BD%E5%8F%8B%E8%AF%B7%E6%B1%82
func (bot *CQBot) CQProcessFriendRequest(flag string, approve bool) MSG { func (bot *CQBot) CQProcessFriendRequest(flag string, approve bool) MSG {
req, ok := bot.friendReqCache.Load(flag) req, ok := bot.friendReqCache.Load(flag)
@ -744,6 +755,7 @@ func (bot *CQBot) CQGetMessage(messageId int32) MSG {
"nickname": sender.Nickname, "nickname": sender.Nickname,
}, },
"time": msg["time"], "time": msg["time"],
"message_raw": raw,
"message": ToFormattedMessage(bot.ConvertStringMessage(raw, isGroup), func() int64 { "message": ToFormattedMessage(bot.ConvertStringMessage(raw, isGroup), func() int64 {
if isGroup { if isGroup {
return gid.(int64) return gid.(int64)

View File

@ -88,7 +88,7 @@ func NewQQBot(cli *client.QQClient, conf *global.JsonConfig) *CQBot {
"self_id": bot.Client.Uin, "self_id": bot.Client.Uin,
"post_type": "meta_event", "post_type": "meta_event",
"meta_event_type": "heartbeat", "meta_event_type": "heartbeat",
"status": nil, "status": bot.CQGetStatus()["data"],
"interval": 1000 * i, "interval": 1000 * i,
}) })
} }

View File

@ -10,6 +10,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"math" "math"
"math/rand"
"net/url" "net/url"
"path" "path"
"runtime" "runtime"
@ -30,6 +31,7 @@ var paramReg = regexp.MustCompile(`,([\w\-.]+?)=([^,\]]+)`)
*/ */
var IgnoreInvalidCQCode = false var IgnoreInvalidCQCode = false
var SplitUrl = false
type PokeElement struct { type PokeElement struct {
Target int64 Target int64
@ -342,8 +344,14 @@ func (bot *CQBot) ConvertStringMessage(msg string, group bool) (r []message.IMes
} }
saveTempText := func() { saveTempText := func() {
if len(tempText) != 0 { if len(tempText) != 0 {
if SplitUrl {
for _, t := range global.SplitUrl(CQCodeUnescapeValue(string(tempText))) {
r = append(r, message.NewText(t))
}
} else {
r = append(r, message.NewText(CQCodeUnescapeValue(string(tempText)))) r = append(r, message.NewText(CQCodeUnescapeValue(string(tempText))))
} }
}
tempText = []rune{} tempText = []rune{}
cqCode = []rune{} cqCode = []rune{}
} }
@ -505,6 +513,13 @@ func (bot *CQBot) ConvertObjectMessage(m gjson.Result, group bool) (r []message.
func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interface{}, err error) { func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interface{}, err error) {
switch t { switch t {
case "text": case "text":
if SplitUrl {
var ret []message.IMessageElement
for _, text := range global.SplitUrl(d["text"]) {
ret = append(ret, message.NewText(text))
}
return ret, nil
}
return message.NewText(d["text"]), nil return message.NewText(d["text"]), nil
case "image": case "image":
img, err := bot.makeImageElem(d, group) img, err := bot.makeImageElem(d, group)
@ -573,6 +588,9 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf
case "record": case "record":
f := d["file"] f := d["file"]
data, err := global.FindFile(f, d["cache"], global.VOICE_PATH) data, err := global.FindFile(f, d["cache"], global.VOICE_PATH)
if err == global.ErrSyntax {
data, err = global.FindFile(f, d["cache"], global.VOICE_PATH_OLD)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -817,6 +835,9 @@ func (bot *CQBot) makeImageElem(d map[string]string, group bool) (message.IMessa
return message.NewImage(b), nil return message.NewImage(b), nil
} }
rawPath := path.Join(global.IMAGE_PATH, f) rawPath := path.Join(global.IMAGE_PATH, f)
if !global.PathExists(rawPath) && global.PathExists(path.Join(global.IMAGE_PATH_OLD, f)) {
rawPath = path.Join(global.IMAGE_PATH_OLD, f)
}
if !global.PathExists(rawPath) && global.PathExists(rawPath+".cqimg") { if !global.PathExists(rawPath) && global.PathExists(rawPath+".cqimg") {
rawPath += ".cqimg" rawPath += ".cqimg"
} }
@ -865,7 +886,7 @@ func (bot *CQBot) makeImageElem(d map[string]string, group bool) (message.IMessa
return nil, errors.New("invalid hash") return nil, errors.New("invalid hash")
} }
if group { if group {
rsp, err := bot.Client.QueryGroupImage(1, hash, size) rsp, err := bot.Client.QueryGroupImage(int64(rand.Uint32()), hash, size)
if err != nil { if err != nil {
if url != "" { if url != "" {
return bot.makeImageElem(map[string]string{"file": url}, group) return bot.makeImageElem(map[string]string{"file": url}, group)
@ -874,7 +895,7 @@ func (bot *CQBot) makeImageElem(d map[string]string, group bool) (message.IMessa
} }
return rsp, nil return rsp, nil
} }
rsp, err := bot.Client.QueryFriendImage(1, hash, size) rsp, err := bot.Client.QueryFriendImage(int64(rand.Uint32()), hash, size)
if err != nil { if err != nil {
if url != "" { if url != "" {
return bot.makeImageElem(map[string]string{"file": url}, group) return bot.makeImageElem(map[string]string{"file": url}, group)

View File

@ -78,6 +78,7 @@ go-cqhttp 支持导入CQHTTP的配置文件, 具体步骤为:
| post_message_format | string | 上报信息类型 | | post_message_format | string | 上报信息类型 |
| ignore_invalid_cqcode | bool | 是否忽略错误的CQ码 | | ignore_invalid_cqcode | bool | 是否忽略错误的CQ码 |
| force_fragmented | bool | 是否强制分片发送群长消息 | | force_fragmented | bool | 是否强制分片发送群长消息 |
| fix_url | bool | 是否对链接的发送进行预处理, 可缓解链接信息被风控导致无法发送的情况, 但可能影响客户端着色(不影响内容)|
| use_sso_address | bool | 是否使用服务器下发的地址 | | use_sso_address | bool | 是否使用服务器下发的地址 |
| heartbeat_interval | int64 | 心跳间隔时间单位秒。小于0则关闭心跳等于0使用默认值(5秒) | | heartbeat_interval | int64 | 心跳间隔时间单位秒。小于0则关闭心跳等于0使用默认值(5秒) |
| http_config | object | HTTP API配置 | | http_config | object | HTTP API配置 |
@ -113,8 +114,8 @@ go-cqhttp 支持导入CQHTTP的配置文件, 具体步骤为:
| 值 | 类型 | 限制 | | 值 | 类型 | 限制 |
| --- | ------------- | ---------------------------------------------------------------- | | --- | ------------- | ---------------------------------------------------------------- |
| 0 | iPad | 无 | | 0 | iPad | 无 |
| 1 | Android Phone | 无法接收新版表情如 `/吃瓜 /汪汪`, 会自动转换为字符串 | | 1 | Android Phone | 无 |
| 2 | Android Watch | 除`Android Phone`的限制外, 无法接收 `notify` 事件、无法接收口令红包、无法接收撤回消息 | | 2 | Android Watch | 无法接收 `notify` 事件、无法接收口令红包、无法接收撤回消息 |
| 3 | MacOS | 无 | | 3 | MacOS | 无 |
> 注意, 根据协议的不同, 各类消息有所限制 > 注意, 根据协议的不同, 各类消息有所限制

View File

@ -736,6 +736,24 @@ Type: `tts`
> 注意: 所有统计信息都将在重启后重制 > 注意: 所有统计信息都将在重启后重制
### 获取群@全体成员剩余次数
终结点: `/get_group_at_all_remain`
**参数**
| 字段 | 类型 | 说明 |
| ---------- | ------ | ------------------------- |
| `group_id` | int64 | 群号 |
**响应数据**
| 字段 | 类型 | 说明 |
| ------------------------------- | ---------- | ------------------------------- |
| `can_at_all` | bool | 是否可以@全体成员 |
| `remain_at_all_count_for_group` | int16 | 群内所有管理当天剩余@全体成员次数 |
| `remain_at_all_count_for_uin` | int16 | BOT当天剩余@全体成员次数 |
## 事件 ## 事件
### 群消息撤回 ### 群消息撤回

View File

@ -153,6 +153,7 @@ type JsonConfig struct {
} `json:"_rate_limit"` } `json:"_rate_limit"`
IgnoreInvalidCQCode bool `json:"ignore_invalid_cqcode"` IgnoreInvalidCQCode bool `json:"ignore_invalid_cqcode"`
ForceFragmented bool `json:"force_fragmented"` ForceFragmented bool `json:"force_fragmented"`
FixUrl bool `json:"fix_url"`
ProxyRewrite string `json:"proxy_rewrite"` ProxyRewrite string `json:"proxy_rewrite"`
HeartbeatInterval time.Duration `json:"heartbeat_interval"` HeartbeatInterval time.Duration `json:"heartbeat_interval"`
HttpConfig *GoCQHttpConfig `json:"http_config"` HttpConfig *GoCQHttpConfig `json:"http_config"`

View File

@ -22,12 +22,16 @@ import (
var ( var (
IMAGE_PATH = path.Join("data", "images") IMAGE_PATH = path.Join("data", "images")
IMAGE_PATH_OLD = path.Join("data", "image")
VOICE_PATH = path.Join("data", "voices") VOICE_PATH = path.Join("data", "voices")
VOICE_PATH_OLD = path.Join("data", "record")
VIDEO_PATH = path.Join("data", "videos") VIDEO_PATH = path.Join("data", "videos")
CACHE_PATH = path.Join("data", "cache") CACHE_PATH = path.Join("data", "cache")
HEADER_AMR = []byte("#!AMR") HEADER_AMR = []byte("#!AMR")
HEADER_SILK = []byte("\x02#!SILK_V3") HEADER_SILK = []byte("\x02#!SILK_V3")
ErrSyntax = errors.New("syntax error")
) )
func PathExists(path string) bool { func PathExists(path string) bool {
@ -58,7 +62,7 @@ func IsAMRorSILK(b []byte) bool {
} }
func FindFile(f, cache, PATH string) (data []byte, err error) { func FindFile(f, cache, PATH string) (data []byte, err error) {
data, err = nil, errors.New("syntax error") data, err = nil, ErrSyntax
if strings.HasPrefix(f, "http") || strings.HasPrefix(f, "https") { if strings.HasPrefix(f, "http") || strings.HasPrefix(f, "https") {
if cache == "" { if cache == "" {
cache = "1" cache = "1"

View File

@ -26,7 +26,6 @@ var client = &http.Client{
DialContext: (&net.Dialer{ DialContext: (&net.Dialer{
Timeout: 30 * time.Second, Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second, KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext, }).DialContext,
ForceAttemptHTTP2: true, ForceAttemptHTTP2: true,
MaxIdleConns: 100, MaxIdleConns: 100,

View File

@ -71,3 +71,23 @@ func VersionNameCompare(current, remote string) bool {
} }
return len(cur) < len(re) return len(cur) < len(re)
} }
func SplitUrl(s string) []string {
reg := regexp.MustCompile(`[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?`)
idx := reg.FindAllStringIndex(s, -1)
if len(idx) == 0 {
return []string{s}
}
var result []string
last := 0
for i := 0; i < len(idx); i++ {
if len(idx[i]) != 2 {
continue
}
m := int(math.Abs(float64(idx[i][0]-idx[i][1]))/1.5) + idx[i][0]
result = append(result, s[last:m])
last = m
}
result = append(result, s[last:])
return result
}

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/Mrs4s/go-cqhttp
go 1.15 go 1.15
require ( require (
github.com/Mrs4s/MiraiGo v0.0.0-20201212141451-52096c28df90 github.com/Mrs4s/MiraiGo v0.0.0-20201218175143-7312c96e82f7
github.com/dustin/go-humanize v1.0.0 github.com/dustin/go-humanize v1.0.0
github.com/getlantern/go-update v0.0.0-20190510022740-79c495ab728c github.com/getlantern/go-update v0.0.0-20190510022740-79c495ab728c
github.com/getlantern/golog v0.0.0-20201105130739-9586b8bde3a9 // indirect github.com/getlantern/golog v0.0.0-20201105130739-9586b8bde3a9 // indirect

7
go.sum
View File

@ -1,9 +1,7 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Mrs4s/MiraiGo v0.0.0-20201212132428-af0230171ee1 h1:NA46lAqHDhrXMRBjHmnnDDyEbv6d5Ajh4UyO1Dqra7U= github.com/Mrs4s/MiraiGo v0.0.0-20201218175143-7312c96e82f7 h1:h4QVB94oL6riP5hYb2BWqJ6KGP7zQVGPXd91V/IQm9g=
github.com/Mrs4s/MiraiGo v0.0.0-20201212132428-af0230171ee1/go.mod h1:o+me0DWqTbZU4Xmu2D1gIpCditlwt+vMTNZmjvApf5Y= github.com/Mrs4s/MiraiGo v0.0.0-20201218175143-7312c96e82f7/go.mod h1:o+me0DWqTbZU4Xmu2D1gIpCditlwt+vMTNZmjvApf5Y=
github.com/Mrs4s/MiraiGo v0.0.0-20201212141451-52096c28df90 h1:/qGcbSQGHqYFUPZVIWWKD/KUkofW4B7msBva5f8R2mY=
github.com/Mrs4s/MiraiGo v0.0.0-20201212141451-52096c28df90/go.mod h1:o+me0DWqTbZU4Xmu2D1gIpCditlwt+vMTNZmjvApf5Y=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -72,7 +70,6 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/guonaihong/gout v0.1.3 h1:BIiV6nnsA+R6dIB1P33uhCM8+TVAG3zHrXGZad7hDc8= github.com/guonaihong/gout v0.1.3 h1:BIiV6nnsA+R6dIB1P33uhCM8+TVAG3zHrXGZad7hDc8=
github.com/guonaihong/gout v0.1.3/go.mod h1:vXvv5Kxr70eM5wrp4F0+t9lnLWmq+YPW2GByll2f/EA= github.com/guonaihong/gout v0.1.3/go.mod h1:vXvv5Kxr70eM5wrp4F0+t9lnLWmq+YPW2GByll2f/EA=
github.com/hjson/hjson-go v0.2.3 h1:KhG7/PSxTibbYOzFso5FoiX2gWePcANaCsvM1WE/bTo=
github.com/hjson/hjson-go v3.1.0+incompatible h1:DY/9yE8ey8Zv22bY+mHV1uk2yRy0h8tKhZ77hEdi0Aw= github.com/hjson/hjson-go v3.1.0+incompatible h1:DY/9yE8ey8Zv22bY+mHV1uk2yRy0h8tKhZ77hEdi0Aw=
github.com/hjson/hjson-go v3.1.0+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio= github.com/hjson/hjson-go v3.1.0+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=

View File

@ -99,7 +99,7 @@ func init() {
func main() { func main() {
var byteKey []byte var byteKey []byte
var isFastStart bool = false var isFastStart = false
arg := os.Args arg := os.Args
if len(arg) > 1 { if len(arg) > 1 {
for i := range arg { for i := range arg {

View File

@ -239,6 +239,7 @@ func (s *webServer) Dologin() {
global.BootFilter() global.BootFilter()
global.InitCodec() global.InitCodec()
coolq.IgnoreInvalidCQCode = conf.IgnoreInvalidCQCode coolq.IgnoreInvalidCQCode = conf.IgnoreInvalidCQCode
coolq.SplitUrl = conf.FixUrl
coolq.ForceFragmented = conf.ForceFragmented coolq.ForceFragmented = conf.ForceFragmented
log.Info("资源初始化完成, 开始处理信息.") log.Info("资源初始化完成, 开始处理信息.")
log.Info("アトリは、高性能ですから!") log.Info("アトリは、高性能ですから!")

View File

@ -394,6 +394,11 @@ func GetStrangerInfo(s *httpServer, c *gin.Context) {
c.JSON(200, s.bot.CQGetStrangerInfo(uid)) c.JSON(200, s.bot.CQGetStrangerInfo(uid))
} }
func GetGroupAtAllRemain(s *httpServer, c *gin.Context) {
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
c.JSON(200, s.bot.CQGetAtAllRemain(gid))
}
func HandleQuickOperation(s *httpServer, c *gin.Context) { func HandleQuickOperation(s *httpServer, c *gin.Context) {
if c.Request.Method != "POST" { if c.Request.Method != "POST" {
c.AbortWithStatus(404) c.AbortWithStatus(404)
@ -514,6 +519,7 @@ var httpApi = map[string]func(s *httpServer, c *gin.Context){
".handle_quick_operation": HandleQuickOperation, ".handle_quick_operation": HandleQuickOperation,
".ocr_image": OcrImage, ".ocr_image": OcrImage,
"ocr_image": OcrImage, "ocr_image": OcrImage,
"get_group_at_all_remain": GetGroupAtAllRemain,
".get_word_slices": GetWordSlices, ".get_word_slices": GetWordSlices,
} }

View File

@ -536,6 +536,9 @@ var wsApi = map[string]func(*coolq.CQBot, gjson.Result) coolq.MSG{
"ocr_image": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG { "ocr_image": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQOcrImage(p.Get("image").Str) return bot.CQOcrImage(p.Get("image").Str)
}, },
"get_group_at_all_remain": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetAtAllRemain(p.Get("group_id").Int())
},
".get_word_slices": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG { ".get_word_slices": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetWordSlices(p.Get("content").Str) return bot.CQGetWordSlices(p.Get("content").Str)
}, },