mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-05 03:23:49 +08:00
Compare commits
77 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a5923f179b | ||
|
730d01c648 | ||
|
12e0cb4afb | ||
|
e06edd2412 | ||
|
5aca1f4500 | ||
|
75635739ba | ||
|
d25e320238 | ||
|
b8d622bb90 | ||
|
9cccd0e39b | ||
|
e1a4293ee6 | ||
|
8607542f1e | ||
|
5cbbcda2c2 | ||
|
fcf79ded58 | ||
|
6ac7a8f0ae | ||
|
bd785d3894 | ||
|
642c74688c | ||
|
517d323953 | ||
|
07214e396e | ||
|
1c34643f4f | ||
|
f16d72f0ca | ||
|
9e6d7b7650 | ||
|
417a0f256a | ||
|
77b54fca20 | ||
|
fd6ef4a2b8 | ||
|
79a194fbb0 | ||
|
f8354ec082 | ||
|
d85d697fc2 | ||
|
da9f03fa47 | ||
|
977030e814 | ||
|
5db03c7092 | ||
|
3b99a825eb | ||
|
94a3ff5dae | ||
|
0714aac1f0 | ||
|
ca20a3d6bf | ||
|
ce119b7ddf | ||
|
a6fd7de65a | ||
|
8ea182a4c3 | ||
|
99cdf9247a | ||
|
837e163ef6 | ||
|
fe92bb54df | ||
|
7cae9829a8 | ||
|
3992dd40c5 | ||
|
1bd0bb9ae2 | ||
|
b8527721c2 | ||
|
14539adcb8 | ||
|
1911b5d245 | ||
|
75ad7aa45c | ||
|
cffdfd8181 | ||
|
99e5cb6c6b | ||
|
09ab2169d9 | ||
|
2b1d9c21cb | ||
|
998fda54a2 | ||
|
5cb8548487 | ||
|
88f5db89a8 | ||
|
7c813f8579 | ||
|
7adbbd6f81 | ||
|
04cbf7b5d7 | ||
|
dae03784cc | ||
|
f466ca7a72 | ||
|
13215f23c5 | ||
|
19dd37a938 | ||
|
a3ad233cd9 | ||
|
06461960a9 | ||
|
aa3a5d28da | ||
|
a4c131e04a | ||
|
526391e613 | ||
|
2901fd14bb | ||
|
16a2ff050e | ||
|
6cf8030d3c | ||
|
9c1390c75c | ||
|
b958046a27 | ||
|
19906eba36 | ||
|
8e6e79f734 | ||
|
9b9ecd6a41 | ||
|
c8e480d12f | ||
|
5bf64ee743 | ||
|
bad3c86912 |
4
.github/ISSUE_TEMPLATE/bug-report.yaml
vendored
4
.github/ISSUE_TEMPLATE/bug-report.yaml
vendored
@ -101,11 +101,13 @@ body:
|
|||||||
label: 使用协议
|
label: 使用协议
|
||||||
description: 选择使用的协议
|
description: 选择使用的协议
|
||||||
options:
|
options:
|
||||||
- 0 | iPad
|
- 0 | Default
|
||||||
- 1 | Android Phone
|
- 1 | Android Phone
|
||||||
- 2 | Android Watch
|
- 2 | Android Watch
|
||||||
- 3 | MacOS
|
- 3 | MacOS
|
||||||
- 4 | 企点
|
- 4 | 企点
|
||||||
|
- 5 | iPad
|
||||||
|
- 6 | aPad
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
1
.github/workflows/build_docker_image.yml
vendored
1
.github/workflows/build_docker_image.yml
vendored
@ -77,3 +77,4 @@ jobs:
|
|||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x
|
||||||
|
21
.github/workflows/close_pr.yml
vendored
Normal file
21
.github/workflows/close_pr.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
name: Check and Close Invalid PR
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened, reopened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# This workflow closes invalid PR
|
||||||
|
close_pr:
|
||||||
|
# The type of runner that the job will run on
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions: write-all
|
||||||
|
|
||||||
|
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||||
|
steps:
|
||||||
|
- name: Close PR if it is not pointed to dev branch
|
||||||
|
if: github.event.pull_request.base.ref != 'dev'
|
||||||
|
uses: superbrothers/close-pull-request@v3
|
||||||
|
with:
|
||||||
|
# Optional. Post a issue comment just before closing a pull request.
|
||||||
|
comment: "Invalid PR to `non-dev` branch `${{ github.event.pull_request.base.ref }}`."
|
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: release
|
name: Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -12,7 +12,8 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
run: |
|
run: |
|
||||||
git version
|
git version
|
||||||
git clone https://github.com/Mrs4s/go-cqhttp.git /home/runner/work/go-cqhttp/go-cqhttp
|
git clone "${{ github.event.repository.html_url }}" /home/runner/work/go-cqhttp/go-cqhttp
|
||||||
|
git checkout "${{ github.ref }}"
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
|
@ -21,7 +21,8 @@ RUN chmod +x /docker-entrypoint.sh && \
|
|||||||
ffmpeg \
|
ffmpeg \
|
||||||
coreutils \
|
coreutils \
|
||||||
shadow \
|
shadow \
|
||||||
su-exec && \
|
su-exec \
|
||||||
|
tzdata && \
|
||||||
rm -rf /var/cache/apk/* && \
|
rm -rf /var/cache/apk/* && \
|
||||||
mkdir -p /app && \
|
mkdir -p /app && \
|
||||||
mkdir -p /data && \
|
mkdir -p /data && \
|
||||||
@ -42,3 +43,4 @@ WORKDIR /data
|
|||||||
VOLUME [ "/data" ]
|
VOLUME [ "/data" ]
|
||||||
|
|
||||||
ENTRYPOINT [ "/docker-entrypoint.sh" ]
|
ENTRYPOINT [ "/docker-entrypoint.sh" ]
|
||||||
|
CMD [ "/app/cqhttp" ]
|
||||||
|
@ -42,6 +42,9 @@ _✨ 基于 [Mirai](https://github.com/mamoe/mirai) 以及 [MiraiGo](https://git
|
|||||||
<a href="https://github.com/Mrs4s/go-cqhttp/blob/master/CONTRIBUTING.md">参与贡献</a>
|
<a href="https://github.com/Mrs4s/go-cqhttp/blob/master/CONTRIBUTING.md">参与贡献</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
## 重要信息
|
||||||
|
由于QQ官方针对协议库的围追堵截, 不断更新加密方案, 我们已无力继续维护此项目.
|
||||||
|
建议Bot开发者尽快迁移至无头NTQQ项目 -> https://github.com/Mrs4s/go-cqhttp/issues/2471
|
||||||
|
|
||||||
## 兼容性
|
## 兼容性
|
||||||
go-cqhttp 兼容 [OneBot-v11](https://github.com/botuniverse/onebot-11) 绝大多数内容,并在其基础上做了一些扩展,详情请看 go-cqhttp 的文档。
|
go-cqhttp 兼容 [OneBot-v11](https://github.com/botuniverse/onebot-11) 绝大多数内容,并在其基础上做了一些扩展,详情请看 go-cqhttp 的文档。
|
||||||
|
@ -3,37 +3,26 @@ package gocq
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/png"
|
"image/png"
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/client"
|
"github.com/Mrs4s/MiraiGo/client"
|
||||||
"github.com/Mrs4s/MiraiGo/utils"
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
"github.com/Mrs4s/MiraiGo/wrapper"
|
|
||||||
"github.com/mattn/go-colorable"
|
"github.com/mattn/go-colorable"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"gopkg.ilharper.com/x/isatty"
|
"gopkg.ilharper.com/x/isatty"
|
||||||
|
|
||||||
"github.com/Mrs4s/go-cqhttp/global"
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
"github.com/Mrs4s/go-cqhttp/internal/base"
|
|
||||||
"github.com/Mrs4s/go-cqhttp/internal/download"
|
"github.com/Mrs4s/go-cqhttp/internal/download"
|
||||||
"github.com/Mrs4s/go-cqhttp/internal/encryption"
|
|
||||||
_ "github.com/Mrs4s/go-cqhttp/internal/encryption/t544" // side effect
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var console = bufio.NewReader(os.Stdin)
|
var console = bufio.NewReader(os.Stdin)
|
||||||
|
|
||||||
func init() {
|
|
||||||
wrapper.DandelionEnergy = energy
|
|
||||||
}
|
|
||||||
|
|
||||||
func readLine() (str string) {
|
func readLine() (str string) {
|
||||||
str, _ = console.ReadString('\n')
|
str, _ = console.ReadString('\n')
|
||||||
str = strings.TrimSpace(str)
|
str = strings.TrimSpace(str)
|
||||||
@ -222,9 +211,8 @@ func loginResponseProcessor(res *client.LoginResponse) error {
|
|||||||
log.Warnf("设备信息被封禁, 请删除 device.json 后重试.")
|
log.Warnf("设备信息被封禁, 请删除 device.json 后重试.")
|
||||||
case 237:
|
case 237:
|
||||||
log.Warnf("登录过于频繁, 请在手机QQ登录并根据提示完成认证后等一段时间重试")
|
log.Warnf("登录过于频繁, 请在手机QQ登录并根据提示完成认证后等一段时间重试")
|
||||||
case 45: // 在提供 t544 后还是出现45错误是需要强行升级到最新客户端或被限制非常用设备
|
case 45:
|
||||||
log.Warnf("你的账号涉嫌违规被限制在非常用设备登录, 请在手机QQ登录并根据提示完成认证")
|
log.Warnf("你的账号被限制登录, 请配置 SignServer 后重试")
|
||||||
log.Warnf("或使用 -update-protocol 升级到最新协议后重试")
|
|
||||||
}
|
}
|
||||||
log.Infof("按 Enter 继续....")
|
log.Infof("按 Enter 继续....")
|
||||||
readLine()
|
readLine()
|
||||||
@ -272,34 +260,3 @@ func fetchCaptcha(id string) string {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func energy(uin uint64, id string, appVersion string, salt []byte) ([]byte, error) {
|
|
||||||
if localSigner, ok := encryption.T544Signer[appVersion]; ok {
|
|
||||||
log.Debugf("use local T544Signer v%s", appVersion)
|
|
||||||
result := localSigner(time.Now().UnixMicro(), salt)
|
|
||||||
log.Debugf("t544 sign result: %x", result)
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
log.Debugf("fallback to remote T544Signer v%s", appVersion)
|
|
||||||
signServer := "https://captcha.go-cqhttp.org/sdk/dandelion/energy"
|
|
||||||
if base.SignServerOverwrite != "" {
|
|
||||||
signServer = base.SignServerOverwrite
|
|
||||||
}
|
|
||||||
response, err := download.Request{
|
|
||||||
Method: http.MethodPost,
|
|
||||||
URL: signServer,
|
|
||||||
Header: map[string]string{"Content-Type": "application/x-www-form-urlencoded"},
|
|
||||||
Body: bytes.NewReader([]byte(fmt.Sprintf("uin=%v&id=%s&salt=%s&version=%s", uin, id, hex.EncodeToString(salt), appVersion))),
|
|
||||||
}.Bytes()
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("获取T544时出现问题: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
sign, err := hex.DecodeString(gjson.GetBytes(response, "result").String())
|
|
||||||
if err != nil || len(sign) == 0 {
|
|
||||||
log.Errorf("获取T544时出现问题: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
log.Debugf("t544 sign result: %x", sign)
|
|
||||||
return sign, nil
|
|
||||||
}
|
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/binary"
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
"github.com/Mrs4s/MiraiGo/client"
|
"github.com/Mrs4s/MiraiGo/client"
|
||||||
|
"github.com/Mrs4s/MiraiGo/wrapper"
|
||||||
para "github.com/fumiama/go-hide-param"
|
para "github.com/fumiama/go-hide-param"
|
||||||
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
|
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -162,6 +163,28 @@ func LoginInteract() {
|
|||||||
log.Fatalf("加载设备信息失败: %v", err)
|
log.Fatalf("加载设备信息失败: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
signServer, err := getAvaliableSignServer() // 获取可用签名服务器
|
||||||
|
if err != nil {
|
||||||
|
log.Warn(err)
|
||||||
|
}
|
||||||
|
if signServer != nil && len(signServer.URL) > 1 {
|
||||||
|
log.Infof("使用签名服务器:%v", signServer.URL)
|
||||||
|
go signStartRefreshToken(base.Account.RefreshInterval) // 定时刷新 token
|
||||||
|
wrapper.DandelionEnergy = energy
|
||||||
|
wrapper.FekitGetSign = sign
|
||||||
|
if !base.IsBelow110 {
|
||||||
|
if !base.Account.AutoRegister {
|
||||||
|
log.Warn("自动注册实例已关闭,请配置 sign-server 端自动注册实例以保持正常签名")
|
||||||
|
}
|
||||||
|
if !base.Account.AutoRefreshToken {
|
||||||
|
log.Info("自动刷新 token 已关闭,token 过期后获取签名时将不会立即尝试刷新获取新 token")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warn("签名服务器版本 <= 1.1.0 ,无法使用刷新 token 等操作,建议使用 1.1.6 版本及以上签名服务器")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warnf("警告: 未配置签名服务器或签名服务器不可用, 这可能会导致登录 45 错误码或发送消息被风控")
|
||||||
|
}
|
||||||
|
|
||||||
if base.Account.Encrypt {
|
if base.Account.Encrypt {
|
||||||
if !global.PathExists("password.encrypt") {
|
if !global.PathExists("password.encrypt") {
|
||||||
@ -232,8 +255,14 @@ func LoginInteract() {
|
|||||||
versionFile := path.Join(global.VersionsPath, fmt.Sprint(int(cli.Device().Protocol))+".json")
|
versionFile := path.Join(global.VersionsPath, fmt.Sprint(int(cli.Device().Protocol))+".json")
|
||||||
if global.PathExists(versionFile) {
|
if global.PathExists(versionFile) {
|
||||||
b, err := os.ReadFile(versionFile)
|
b, err := os.ReadFile(versionFile)
|
||||||
if err == nil {
|
if err != nil {
|
||||||
_ = cli.Device().Protocol.Version().UpdateFromJson(b)
|
log.Warnf("从文件 %s 读取本地版本信息文件出错.", versionFile)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
err = cli.Device().Protocol.Version().UpdateFromJson(b)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("从文件 %s 解析本地版本信息出错: %v", versionFile, err)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
log.Infof("从文件 %s 读取协议版本 %v.", versionFile, cli.Device().Protocol.Version())
|
log.Infof("从文件 %s 读取协议版本 %v.", versionFile, cli.Device().Protocol.Version())
|
||||||
}
|
}
|
||||||
@ -278,6 +307,7 @@ func LoginInteract() {
|
|||||||
cli.Uin = base.Account.Uin
|
cli.Uin = base.Account.Uin
|
||||||
cli.PasswordMd5 = base.PasswordHash
|
cli.PasswordMd5 = base.PasswordHash
|
||||||
}
|
}
|
||||||
|
download.SetTimeout(time.Duration(base.HTTPTimeout) * time.Second)
|
||||||
if !base.FastStart {
|
if !base.FastStart {
|
||||||
log.Infof("正在检查协议更新...")
|
log.Infof("正在检查协议更新...")
|
||||||
currentVersionName := device.Protocol.Version().SortVersionName
|
currentVersionName := device.Protocol.Version().SortVersionName
|
||||||
@ -291,7 +321,11 @@ func LoginInteract() {
|
|||||||
log.Infof("如果登录时出现版本过低错误, 可尝试使用 -update-protocol 参数启动")
|
log.Infof("如果登录时出现版本过低错误, 可尝试使用 -update-protocol 参数启动")
|
||||||
case !isTokenLogin:
|
case !isTokenLogin:
|
||||||
_ = device.Protocol.Version().UpdateFromJson(remoteVersion)
|
_ = device.Protocol.Version().UpdateFromJson(remoteVersion)
|
||||||
|
err := os.WriteFile(versionFile, remoteVersion, 0644)
|
||||||
log.Infof("协议版本已更新: %s -> %s", currentVersionName, remoteVersionName)
|
log.Infof("协议版本已更新: %s -> %s", currentVersionName, remoteVersionName)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln("更新协议版本缓存文件", versionFile, "失败:", err)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
log.Infof("检测到协议更新: %s -> %s", currentVersionName, remoteVersionName)
|
log.Infof("检测到协议更新: %s -> %s", currentVersionName, remoteVersionName)
|
||||||
log.Infof("由于使用了会话缓存, 无法自动更新协议, 请删除缓存后重试")
|
log.Infof("由于使用了会话缓存, 无法自动更新协议, 请删除缓存后重试")
|
||||||
@ -314,7 +348,7 @@ func LoginInteract() {
|
|||||||
}
|
}
|
||||||
var times uint = 1 // 重试次数
|
var times uint = 1 // 重试次数
|
||||||
var reLoginLock sync.Mutex
|
var reLoginLock sync.Mutex
|
||||||
cli.DisconnectedEvent.Subscribe(func(q *client.QQClient, e *client.ClientDisconnectedEvent) {
|
cli.DisconnectedEvent.Subscribe(func(_ *client.QQClient, e *client.ClientDisconnectedEvent) {
|
||||||
reLoginLock.Lock()
|
reLoginLock.Lock()
|
||||||
defer reLoginLock.Unlock()
|
defer reLoginLock.Unlock()
|
||||||
times = 1
|
times = 1
|
||||||
@ -364,7 +398,6 @@ func LoginInteract() {
|
|||||||
})
|
})
|
||||||
saveToken()
|
saveToken()
|
||||||
cli.AllowSlider = true
|
cli.AllowSlider = true
|
||||||
download.SetTimeout(time.Duration(base.HTTPTimeout) * time.Second) // 在登录完成后设置, 防止在堵塞协议更新
|
|
||||||
log.Infof("登录成功 欢迎使用: %v", cli.Nickname)
|
log.Infof("登录成功 欢迎使用: %v", cli.Nickname)
|
||||||
log.Info("开始加载好友列表...")
|
log.Info("开始加载好友列表...")
|
||||||
global.Check(cli.ReloadFriendList(), true)
|
global.Check(cli.ReloadFriendList(), true)
|
||||||
@ -428,7 +461,7 @@ func PasswordHashDecrypt(encryptedPasswordHash string, key []byte) ([]byte, erro
|
|||||||
func newClient() *client.QQClient {
|
func newClient() *client.QQClient {
|
||||||
c := client.NewClientEmpty()
|
c := client.NewClientEmpty()
|
||||||
c.UseFragmentMessage = base.ForceFragmented
|
c.UseFragmentMessage = base.ForceFragmented
|
||||||
c.OnServerUpdated(func(bot *client.QQClient, e *client.ServerUpdatedEvent) bool {
|
c.OnServerUpdated(func(_ *client.QQClient, _ *client.ServerUpdatedEvent) bool {
|
||||||
if !base.UseSSOAddress {
|
if !base.UseSSOAddress {
|
||||||
log.Infof("收到服务器地址更新通知, 根据配置文件已忽略.")
|
log.Infof("收到服务器地址更新通知, 根据配置文件已忽略.")
|
||||||
return false
|
return false
|
||||||
@ -460,7 +493,7 @@ func getRemoteLatestProtocolVersion(protocolType int) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
response, err := download.Request{URL: url}.Bytes()
|
response, err := download.Request{URL: url}.Bytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return download.Request{URL: "https://ghproxy.com/" + url}.Bytes()
|
return download.Request{URL: "https://mirror.ghproxy.com/" + url}.Bytes()
|
||||||
}
|
}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
427
cmd/gocq/qsign.go
Normal file
427
cmd/gocq/qsign.go
Normal file
@ -0,0 +1,427 @@
|
|||||||
|
package gocq
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
|
||||||
|
"github.com/Mrs4s/MiraiGo/utils"
|
||||||
|
|
||||||
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
|
"github.com/Mrs4s/go-cqhttp/internal/base"
|
||||||
|
"github.com/Mrs4s/go-cqhttp/internal/download"
|
||||||
|
"github.com/Mrs4s/go-cqhttp/modules/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type currentSignServer atomic.Pointer[config.SignServer]
|
||||||
|
|
||||||
|
func (c *currentSignServer) get() *config.SignServer {
|
||||||
|
if len(base.SignServers) == 1 {
|
||||||
|
// 只配置了一个签名服务时不检查以及切换, 在get阶段返回,防止返回nil导致其他bug(可能)
|
||||||
|
return &base.SignServers[0]
|
||||||
|
}
|
||||||
|
return (*atomic.Pointer[config.SignServer])(c).Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *currentSignServer) set(server *config.SignServer) {
|
||||||
|
(*atomic.Pointer[config.SignServer])(c).Store(server)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当前签名服务器
|
||||||
|
var ss currentSignServer
|
||||||
|
|
||||||
|
// 失败计数
|
||||||
|
type errconut atomic.Uintptr
|
||||||
|
|
||||||
|
func (ec *errconut) hasOver(count uintptr) bool {
|
||||||
|
return (*atomic.Uintptr)(ec).Load() > count
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ec *errconut) inc() {
|
||||||
|
(*atomic.Uintptr)(ec).Add(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errn errconut
|
||||||
|
|
||||||
|
// getAvaliableSignServer 获取可用的签名服务器,没有则返回空和相应错误
|
||||||
|
func getAvaliableSignServer() (*config.SignServer, error) {
|
||||||
|
cs := ss.get()
|
||||||
|
if cs != nil {
|
||||||
|
return cs, nil
|
||||||
|
}
|
||||||
|
if len(base.SignServers) == 0 {
|
||||||
|
return nil, errors.New("no sign server configured")
|
||||||
|
}
|
||||||
|
maxCount := base.Account.MaxCheckCount
|
||||||
|
if maxCount == 0 {
|
||||||
|
if errn.hasOver(3) {
|
||||||
|
log.Warn("已连续 3 次获取不到可用签名服务器,将固定使用主签名服务器")
|
||||||
|
ss.set(&base.SignServers[0])
|
||||||
|
return ss.get(), nil
|
||||||
|
}
|
||||||
|
} else if errn.hasOver(uintptr(maxCount)) {
|
||||||
|
log.Fatalf("获取可用签名服务器失败次数超过 %v 次, 正在离线", maxCount)
|
||||||
|
}
|
||||||
|
if cs != nil && len(cs.URL) > 0 {
|
||||||
|
log.Warnf("当前签名服务器 %v 不可用,正在查找可用服务器", cs.URL)
|
||||||
|
}
|
||||||
|
cs = asyncCheckServer(base.SignServers)
|
||||||
|
if cs == nil {
|
||||||
|
return nil, errors.New("no usable sign server")
|
||||||
|
}
|
||||||
|
return cs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isServerAvaliable(signServer string) bool {
|
||||||
|
resp, err := download.Request{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
URL: signServer,
|
||||||
|
}.WithTimeout(3 * time.Second).Bytes()
|
||||||
|
if err == nil && gjson.GetBytes(resp, "code").Int() == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
log.Warnf("签名服务器 %v 可能不可用,请求出现错误:%v", signServer, err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// asyncCheckServer 按同步顺序检查所有签名服务器直到找到可用的
|
||||||
|
func asyncCheckServer(servers []config.SignServer) *config.SignServer {
|
||||||
|
doRegister := sync.Once{}
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
wg.Add(len(servers))
|
||||||
|
for i, s := range servers {
|
||||||
|
go func(i int, server config.SignServer) {
|
||||||
|
defer wg.Done()
|
||||||
|
log.Infof("检查签名服务器:%v (%v/%v)", server.URL, i+1, len(servers))
|
||||||
|
if len(server.URL) < 4 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if isServerAvaliable(server.URL) {
|
||||||
|
doRegister.Do(func() {
|
||||||
|
ss.set(&server)
|
||||||
|
log.Infof("使用签名服务器 url=%v, key=%v, auth=%v", server.URL, server.Key, server.Authorization)
|
||||||
|
if base.Account.AutoRegister {
|
||||||
|
// 若配置了自动注册实例则在切换后注册实例,否则不需要注册,签名时由qsign自动注册
|
||||||
|
signRegister(base.Account.Uin, device.AndroidId, device.Guid, device.QImei36, server.Key)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}(i, s)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
return ss.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
请求签名服务器
|
||||||
|
|
||||||
|
url: api + params 组合的字符串,无须包含签名服务器地址
|
||||||
|
return: signServer, response, error
|
||||||
|
*/
|
||||||
|
func requestSignServer(method string, url string, headers map[string]string, body io.Reader) (string, []byte, error) {
|
||||||
|
signServer, e := getAvaliableSignServer()
|
||||||
|
if e != nil && len(signServer.URL) == 0 { // 没有可用的
|
||||||
|
log.Warnf("获取可用签名服务器出错:%v, 将使用主签名服务器进行签名", e)
|
||||||
|
errn.inc()
|
||||||
|
signServer = &base.SignServers[0] // 没有获取到时使用第一个
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(url, signServer.URL) {
|
||||||
|
url = strings.TrimSuffix(signServer.URL, "/") + "/" + strings.TrimPrefix(url, "/")
|
||||||
|
}
|
||||||
|
if headers == nil {
|
||||||
|
headers = map[string]string{}
|
||||||
|
}
|
||||||
|
auth := signServer.Authorization
|
||||||
|
if auth != "-" && auth != "" {
|
||||||
|
headers["Authorization"] = auth
|
||||||
|
}
|
||||||
|
req := download.Request{
|
||||||
|
Method: method,
|
||||||
|
Header: headers,
|
||||||
|
URL: url,
|
||||||
|
Body: body,
|
||||||
|
}.WithTimeout(time.Duration(base.SignServerTimeout) * time.Second)
|
||||||
|
resp, err := req.Bytes()
|
||||||
|
if err != nil {
|
||||||
|
ss.set(nil) // 标记为不可用
|
||||||
|
}
|
||||||
|
return signServer.URL, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func energy(uin uint64, id string, _ string, salt []byte) ([]byte, error) {
|
||||||
|
url := "custom_energy" + fmt.Sprintf("?data=%v&salt=%v&uin=%v&android_id=%v&guid=%v",
|
||||||
|
id, hex.EncodeToString(salt), uin, utils.B2S(device.AndroidId), hex.EncodeToString(device.Guid))
|
||||||
|
if base.IsBelow110 {
|
||||||
|
url = "custom_energy" + fmt.Sprintf("?data=%v&salt=%v", id, hex.EncodeToString(salt))
|
||||||
|
}
|
||||||
|
signServer, response, err := requestSignServer(http.MethodGet, url, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("获取T544 sign时出现错误: %v. server: %v", err, signServer)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data, err := hex.DecodeString(gjson.GetBytes(response, "data").String())
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("获取T544 sign时出现错误: %v (data: %v)", err, gjson.GetBytes(response, "data").String())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
log.Warnf("获取T544 sign时出现错误: %v.", "data is empty")
|
||||||
|
return nil, errors.New("data is empty")
|
||||||
|
}
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// signSubmit
|
||||||
|
// 提交回调 buffer
|
||||||
|
func signSubmit(uin string, cmd string, callbackID int64, buffer []byte, t string) {
|
||||||
|
buffStr := hex.EncodeToString(buffer)
|
||||||
|
if base.Debug {
|
||||||
|
tail := 64
|
||||||
|
endl := "..."
|
||||||
|
if len(buffStr) < tail {
|
||||||
|
tail = len(buffStr)
|
||||||
|
endl = "."
|
||||||
|
}
|
||||||
|
log.Debugf("submit (%v): uin=%v, cmd=%v, callbackID=%v, buffer=%v%s", t, uin, cmd, callbackID, buffStr[:tail], endl)
|
||||||
|
}
|
||||||
|
|
||||||
|
signServer, _, err := requestSignServer(
|
||||||
|
http.MethodGet,
|
||||||
|
"submit"+fmt.Sprintf("?uin=%v&cmd=%v&callback_id=%v&buffer=%v",
|
||||||
|
uin, cmd, callbackID, buffStr),
|
||||||
|
nil, nil,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("提交 callback 时出现错误: %v. server: %v", err, signServer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// signCallback
|
||||||
|
// 刷新 token 和签名的回调
|
||||||
|
func signCallback(uin string, results []gjson.Result, t string) {
|
||||||
|
for { // 等待至在线
|
||||||
|
if cli.Online.Load() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
for _, result := range results {
|
||||||
|
cmd := result.Get("cmd").String()
|
||||||
|
callbackID := result.Get("callbackId").Int()
|
||||||
|
body, _ := hex.DecodeString(result.Get("body").String())
|
||||||
|
ret, err := cli.SendSsoPacket(cmd, body)
|
||||||
|
if err != nil || len(ret) == 0 {
|
||||||
|
log.Warnf("Callback error: %v, or response data is empty", err)
|
||||||
|
continue // 发送 SsoPacket 出错或返回数据为空时跳过
|
||||||
|
}
|
||||||
|
signSubmit(uin, cmd, callbackID, ret, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func signRequset(seq uint64, uin string, cmd string, qua string, buff []byte) (sign []byte, extra []byte, token []byte, err error) {
|
||||||
|
headers := map[string]string{"Content-Type": "application/x-www-form-urlencoded"}
|
||||||
|
_, response, err := requestSignServer(
|
||||||
|
http.MethodPost,
|
||||||
|
"sign",
|
||||||
|
headers,
|
||||||
|
bytes.NewReader([]byte(fmt.Sprintf("uin=%v&qua=%s&cmd=%s&seq=%v&buffer=%v&android_id=%v&guid=%v",
|
||||||
|
uin, qua, cmd, seq, hex.EncodeToString(buff), utils.B2S(device.AndroidId), hex.EncodeToString(device.Guid)))),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
sign, _ = hex.DecodeString(gjson.GetBytes(response, "data.sign").String())
|
||||||
|
extra, _ = hex.DecodeString(gjson.GetBytes(response, "data.extra").String())
|
||||||
|
token, _ = hex.DecodeString(gjson.GetBytes(response, "data.token").String())
|
||||||
|
if !base.IsBelow110 {
|
||||||
|
go signCallback(uin, gjson.GetBytes(response, "data.requestCallback").Array(), "sign")
|
||||||
|
}
|
||||||
|
return sign, extra, token, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var registerLock sync.Mutex
|
||||||
|
|
||||||
|
func signRegister(uin int64, androidID, guid []byte, qimei36, key string) {
|
||||||
|
if base.IsBelow110 {
|
||||||
|
log.Warn("签名服务器版本低于1.1.0, 跳过实例注册")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
signServer, resp, err := requestSignServer(
|
||||||
|
http.MethodGet,
|
||||||
|
"register"+fmt.Sprintf("?uin=%v&android_id=%v&guid=%v&qimei36=%v&key=%s",
|
||||||
|
uin, utils.B2S(androidID), hex.EncodeToString(guid), qimei36, key),
|
||||||
|
nil, nil,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("注册QQ实例时出现错误: %v. server: %v", err, signServer)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
msg := gjson.GetBytes(resp, "msg")
|
||||||
|
if gjson.GetBytes(resp, "code").Int() != 0 {
|
||||||
|
log.Warnf("注册QQ实例时出现错误: %v. server: %v", msg, signServer)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Infof("注册QQ实例 %v 成功: %v", uin, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func signRefreshToken(uin string) error {
|
||||||
|
log.Info("正在刷新 token")
|
||||||
|
_, resp, err := requestSignServer(
|
||||||
|
http.MethodGet,
|
||||||
|
"request_token?uin="+uin,
|
||||||
|
nil, nil,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
msg := gjson.GetBytes(resp, "msg")
|
||||||
|
code := gjson.GetBytes(resp, "code")
|
||||||
|
if code.Int() != 0 {
|
||||||
|
return errors.New("code=" + code.String() + ", msg: " + msg.String())
|
||||||
|
}
|
||||||
|
go signCallback(uin, gjson.GetBytes(resp, "data").Array(), "request token")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var missTokenCount = uint64(0)
|
||||||
|
var lastToken = ""
|
||||||
|
|
||||||
|
func sign(seq uint64, uin string, cmd string, qua string, buff []byte) (sign []byte, extra []byte, token []byte, err error) {
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
sign, extra, token, err = signRequset(seq, uin, cmd, qua, buff)
|
||||||
|
cs := ss.get()
|
||||||
|
if cs == nil {
|
||||||
|
// 最好在请求后判断,否则若被设置为nil后不会再请求签名,
|
||||||
|
// 导致在下一次有请求签名服务操作之前,ss无法更新
|
||||||
|
err = errors.New("nil signserver")
|
||||||
|
log.Warn("nil sign-server") // 返回的err并不会log出来,加条日志
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("获取sso sign时出现错误: %v. server: %v", err, cs.URL)
|
||||||
|
}
|
||||||
|
if i > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
if (!base.IsBelow110) && base.Account.AutoRegister && err == nil && len(sign) == 0 {
|
||||||
|
if registerLock.TryLock() { // 避免并发时多处同时销毁并重新注册
|
||||||
|
log.Debugf("请求签名:cmd=%v, qua=%v, buff=%v", seq, cmd, hex.EncodeToString(buff))
|
||||||
|
log.Debugf("返回结果:sign=%v, extra=%v, token=%v",
|
||||||
|
hex.EncodeToString(sign), hex.EncodeToString(extra), hex.EncodeToString(token))
|
||||||
|
log.Warn("获取签名为空,实例可能丢失,正在尝试重新注册")
|
||||||
|
defer registerLock.Unlock()
|
||||||
|
err := signServerDestroy(uin)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln(err) // 实例真的丢失时则必出错,或许应该不 return , 以重新获取本次签名
|
||||||
|
// return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
signRegister(base.Account.Uin, device.AndroidId, device.Guid, device.QImei36, cs.Key)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (!base.IsBelow110) && base.Account.AutoRefreshToken && len(token) == 0 {
|
||||||
|
log.Warnf("token 已过期, 总丢失 token 次数为 %v", atomic.AddUint64(&missTokenCount, 1))
|
||||||
|
if registerLock.TryLock() {
|
||||||
|
defer registerLock.Unlock()
|
||||||
|
if err := signRefreshToken(uin); err != nil {
|
||||||
|
log.Warnf("刷新 token 出现错误: %v. server: %v", err, cs.URL)
|
||||||
|
} else {
|
||||||
|
log.Info("刷新 token 成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if tokenString := hex.EncodeToString(token); lastToken != tokenString {
|
||||||
|
log.Infof("token 已更新:%v -> %v", lastToken, tokenString)
|
||||||
|
lastToken = tokenString
|
||||||
|
}
|
||||||
|
rule := base.Account.RuleChangeSignServer
|
||||||
|
if (len(sign) == 0 && rule >= 1) || (len(token) == 0 && rule >= 2) {
|
||||||
|
ss.set(nil)
|
||||||
|
}
|
||||||
|
return sign, extra, token, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func signServerDestroy(uin string) error {
|
||||||
|
signServer, signVersion, err := signVersion()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "获取签名服务版本出现错误, server: %v", signServer)
|
||||||
|
}
|
||||||
|
if global.VersionNameCompare("v"+signVersion, "v1.1.6") {
|
||||||
|
return errors.Errorf("当前签名服务器版本 %v 低于 1.1.6,无法使用 destroy 接口", signVersion)
|
||||||
|
}
|
||||||
|
cs := ss.get()
|
||||||
|
if cs == nil {
|
||||||
|
return errors.New("nil signserver")
|
||||||
|
}
|
||||||
|
signServer, resp, err := requestSignServer(
|
||||||
|
http.MethodGet,
|
||||||
|
"destroy"+fmt.Sprintf("?uin=%v&key=%v", uin, cs.Key),
|
||||||
|
nil, nil,
|
||||||
|
)
|
||||||
|
if err != nil || gjson.GetBytes(resp, "code").Int() != 0 {
|
||||||
|
return errors.Wrapf(err, "destroy 实例出现错误, server: %v", signServer)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func signVersion() (signServer string, version string, err error) {
|
||||||
|
signServer, resp, err := requestSignServer(http.MethodGet, "", nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return signServer, "", err
|
||||||
|
}
|
||||||
|
if gjson.GetBytes(resp, "code").Int() == 0 {
|
||||||
|
return signServer, gjson.GetBytes(resp, "data.version").String(), nil
|
||||||
|
}
|
||||||
|
return signServer, "", errors.New("empty version")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定时刷新 token, interval 为间隔时间(分钟)
|
||||||
|
func signStartRefreshToken(interval int64) {
|
||||||
|
if interval <= 0 {
|
||||||
|
log.Warn("定时刷新 token 已关闭")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Infof("每 %v 分钟将刷新一次签名 token", interval)
|
||||||
|
if interval < 10 {
|
||||||
|
log.Warnf("间隔时间 %v 分钟较短,推荐 30~40 分钟", interval)
|
||||||
|
}
|
||||||
|
if interval > 60 {
|
||||||
|
log.Warn("间隔时间不能超过 60 分钟,已自动设置为 60 分钟")
|
||||||
|
interval = 60
|
||||||
|
}
|
||||||
|
t := time.NewTicker(time.Duration(interval) * time.Minute)
|
||||||
|
qqstr := strconv.FormatInt(base.Account.Uin, 10)
|
||||||
|
defer t.Stop()
|
||||||
|
for range t.C {
|
||||||
|
cs, master := ss.get(), &base.SignServers[0]
|
||||||
|
if (cs == nil || cs.URL != master.URL) && isServerAvaliable(master.URL) {
|
||||||
|
ss.set(master)
|
||||||
|
log.Infof("主签名服务器可用,已切换至主签名服务器 %v", master.URL)
|
||||||
|
}
|
||||||
|
cs = ss.get()
|
||||||
|
if cs == nil {
|
||||||
|
log.Warn("无法获得可用签名服务器,停止 token 定时刷新")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := signRefreshToken(qqstr)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("刷新 token 出现错误: %v. server: %v", err, cs.URL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
coolq/api.go
71
coolq/api.go
@ -617,6 +617,7 @@ func (bot *CQBot) CQUploadPrivateFile(userID int64, file, name string) global.MS
|
|||||||
log.Warnf("上传私聊文件 %v 失败: %+v", file, err)
|
log.Warnf("上传私聊文件 %v 失败: %+v", file, err)
|
||||||
return Failed(100, "OPEN_FILE_ERROR", "打开文件失败")
|
return Failed(100, "OPEN_FILE_ERROR", "打开文件失败")
|
||||||
}
|
}
|
||||||
|
defer func() { _ = fileBody.Close() }()
|
||||||
localFile := &client.LocalFile{
|
localFile := &client.LocalFile{
|
||||||
FileName: name,
|
FileName: name,
|
||||||
Body: fileBody,
|
Body: fileBody,
|
||||||
@ -758,7 +759,7 @@ func (bot *CQBot) CQSendGroupMessage(groupID int64, m gjson.Result, autoEscape b
|
|||||||
} else {
|
} else {
|
||||||
str := m.String()
|
str := m.String()
|
||||||
if str == "" {
|
if str == "" {
|
||||||
log.Warn("群消息发送失败: 信息为空.")
|
log.Warnf("群 %v 消息发送失败: 信息为空.", groupID)
|
||||||
return Failed(100, "EMPTY_MSG_ERROR", "消息为空")
|
return Failed(100, "EMPTY_MSG_ERROR", "消息为空")
|
||||||
}
|
}
|
||||||
if autoEscape {
|
if autoEscape {
|
||||||
@ -895,7 +896,7 @@ func (bot *CQBot) uploadForwardElement(m gjson.Result, target int64, sourceType
|
|||||||
SenderId: m.GetAttribute().SenderUin,
|
SenderId: m.GetAttribute().SenderUin,
|
||||||
SenderName: m.GetAttribute().SenderName,
|
SenderName: m.GetAttribute().SenderName,
|
||||||
Time: int32(msgTime),
|
Time: int32(msgTime),
|
||||||
Message: resolveElement(bot.ConvertContentMessage(m.GetContent(), mSource)),
|
Message: resolveElement(bot.ConvertContentMessage(m.GetContent(), mSource, false)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Warnf("警告: 引用消息 %v 错误或数据库未开启.", e.Get("data.id").Str)
|
log.Warnf("警告: 引用消息 %v 错误或数据库未开启.", e.Get("data.id").Str)
|
||||||
@ -970,17 +971,20 @@ func (bot *CQBot) CQSendGroupForwardMessage(groupID int64, m gjson.Result) globa
|
|||||||
if m.Type != gjson.JSON {
|
if m.Type != gjson.JSON {
|
||||||
return Failed(100)
|
return Failed(100)
|
||||||
}
|
}
|
||||||
|
source := message.Source{
|
||||||
|
SourceType: message.SourcePrivate,
|
||||||
|
PrimaryID: 0,
|
||||||
|
}
|
||||||
fe := bot.uploadForwardElement(m, groupID, message.SourceGroup)
|
fe := bot.uploadForwardElement(m, groupID, message.SourceGroup)
|
||||||
if fe == nil {
|
if fe == nil {
|
||||||
return Failed(100, "EMPTY_NODES", "未找到任何可发送的合并转发信息")
|
return Failed(100, "EMPTY_NODES", "未找到任何可发送的合并转发信息")
|
||||||
}
|
}
|
||||||
ret := bot.Client.SendGroupForwardMessage(groupID, fe)
|
ret := bot.Client.SendGroupForwardMessage(groupID, fe)
|
||||||
if ret == nil || ret.Id == -1 {
|
if ret == nil || ret.Id == -1 {
|
||||||
log.Warnf("合并转发(群)消息发送失败: 账号可能被风控.")
|
log.Warnf("合并转发(群 %v)消息发送失败: 账号可能被风控.", groupID)
|
||||||
return Failed(100, "SEND_MSG_API_ERROR", "请参考 go-cqhttp 端输出")
|
return Failed(100, "SEND_MSG_API_ERROR", "请参考 go-cqhttp 端输出")
|
||||||
}
|
}
|
||||||
mid := bot.InsertGroupMessage(ret)
|
mid := bot.InsertGroupMessage(ret, source)
|
||||||
log.Infof("发送群 %v(%v) 的合并转发消息: %v (%v)", groupID, groupID, limitedString(m.String()), mid)
|
log.Infof("发送群 %v(%v) 的合并转发消息: %v (%v)", groupID, groupID, limitedString(m.String()), mid)
|
||||||
return OK(global.MSG{
|
return OK(global.MSG{
|
||||||
"message_id": mid,
|
"message_id": mid,
|
||||||
@ -1003,7 +1007,7 @@ func (bot *CQBot) CQSendPrivateForwardMessage(userID int64, m gjson.Result) glob
|
|||||||
}
|
}
|
||||||
mid := bot.SendPrivateMessage(userID, 0, &message.SendingMessage{Elements: []message.IMessageElement{fe}})
|
mid := bot.SendPrivateMessage(userID, 0, &message.SendingMessage{Elements: []message.IMessageElement{fe}})
|
||||||
if mid == -1 {
|
if mid == -1 {
|
||||||
log.Warnf("合并转发(好友)消息发送失败: 账号可能被风控.")
|
log.Warnf("合并转发(好友 %v)消息发送失败: 账号可能被风控.", userID)
|
||||||
return Failed(100, "SEND_MSG_API_ERROR", "请参考 go-cqhttp 端输出")
|
return Failed(100, "SEND_MSG_API_ERROR", "请参考 go-cqhttp 端输出")
|
||||||
}
|
}
|
||||||
log.Infof("发送好友 %v(%v) 的合并转发消息: %v (%v)", userID, userID, limitedString(m.String()), mid)
|
log.Infof("发送好友 %v(%v) 的合并转发消息: %v (%v)", userID, userID, limitedString(m.String()), mid)
|
||||||
@ -1109,17 +1113,17 @@ 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)
|
noticeID, err := bot.Client.AddGroupNoticeWithPic(groupID, msg, data)
|
||||||
if err != nil {
|
|
||||||
return Failed(100, "SEND_NOTICE_ERROR", err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, 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())
|
||||||
}
|
}
|
||||||
|
return OK(global.MSG{"notice_id": noticeID})
|
||||||
}
|
}
|
||||||
return OK(nil)
|
noticeID, err := bot.Client.AddGroupNoticeSimple(groupID, msg)
|
||||||
|
if err != nil {
|
||||||
|
return Failed(100, "SEND_NOTICE_ERROR", err.Error())
|
||||||
|
}
|
||||||
|
return OK(global.MSG{"notice_id": noticeID})
|
||||||
}
|
}
|
||||||
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
@ -1148,13 +1152,15 @@ func (bot *CQBot) CQDelGroupMemo(groupID int64, fid string) global.MSG {
|
|||||||
// @rename(msg->message, block->reject_add_request)
|
// @rename(msg->message, block->reject_add_request)
|
||||||
func (bot *CQBot) CQSetGroupKick(groupID int64, userID int64, msg string, block bool) global.MSG {
|
func (bot *CQBot) CQSetGroupKick(groupID int64, userID int64, msg string, block bool) global.MSG {
|
||||||
if g := bot.Client.FindGroup(groupID); g != nil {
|
if g := bot.Client.FindGroup(groupID); g != nil {
|
||||||
if m := g.FindMember(userID); m != nil {
|
m := g.FindMember(userID)
|
||||||
err := m.Kick(msg, block)
|
if m == nil {
|
||||||
if err != nil {
|
return Failed(100, "MEMBER_NOT_FOUND", "人员不存在")
|
||||||
return Failed(100, "NOT_MANAGEABLE", "机器人权限不足")
|
|
||||||
}
|
|
||||||
return OK(nil)
|
|
||||||
}
|
}
|
||||||
|
err := m.Kick(msg, block)
|
||||||
|
if err != nil {
|
||||||
|
return Failed(100, "NOT_MANAGEABLE", "机器人权限不足")
|
||||||
|
}
|
||||||
|
return OK(nil)
|
||||||
}
|
}
|
||||||
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
@ -1382,33 +1388,42 @@ func (bot *CQBot) CQGetGroupHonorInfo(groupID int64, t string) global.MSG {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg["talkative_list"] = convertMem(honor.TalkativeList)
|
msg["talkative_list"] = convertMem(honor.TalkativeList)
|
||||||
|
} else {
|
||||||
|
log.Infof("获取群龙王出错:%v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if t == "performer" || t == "all" {
|
if t == "performer" || t == "all" {
|
||||||
if honor, err := bot.Client.GetGroupHonorInfo(groupID, client.Performer); err == nil {
|
if honor, err := bot.Client.GetGroupHonorInfo(groupID, client.Performer); err == nil {
|
||||||
msg["performer_lis"] = convertMem(honor.ActorList)
|
msg["performer_list"] = convertMem(honor.ActorList)
|
||||||
|
} else {
|
||||||
|
log.Infof("获取群聊之火出错:%v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if t == "legend" || t == "all" {
|
if t == "legend" || t == "all" {
|
||||||
if honor, err := bot.Client.GetGroupHonorInfo(groupID, client.Legend); err == nil {
|
if honor, err := bot.Client.GetGroupHonorInfo(groupID, client.Legend); err == nil {
|
||||||
msg["legend_list"] = convertMem(honor.LegendList)
|
msg["legend_list"] = convertMem(honor.LegendList)
|
||||||
|
} else {
|
||||||
|
log.Infof("获取群聊炽焰出错:%v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if t == "strong_newbie" || t == "all" {
|
if t == "strong_newbie" || t == "all" {
|
||||||
if honor, err := bot.Client.GetGroupHonorInfo(groupID, client.StrongNewbie); err == nil {
|
if honor, err := bot.Client.GetGroupHonorInfo(groupID, client.StrongNewbie); err == nil {
|
||||||
msg["strong_newbie_list"] = convertMem(honor.StrongNewbieList)
|
msg["strong_newbie_list"] = convertMem(honor.StrongNewbieList)
|
||||||
|
} else {
|
||||||
|
log.Infof("获取冒尖小春笋出错:%v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if t == "emotion" || t == "all" {
|
if t == "emotion" || t == "all" {
|
||||||
if honor, err := bot.Client.GetGroupHonorInfo(groupID, client.Emotion); err == nil {
|
if honor, err := bot.Client.GetGroupHonorInfo(groupID, client.Emotion); err == nil {
|
||||||
msg["emotion_list"] = convertMem(honor.EmotionList)
|
msg["emotion_list"] = convertMem(honor.EmotionList)
|
||||||
|
} else {
|
||||||
|
log.Infof("获取快乐之源出错:%v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK(msg)
|
return OK(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1683,9 +1698,9 @@ func (bot *CQBot) CQGetMessage(messageID int32) global.MSG {
|
|||||||
switch o := msg.(type) {
|
switch o := msg.(type) {
|
||||||
case *db.StoredGroupMessage:
|
case *db.StoredGroupMessage:
|
||||||
m["group_id"] = o.GroupCode
|
m["group_id"] = o.GroupCode
|
||||||
m["message"] = ToFormattedMessage(bot.ConvertContentMessage(o.Content, message.SourceGroup), message.Source{SourceType: message.SourceGroup, PrimaryID: o.GroupCode})
|
m["message"] = ToFormattedMessage(bot.ConvertContentMessage(o.Content, message.SourceGroup, false), message.Source{SourceType: message.SourceGroup, PrimaryID: o.GroupCode})
|
||||||
case *db.StoredPrivateMessage:
|
case *db.StoredPrivateMessage:
|
||||||
m["message"] = ToFormattedMessage(bot.ConvertContentMessage(o.Content, message.SourcePrivate), message.Source{SourceType: message.SourcePrivate})
|
m["message"] = ToFormattedMessage(bot.ConvertContentMessage(o.Content, message.SourcePrivate, false), message.Source{SourceType: message.SourcePrivate})
|
||||||
}
|
}
|
||||||
return OK(m)
|
return OK(m)
|
||||||
}
|
}
|
||||||
@ -1745,7 +1760,7 @@ func (bot *CQBot) CQGetGuildMessage(messageID string, noCache bool) global.MSG {
|
|||||||
"tiny_id": fU64(channelMsgByDB.Attribute.SenderTinyID),
|
"tiny_id": fU64(channelMsgByDB.Attribute.SenderTinyID),
|
||||||
"nickname": channelMsgByDB.Attribute.SenderName,
|
"nickname": channelMsgByDB.Attribute.SenderName,
|
||||||
}
|
}
|
||||||
m["message"] = ToFormattedMessage(bot.ConvertContentMessage(channelMsgByDB.Content, message.SourceGuildChannel), source)
|
m["message"] = ToFormattedMessage(bot.ConvertContentMessage(channelMsgByDB.Content, message.SourceGuildChannel, false), source)
|
||||||
}
|
}
|
||||||
case message.SourceGuildDirect:
|
case message.SourceGuildDirect:
|
||||||
// todo(mrs4s): 支持 direct 消息
|
// todo(mrs4s): 支持 direct 消息
|
||||||
@ -1788,10 +1803,14 @@ func (bot *CQBot) CQGetGroupMessageHistory(groupID int64, seq int64) global.MSG
|
|||||||
log.Warnf("获取群历史消息失败: %v", err)
|
log.Warnf("获取群历史消息失败: %v", err)
|
||||||
return Failed(100, "MESSAGES_API_ERROR", err.Error())
|
return Failed(100, "MESSAGES_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
|
source := message.Source{
|
||||||
|
SourceType: message.SourcePrivate,
|
||||||
|
PrimaryID: 0,
|
||||||
|
}
|
||||||
ms := make([]*event, 0, len(msg))
|
ms := make([]*event, 0, len(msg))
|
||||||
for _, m := range msg {
|
for _, m := range msg {
|
||||||
bot.checkMedia(m.Elements, groupID)
|
bot.checkMedia(m.Elements, groupID)
|
||||||
id := bot.InsertGroupMessage(m)
|
id := bot.InsertGroupMessage(m, source)
|
||||||
t := bot.formatGroupMessage(m)
|
t := bot.formatGroupMessage(m)
|
||||||
t.Others["message_id"] = id
|
t.Others["message_id"] = id
|
||||||
ms = append(ms, t)
|
ms = append(ms, t)
|
||||||
@ -2011,7 +2030,7 @@ func (bot *CQBot) CQGetVersionInfo() global.MSG {
|
|||||||
"protocol_version": "v11",
|
"protocol_version": "v11",
|
||||||
"coolq_directory": wd,
|
"coolq_directory": wd,
|
||||||
"coolq_edition": "pro",
|
"coolq_edition": "pro",
|
||||||
"go-cqhttp": true,
|
"go_cqhttp": true,
|
||||||
"plugin_version": "4.15.0",
|
"plugin_version": "4.15.0",
|
||||||
"plugin_build_number": 99,
|
"plugin_build_number": 99,
|
||||||
"plugin_build_configuration": "release",
|
"plugin_build_configuration": "release",
|
||||||
|
30
coolq/bot.go
30
coolq/bot.go
@ -288,7 +288,7 @@ func (bot *CQBot) SendGroupMessage(groupID int64, m *message.SendingMessage) (in
|
|||||||
log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupID, err)
|
log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupID, err)
|
||||||
return -1, errors.Wrap(err, "send group music share error")
|
return -1, errors.Wrap(err, "send group music share error")
|
||||||
}
|
}
|
||||||
return bot.InsertGroupMessage(ret), nil
|
return bot.InsertGroupMessage(ret, source), nil
|
||||||
case *message.AtElement:
|
case *message.AtElement:
|
||||||
if i.Target == 0 && group.SelfPermission() == client.Member {
|
if i.Target == 0 && group.SelfPermission() == client.Member {
|
||||||
e = message.NewText("@全体成员")
|
e = message.NewText("@全体成员")
|
||||||
@ -297,17 +297,17 @@ func (bot *CQBot) SendGroupMessage(groupID int64, m *message.SendingMessage) (in
|
|||||||
newElem = append(newElem, e)
|
newElem = append(newElem, e)
|
||||||
}
|
}
|
||||||
if len(newElem) == 0 {
|
if len(newElem) == 0 {
|
||||||
log.Warnf("群消息发送失败: 消息为空.")
|
log.Warnf("群 %v 消息发送失败: 消息为空.", groupID)
|
||||||
return -1, errors.New("empty message")
|
return -1, errors.New("empty message")
|
||||||
}
|
}
|
||||||
m.Elements = newElem
|
m.Elements = newElem
|
||||||
bot.checkMedia(newElem, groupID)
|
bot.checkMedia(newElem, groupID)
|
||||||
ret := bot.Client.SendGroupMessage(groupID, m)
|
ret := bot.Client.SendGroupMessage(groupID, m)
|
||||||
if ret == nil || ret.Id == -1 {
|
if ret == nil || ret.Id == -1 {
|
||||||
log.Warnf("群消息发送失败: 账号可能被风控.")
|
log.Warnf("群 %v 发送消息失败: 账号可能被风控.", groupID)
|
||||||
return -1, errors.New("send group message failed: blocked by server")
|
return -1, errors.New("send group message failed: blocked by server")
|
||||||
}
|
}
|
||||||
return bot.InsertGroupMessage(ret), nil
|
return bot.InsertGroupMessage(ret, source), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendPrivateMessage 发送私聊消息
|
// SendPrivateMessage 发送私聊消息
|
||||||
@ -357,7 +357,7 @@ func (bot *CQBot) SendPrivateMessage(target int64, groupID int64, m *message.Sen
|
|||||||
case bot.Client.FindFriend(target) != nil: // 双向好友
|
case bot.Client.FindFriend(target) != nil: // 双向好友
|
||||||
msg := bot.Client.SendPrivateMessage(target, m)
|
msg := bot.Client.SendPrivateMessage(target, m)
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
id = bot.InsertPrivateMessage(msg)
|
id = bot.InsertPrivateMessage(msg, source)
|
||||||
}
|
}
|
||||||
case ok || groupID != 0: // 临时会话
|
case ok || groupID != 0: // 临时会话
|
||||||
if !base.AllowTempSession {
|
if !base.AllowTempSession {
|
||||||
@ -395,7 +395,7 @@ func (bot *CQBot) SendPrivateMessage(target int64, groupID int64, m *message.Sen
|
|||||||
case unidirectionalFriendExists(): // 单向好友
|
case unidirectionalFriendExists(): // 单向好友
|
||||||
msg := bot.Client.SendPrivateMessage(target, m)
|
msg := bot.Client.SendPrivateMessage(target, m)
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
id = bot.InsertPrivateMessage(msg)
|
id = bot.InsertPrivateMessage(msg, source)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
nickname := "Unknown"
|
nickname := "Unknown"
|
||||||
@ -444,7 +444,7 @@ func (bot *CQBot) SendGuildChannelMessage(guildID, channelID uint64, m *message.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InsertGroupMessage 群聊消息入数据库
|
// InsertGroupMessage 群聊消息入数据库
|
||||||
func (bot *CQBot) InsertGroupMessage(m *message.GroupMessage) int32 {
|
func (bot *CQBot) InsertGroupMessage(m *message.GroupMessage, source message.Source) int32 {
|
||||||
t := &message.SendingMessage{Elements: m.Elements}
|
t := &message.SendingMessage{Elements: m.Elements}
|
||||||
replyElem := t.FirstOrNil(func(e message.IMessageElement) bool {
|
replyElem := t.FirstOrNil(func(e message.IMessageElement) bool {
|
||||||
_, ok := e.(*message.ReplyElement)
|
_, ok := e.(*message.ReplyElement)
|
||||||
@ -468,7 +468,7 @@ func (bot *CQBot) InsertGroupMessage(m *message.GroupMessage) int32 {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}(),
|
}(),
|
||||||
Content: ToMessageContent(m.Elements),
|
Content: ToMessageContent(m.Elements, source),
|
||||||
}
|
}
|
||||||
if replyElem != nil {
|
if replyElem != nil {
|
||||||
reply := replyElem.(*message.ReplyElement)
|
reply := replyElem.(*message.ReplyElement)
|
||||||
@ -476,7 +476,7 @@ func (bot *CQBot) InsertGroupMessage(m *message.GroupMessage) int32 {
|
|||||||
msg.QuotedInfo = &db.QuotedInfo{
|
msg.QuotedInfo = &db.QuotedInfo{
|
||||||
PrevID: encodeMessageID(m.GroupCode, reply.ReplySeq),
|
PrevID: encodeMessageID(m.GroupCode, reply.ReplySeq),
|
||||||
PrevGlobalID: db.ToGlobalID(m.GroupCode, reply.ReplySeq),
|
PrevGlobalID: db.ToGlobalID(m.GroupCode, reply.ReplySeq),
|
||||||
QuotedContent: ToMessageContent(reply.Elements),
|
QuotedContent: ToMessageContent(reply.Elements, source),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := db.InsertGroupMessage(msg); err != nil {
|
if err := db.InsertGroupMessage(msg); err != nil {
|
||||||
@ -487,7 +487,7 @@ func (bot *CQBot) InsertGroupMessage(m *message.GroupMessage) int32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InsertPrivateMessage 私聊消息入数据库
|
// InsertPrivateMessage 私聊消息入数据库
|
||||||
func (bot *CQBot) InsertPrivateMessage(m *message.PrivateMessage) int32 {
|
func (bot *CQBot) InsertPrivateMessage(m *message.PrivateMessage, source message.Source) int32 {
|
||||||
t := &message.SendingMessage{Elements: m.Elements}
|
t := &message.SendingMessage{Elements: m.Elements}
|
||||||
replyElem := t.FirstOrNil(func(e message.IMessageElement) bool {
|
replyElem := t.FirstOrNil(func(e message.IMessageElement) bool {
|
||||||
_, ok := e.(*message.ReplyElement)
|
_, ok := e.(*message.ReplyElement)
|
||||||
@ -511,7 +511,7 @@ func (bot *CQBot) InsertPrivateMessage(m *message.PrivateMessage) int32 {
|
|||||||
return m.Sender.Uin
|
return m.Sender.Uin
|
||||||
}(),
|
}(),
|
||||||
TargetUin: m.Target,
|
TargetUin: m.Target,
|
||||||
Content: ToMessageContent(m.Elements),
|
Content: ToMessageContent(m.Elements, source),
|
||||||
}
|
}
|
||||||
if replyElem != nil {
|
if replyElem != nil {
|
||||||
reply := replyElem.(*message.ReplyElement)
|
reply := replyElem.(*message.ReplyElement)
|
||||||
@ -519,7 +519,7 @@ func (bot *CQBot) InsertPrivateMessage(m *message.PrivateMessage) int32 {
|
|||||||
msg.QuotedInfo = &db.QuotedInfo{
|
msg.QuotedInfo = &db.QuotedInfo{
|
||||||
PrevID: encodeMessageID(reply.Sender, reply.ReplySeq),
|
PrevID: encodeMessageID(reply.Sender, reply.ReplySeq),
|
||||||
PrevGlobalID: db.ToGlobalID(reply.Sender, reply.ReplySeq),
|
PrevGlobalID: db.ToGlobalID(reply.Sender, reply.ReplySeq),
|
||||||
QuotedContent: ToMessageContent(reply.Elements),
|
QuotedContent: ToMessageContent(reply.Elements, source),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := db.InsertPrivateMessage(msg); err != nil {
|
if err := db.InsertPrivateMessage(msg); err != nil {
|
||||||
@ -562,6 +562,10 @@ func (bot *CQBot) InsertTempMessage(target int64, m *message.TempMessage) int32
|
|||||||
// InsertGuildChannelMessage 频道消息入数据库
|
// InsertGuildChannelMessage 频道消息入数据库
|
||||||
func (bot *CQBot) InsertGuildChannelMessage(m *message.GuildChannelMessage) string {
|
func (bot *CQBot) InsertGuildChannelMessage(m *message.GuildChannelMessage) string {
|
||||||
id := encodeGuildMessageID(m.GuildId, m.ChannelId, m.Id, message.SourceGuildChannel)
|
id := encodeGuildMessageID(m.GuildId, m.ChannelId, m.Id, message.SourceGuildChannel)
|
||||||
|
source := message.Source{
|
||||||
|
SourceType: message.SourceGuildChannel,
|
||||||
|
PrimaryID: int64(m.Sender.TinyId),
|
||||||
|
}
|
||||||
msg := &db.StoredGuildChannelMessage{
|
msg := &db.StoredGuildChannelMessage{
|
||||||
ID: id,
|
ID: id,
|
||||||
Attribute: &db.StoredGuildMessageAttribute{
|
Attribute: &db.StoredGuildMessageAttribute{
|
||||||
@ -573,7 +577,7 @@ func (bot *CQBot) InsertGuildChannelMessage(m *message.GuildChannelMessage) stri
|
|||||||
},
|
},
|
||||||
GuildID: m.GuildId,
|
GuildID: m.GuildId,
|
||||||
ChannelID: m.ChannelId,
|
ChannelID: m.ChannelId,
|
||||||
Content: ToMessageContent(m.Elements),
|
Content: ToMessageContent(m.Elements, source),
|
||||||
}
|
}
|
||||||
if err := db.InsertGuildChannelMessage(msg); err != nil {
|
if err := db.InsertGuildChannelMessage(msg); err != nil {
|
||||||
log.Warnf("记录聊天数据时出现错误: %v", err)
|
log.Warnf("记录聊天数据时出现错误: %v", err)
|
||||||
|
@ -92,7 +92,7 @@ func (bot *CQBot) formatGroupMessage(m *message.GroupMessage) *event {
|
|||||||
"name": m.Sender.AnonymousInfo.AnonymousNick,
|
"name": m.Sender.AnonymousInfo.AnonymousNick,
|
||||||
}
|
}
|
||||||
gm["sender"].(global.MSG)["nickname"] = "匿名消息"
|
gm["sender"].(global.MSG)["nickname"] = "匿名消息"
|
||||||
gm["sub_type"] = "anonymous"
|
typ = "message/group/anonymous"
|
||||||
} else {
|
} else {
|
||||||
group := bot.Client.FindGroup(m.GroupCode)
|
group := bot.Client.FindGroup(m.GroupCode)
|
||||||
mem := group.FindMember(m.Sender.Uin)
|
mem := group.FindMember(m.Sender.Uin)
|
||||||
|
@ -51,7 +51,7 @@ func replyID(r *message.ReplyElement, source message.Source) int32 {
|
|||||||
}
|
}
|
||||||
// 私聊时,部分(不确定)的账号会在 ReplyElement 中带有 GroupID 字段。
|
// 私聊时,部分(不确定)的账号会在 ReplyElement 中带有 GroupID 字段。
|
||||||
// 这里需要判断是由于 “直接回复” 功能,GroupID 为触发直接回复的来源那个群。
|
// 这里需要判断是由于 “直接回复” 功能,GroupID 为触发直接回复的来源那个群。
|
||||||
if source.SourceType == message.SourcePrivate && (r.Sender == source.PrimaryID || r.GroupID == source.PrimaryID) {
|
if source.SourceType == message.SourcePrivate && (r.Sender == source.PrimaryID || r.GroupID == source.PrimaryID || r.GroupID == 0) {
|
||||||
// 私聊似乎腾讯服务器有bug?
|
// 私聊似乎腾讯服务器有bug?
|
||||||
seq = int32(uint16(seq))
|
seq = int32(uint16(seq))
|
||||||
id = r.Sender
|
id = r.Sender
|
||||||
@ -243,6 +243,16 @@ func toElements(e []message.IMessageElement, source message.Source) (r []msg.Ele
|
|||||||
{K: "type", V: "sticker"},
|
{K: "type", V: "sticker"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
case *message.GroupFileElement:
|
||||||
|
m = msg.Element{
|
||||||
|
Type: "file",
|
||||||
|
Data: pairs{
|
||||||
|
{K: "path", V: o.Path},
|
||||||
|
{K: "name", V: o.Name},
|
||||||
|
{K: "size", V: strconv.FormatInt(o.Size, 10)},
|
||||||
|
{K: "busid", V: strconv.FormatInt(int64(o.Busid), 10)},
|
||||||
|
},
|
||||||
|
}
|
||||||
case *msg.LocalImage:
|
case *msg.LocalImage:
|
||||||
data := pairs{
|
data := pairs{
|
||||||
{K: "file", V: o.File},
|
{K: "file", V: o.File},
|
||||||
@ -266,10 +276,15 @@ func toElements(e []message.IMessageElement, source message.Source) (r []msg.Ele
|
|||||||
// ToMessageContent 将消息转换成 Content. 忽略 Reply
|
// ToMessageContent 将消息转换成 Content. 忽略 Reply
|
||||||
// 不同于 onebot 的 Array Message, 此函数转换出来的 Content 的 data 段为实际类型
|
// 不同于 onebot 的 Array Message, 此函数转换出来的 Content 的 data 段为实际类型
|
||||||
// 方便数据库查询
|
// 方便数据库查询
|
||||||
func ToMessageContent(e []message.IMessageElement) (r []global.MSG) {
|
func ToMessageContent(e []message.IMessageElement, source message.Source) (r []global.MSG) {
|
||||||
for _, elem := range e {
|
for _, elem := range e {
|
||||||
var m global.MSG
|
var m global.MSG
|
||||||
switch o := elem.(type) {
|
switch o := elem.(type) {
|
||||||
|
case *message.ReplyElement:
|
||||||
|
m = global.MSG{
|
||||||
|
"type": "reply",
|
||||||
|
"data": global.MSG{"id": replyID(o, source)},
|
||||||
|
}
|
||||||
case *message.TextElement:
|
case *message.TextElement:
|
||||||
m = global.MSG{
|
m = global.MSG{
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@ -373,6 +388,11 @@ func ToMessageContent(e []message.IMessageElement) (r []global.MSG) {
|
|||||||
"type": "face",
|
"type": "face",
|
||||||
"data": global.MSG{"id": o.ID, "type": "sticker"},
|
"data": global.MSG{"id": o.ID, "type": "sticker"},
|
||||||
}
|
}
|
||||||
|
case *message.GroupFileElement:
|
||||||
|
m = global.MSG{
|
||||||
|
"type": "file",
|
||||||
|
"data": global.MSG{"path": o.Path, "name": o.Name, "size": strconv.FormatInt(o.Size, 10), "busid": strconv.FormatInt(int64(o.Busid), 10)},
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -384,7 +404,7 @@ func ToMessageContent(e []message.IMessageElement) (r []global.MSG) {
|
|||||||
// ConvertStringMessage 将消息字符串转为消息元素数组
|
// ConvertStringMessage 将消息字符串转为消息元素数组
|
||||||
func (bot *CQBot) ConvertStringMessage(spec *onebot.Spec, raw string, sourceType message.SourceType) (r []message.IMessageElement) {
|
func (bot *CQBot) ConvertStringMessage(spec *onebot.Spec, raw string, sourceType message.SourceType) (r []message.IMessageElement) {
|
||||||
elems := msg.ParseString(raw)
|
elems := msg.ParseString(raw)
|
||||||
return bot.ConvertElements(spec, elems, sourceType)
|
return bot.ConvertElements(spec, elems, sourceType, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertObjectMessage 将消息JSON对象转为消息元素数组
|
// ConvertObjectMessage 将消息JSON对象转为消息元素数组
|
||||||
@ -393,11 +413,11 @@ func (bot *CQBot) ConvertObjectMessage(spec *onebot.Spec, m gjson.Result, source
|
|||||||
return bot.ConvertStringMessage(spec, m.Str, sourceType)
|
return bot.ConvertStringMessage(spec, m.Str, sourceType)
|
||||||
}
|
}
|
||||||
elems := msg.ParseObject(m)
|
elems := msg.ParseObject(m)
|
||||||
return bot.ConvertElements(spec, elems, sourceType)
|
return bot.ConvertElements(spec, elems, sourceType, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertContentMessage 将数据库用的 content 转换为消息元素数组
|
// ConvertContentMessage 将数据库用的 content 转换为消息元素数组
|
||||||
func (bot *CQBot) ConvertContentMessage(content []global.MSG, sourceType message.SourceType) (r []message.IMessageElement) {
|
func (bot *CQBot) ConvertContentMessage(content []global.MSG, sourceType message.SourceType, noReply bool) (r []message.IMessageElement) {
|
||||||
elems := make([]msg.Element, len(content))
|
elems := make([]msg.Element, len(content))
|
||||||
for i, v := range content {
|
for i, v := range content {
|
||||||
elem := msg.Element{Type: v["type"].(string)}
|
elem := msg.Element{Type: v["type"].(string)}
|
||||||
@ -407,13 +427,16 @@ func (bot *CQBot) ConvertContentMessage(content []global.MSG, sourceType message
|
|||||||
}
|
}
|
||||||
elems[i] = elem
|
elems[i] = elem
|
||||||
}
|
}
|
||||||
return bot.ConvertElements(onebot.V11, elems, sourceType)
|
return bot.ConvertElements(onebot.V11, elems, sourceType, noReply)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertElements 将解码后的消息数组转换为MiraiGo表示
|
// ConvertElements 将解码后的消息数组转换为MiraiGo表示
|
||||||
func (bot *CQBot) ConvertElements(spec *onebot.Spec, elems []msg.Element, sourceType message.SourceType) (r []message.IMessageElement) {
|
func (bot *CQBot) ConvertElements(spec *onebot.Spec, elems []msg.Element, sourceType message.SourceType, noReply bool) (r []message.IMessageElement) {
|
||||||
var replyCount int
|
var replyCount int
|
||||||
for _, elem := range elems {
|
for _, elem := range elems {
|
||||||
|
if noReply && elem.Type == "reply" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
me, err := bot.ConvertElement(spec, elem, sourceType)
|
me, err := bot.ConvertElement(spec, elem, sourceType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: don't use cqcode format
|
// TODO: don't use cqcode format
|
||||||
@ -497,7 +520,7 @@ func (bot *CQBot) reply(spec *onebot.Spec, elem msg.Element, sourceType message.
|
|||||||
ReplySeq: org.GetAttribute().MessageSeq,
|
ReplySeq: org.GetAttribute().MessageSeq,
|
||||||
Sender: org.GetAttribute().SenderUin,
|
Sender: org.GetAttribute().SenderUin,
|
||||||
Time: int32(org.GetAttribute().Timestamp),
|
Time: int32(org.GetAttribute().Timestamp),
|
||||||
Elements: bot.ConvertContentMessage(org.GetContent(), sourceType),
|
Elements: bot.ConvertContentMessage(org.GetContent(), sourceType, true),
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -713,7 +736,7 @@ func (bot *CQBot) ConvertElement(spec *onebot.Spec, elem msg.Element, sourceType
|
|||||||
MusicType: message.CloudMusic,
|
MusicType: message.CloudMusic,
|
||||||
Title: info.Get("name").String(),
|
Title: info.Get("name").String(),
|
||||||
Summary: artistName,
|
Summary: artistName,
|
||||||
Url: "https://y.music.163.com/m/song/" + id,
|
Url: "https://music.163.com/song/?id=" + id,
|
||||||
PictureUrl: info.Get("album.picUrl").String(),
|
PictureUrl: info.Get("album.picUrl").String(),
|
||||||
MusicUrl: "https://music.163.com/song/media/outer/url?id=" + id,
|
MusicUrl: "https://music.163.com/song/media/outer/url?id=" + id,
|
||||||
}, nil
|
}, nil
|
||||||
@ -841,6 +864,17 @@ func (bot *CQBot) ConvertElement(spec *onebot.Spec, elem msg.Element, sourceType
|
|||||||
v.File = cacheFile
|
v.File = cacheFile
|
||||||
}
|
}
|
||||||
return v, nil
|
return v, nil
|
||||||
|
case "file":
|
||||||
|
path := elem.Get("path")
|
||||||
|
name := elem.Get("name")
|
||||||
|
size, _ := strconv.ParseInt(elem.Get("size"), 10, 64)
|
||||||
|
busid, _ := strconv.ParseInt(elem.Get("busid"), 10, 64)
|
||||||
|
return &message.GroupFileElement{
|
||||||
|
Name: name,
|
||||||
|
Size: size,
|
||||||
|
Path: path,
|
||||||
|
Busid: int32(busid),
|
||||||
|
}, nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("unsupported message type: " + elem.Type)
|
return nil, errors.New("unsupported message type: " + elem.Type)
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ func (bot *CQBot) privateMessageEvent(_ *client.QQClient, m *message.PrivateMess
|
|||||||
PrimaryID: m.Sender.Uin,
|
PrimaryID: m.Sender.Uin,
|
||||||
}
|
}
|
||||||
cqm := toStringMessage(m.Elements, source)
|
cqm := toStringMessage(m.Elements, source)
|
||||||
id := bot.InsertPrivateMessage(m)
|
id := bot.InsertPrivateMessage(m, source)
|
||||||
log.Infof("收到好友 %v(%v) 的消息: %v (%v)", m.Sender.DisplayName(), m.Sender.Uin, cqm, id)
|
log.Infof("收到好友 %v(%v) 的消息: %v (%v)", m.Sender.DisplayName(), m.Sender.Uin, cqm, id)
|
||||||
typ := "message/private/friend"
|
typ := "message/private/friend"
|
||||||
if m.Sender.Uin == bot.Client.Uin {
|
if m.Sender.Uin == bot.Client.Uin {
|
||||||
@ -118,7 +118,7 @@ func (bot *CQBot) groupMessageEvent(c *client.QQClient, m *message.GroupMessage)
|
|||||||
"url": c.GetGroupFileUrl(m.GroupCode, file.Path, file.Busid),
|
"url": c.GetGroupFileUrl(m.GroupCode, file.Path, file.Busid),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return
|
// return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
source := message.Source{
|
source := message.Source{
|
||||||
@ -126,7 +126,7 @@ func (bot *CQBot) groupMessageEvent(c *client.QQClient, m *message.GroupMessage)
|
|||||||
PrimaryID: m.GroupCode,
|
PrimaryID: m.GroupCode,
|
||||||
}
|
}
|
||||||
cqm := toStringMessage(m.Elements, source)
|
cqm := toStringMessage(m.Elements, source)
|
||||||
id := bot.InsertGroupMessage(m)
|
id := bot.InsertGroupMessage(m, source)
|
||||||
log.Infof("收到群 %v(%v) 内 %v(%v) 的消息: %v (%v)", m.GroupName, m.GroupCode, m.Sender.DisplayName(), m.Sender.Uin, cqm, id)
|
log.Infof("收到群 %v(%v) 内 %v(%v) 的消息: %v (%v)", m.GroupName, m.GroupCode, m.Sender.DisplayName(), m.Sender.Uin, cqm, id)
|
||||||
gm := bot.formatGroupMessage(m)
|
gm := bot.formatGroupMessage(m)
|
||||||
if gm == nil {
|
if gm == nil {
|
||||||
|
@ -17,4 +17,4 @@ chown -R ${UID}:${GID} /app /data
|
|||||||
chmod +x /app/cqhttp
|
chmod +x /app/cqhttp
|
||||||
|
|
||||||
echo "Starting..."
|
echo "Starting..."
|
||||||
su-exec ${USER} /app/cqhttp
|
su-exec ${USER} /app/cqhttp "$@"
|
||||||
|
41
go.mod
41
go.mod
@ -3,28 +3,28 @@ module github.com/Mrs4s/go-cqhttp
|
|||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/FloatTech/sqlite v1.5.7
|
github.com/FloatTech/sqlite v1.6.3
|
||||||
github.com/Microsoft/go-winio v0.6.0
|
github.com/Microsoft/go-winio v0.6.2-0.20230724192519-b29bbd58a65a
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20230401072048-f8d9841755b5
|
github.com/Mrs4s/MiraiGo v0.0.0-20230823050531-a8213e127b2b
|
||||||
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.20220227141055-9b2c6168c9c5
|
||||||
github.com/fumiama/go-base16384 v1.6.1
|
github.com/fumiama/go-base16384 v1.7.0
|
||||||
github.com/fumiama/go-hide-param v0.1.4
|
github.com/fumiama/go-hide-param v0.1.4
|
||||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
||||||
github.com/mattn/go-colorable v0.1.13
|
github.com/mattn/go-colorable v0.1.13
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/segmentio/asm v1.2.0
|
github.com/segmentio/asm v1.2.0
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/stretchr/testify v1.8.1
|
github.com/stretchr/testify v1.8.1
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
github.com/tidwall/gjson v1.14.4
|
github.com/tidwall/gjson v1.15.0
|
||||||
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.12.0
|
||||||
golang.org/x/crypto v0.3.0
|
golang.org/x/crypto v0.17.0
|
||||||
golang.org/x/image v0.5.0
|
golang.org/x/image v0.10.0
|
||||||
golang.org/x/sys v0.2.0
|
golang.org/x/sys v0.15.0
|
||||||
golang.org/x/term v0.2.0
|
golang.org/x/term v0.15.0
|
||||||
golang.org/x/time v0.2.0
|
golang.org/x/time v0.3.0
|
||||||
gopkg.ilharper.com/x/isatty v1.1.1
|
gopkg.ilharper.com/x/isatty v1.1.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
@ -39,6 +39,7 @@ require (
|
|||||||
github.com/jonboulle/clockwork v0.3.0 // indirect
|
github.com/jonboulle/clockwork v0.3.0 // indirect
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||||
github.com/klauspost/compress v1.13.6 // indirect
|
github.com/klauspost/compress v1.13.6 // indirect
|
||||||
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/lestrrat-go/strftime v1.0.6 // indirect
|
github.com/lestrrat-go/strftime v1.0.6 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||||
@ -48,13 +49,13 @@ require (
|
|||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
github.com/tidwall/pretty v1.2.0 // indirect
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
github.com/xdg-go/scram v1.1.1 // indirect
|
github.com/xdg-go/scram v1.1.2 // indirect
|
||||||
github.com/xdg-go/stringprep v1.0.3 // indirect
|
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||||
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.12.0 // indirect
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
|
golang.org/x/sync v0.3.0 // indirect
|
||||||
golang.org/x/text v0.7.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/tools v0.1.12 // indirect
|
golang.org/x/tools v0.11.0 // 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
|
||||||
modernc.org/ccgo/v3 v3.16.13 // indirect
|
modernc.org/ccgo/v3 v3.16.13 // indirect
|
||||||
|
155
go.sum
155
go.sum
@ -1,48 +1,40 @@
|
|||||||
github.com/FloatTech/sqlite v1.5.7 h1:Bvo4LSojcZ6dVtbHrkqvt6z4v8e+sj0G5PSUIvdawsk=
|
github.com/FloatTech/sqlite v1.6.3 h1:MQkqBNlkPuCoKQQgoNLuTL/2Ci3tBTFAnVYBdD0Wy4M=
|
||||||
github.com/FloatTech/sqlite v1.5.7/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY=
|
github.com/FloatTech/sqlite v1.6.3/go.mod h1:zFbHzRfB+CJ+VidfjuVbrcin3DAz283F7hF1hIeHzpY=
|
||||||
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw=
|
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJGLDNIdRX3BI546D3O7k7vrVueZw=
|
||||||
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.2-0.20230724192519-b29bbd58a65a h1:aU1703IHxupjzipvhu16qYKLMR03e+8WuNR+JMsKfGU=
|
||||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
github.com/Microsoft/go-winio v0.6.2-0.20230724192519-b29bbd58a65a/go.mod h1:OZqLNXdYJHmx7aqq/T6wAdFEdoGm5nmIfC4kU7M8P8o=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20230401072048-f8d9841755b5 h1:E4fIQ0l/LNZK44NjdViRb/hx4cIeHXyQFPzzkx7cjVE=
|
github.com/Mrs4s/MiraiGo v0.0.0-20230823050531-a8213e127b2b h1:0GG6kDFgzie0HNdlkrgPwyX4WqUjckTP1xTM4cYaC2g=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20230401072048-f8d9841755b5/go.mod h1:mU3fBFU+7eO0kaGes7YRKtzIDtwIU84nSSwTV7NK2b0=
|
github.com/Mrs4s/MiraiGo v0.0.0-20230823050531-a8213e127b2b/go.mod h1:mU3fBFU+7eO0kaGes7YRKtzIDtwIU84nSSwTV7NK2b0=
|
||||||
github.com/RomiChan/protobuf v0.1.1-0.20230204044148-2ed269a2e54d h1:/Xuj3fIiMY2ls1TwvPKmaqQrtJsPY+c9s+0lOScVHd8=
|
github.com/RomiChan/protobuf v0.1.1-0.20230204044148-2ed269a2e54d h1:/Xuj3fIiMY2ls1TwvPKmaqQrtJsPY+c9s+0lOScVHd8=
|
||||||
github.com/RomiChan/protobuf v0.1.1-0.20230204044148-2ed269a2e54d/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.20220227141055-9b2c6168c9c5 h1:bBmmB7he0iVN4m5mcehfheeRUEer/Avo4ujnxI3uCqs=
|
||||||
github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc/go.mod h1:OMmITAib6POA37xCichWM0aRnoVpSMZO1rB/G01wrr0=
|
github.com/RomiChan/websocket v1.4.3-0.20220227141055-9b2c6168c9c5/go.mod h1:0UcFaCkhp6vZw6l5Dpq0Dp673CoF9GdvA8lTfst0GiU=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
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=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
github.com/fumiama/go-base16384 v1.7.0 h1:6fep7XPQWxRlh4Hu+KsdH+6+YdUp+w6CwRXtMWSsXCA=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fumiama/go-base16384 v1.7.0/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
||||||
github.com/fumiama/go-base16384 v1.6.1 h1:4yb4JgmBJDnQtq3XGXXdLrVwEnRpjhMUt4eAcsNeA30=
|
|
||||||
github.com/fumiama/go-base16384 v1.6.1/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
|
|
||||||
github.com/fumiama/go-hide-param v0.1.4 h1:y7TRTzZMdCH9GOXnIzU3B+1BSkcmvejVGmGsz4t0DGU=
|
github.com/fumiama/go-hide-param v0.1.4 h1:y7TRTzZMdCH9GOXnIzU3B+1BSkcmvejVGmGsz4t0DGU=
|
||||||
github.com/fumiama/go-hide-param v0.1.4/go.mod h1:vJkQlJIEI56nIyp7tCQu1/2QOyKtZpudsnJkGk9U1aY=
|
github.com/fumiama/go-hide-param v0.1.4/go.mod h1:vJkQlJIEI56nIyp7tCQu1/2QOyKtZpudsnJkGk9U1aY=
|
||||||
github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
|
github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
|
||||||
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
|
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
|
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
|
||||||
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||||
@ -50,11 +42,10 @@ 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.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
|
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
|
||||||
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
|
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
|
||||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
|
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
|
||||||
@ -69,17 +60,14 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
|||||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||||
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
|
||||||
github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
|
github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
|
||||||
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
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=
|
||||||
@ -87,126 +75,115 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
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.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
github.com/tidwall/gjson v1.15.0 h1:5n/pM+v3r5ujuNl4YLZLsQ+UE5jlkLVm7jMzT5Mpolw=
|
||||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.15.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
|
||||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/wdvxdr1123/go-silk v0.0.0-20210316130616-d47b553def60 h1:lRKf10iIOW0VsH5WDF621ihzR+R2wEBZVtNRHuLLCb4=
|
github.com/wdvxdr1123/go-silk v0.0.0-20210316130616-d47b553def60 h1:lRKf10iIOW0VsH5WDF621ihzR+R2wEBZVtNRHuLLCb4=
|
||||||
github.com/wdvxdr1123/go-silk v0.0.0-20210316130616-d47b553def60/go.mod h1:ecFKZPX81BaB70I6ruUgEwYcDOtuNgJGnjdK+MIl5ko=
|
github.com/wdvxdr1123/go-silk v0.0.0-20210316130616-d47b553def60/go.mod h1:ecFKZPX81BaB70I6ruUgEwYcDOtuNgJGnjdK+MIl5ko=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
|
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||||
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
|
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||||
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
|
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||||
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
|
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||||
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=
|
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.12.0 h1:aPx33jmn/rQuJXPQLZQ8NtfPQG8CaqgLThFtqRb0PiE=
|
||||||
go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
|
go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0=
|
||||||
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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
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.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
|
golang.org/x/image v0.10.0 h1:gXjUUtwtx5yOE0VKWq1CH4IJAClq4UGgUA3i+rpON9M=
|
||||||
golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
|
golang.org/x/image v0.10.0/go.mod h1:jtrku+n79PfroUbvDdeUWMAI+heR786BofxrbiSF+J0=
|
||||||
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/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||||
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
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-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-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.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||||
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-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-20220722155255-886fb9371eb4/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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||||
|
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
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=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
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-20220520151302-bc2c85ada10a/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-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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||||
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
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.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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||||
|
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
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=
|
||||||
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.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
|
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
|
golang.org/x/time v0.3.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.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/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
|
||||||
|
golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
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.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
gopkg.ilharper.com/x/isatty v1.1.1 h1:RAg32Pxq/nIK4AVtdm9RBqxsxZZX1uRKRSS21E5SHMk=
|
gopkg.ilharper.com/x/isatty v1.1.1 h1:RAg32Pxq/nIK4AVtdm9RBqxsxZZX1uRKRSS21E5SHMk=
|
||||||
gopkg.ilharper.com/x/isatty v1.1.1/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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
@ -23,23 +23,25 @@ var (
|
|||||||
|
|
||||||
// config file flags
|
// config file flags
|
||||||
var (
|
var (
|
||||||
Debug bool // 是否开启 debug 模式
|
Debug bool // 是否开启 debug 模式
|
||||||
RemoveReplyAt bool // 是否删除reply后的at
|
RemoveReplyAt bool // 是否删除reply后的at
|
||||||
ExtraReplyData bool // 是否上报额外reply信息
|
ExtraReplyData bool // 是否上报额外reply信息
|
||||||
IgnoreInvalidCQCode bool // 是否忽略无效CQ码
|
IgnoreInvalidCQCode bool // 是否忽略无效CQ码
|
||||||
SplitURL bool // 是否分割URL
|
SplitURL bool // 是否分割URL
|
||||||
ForceFragmented bool // 是否启用强制分片
|
ForceFragmented bool // 是否启用强制分片
|
||||||
SkipMimeScan bool // 是否跳过Mime扫描
|
SkipMimeScan bool // 是否跳过Mime扫描
|
||||||
ConvertWebpImage bool // 是否转换Webp图片
|
ConvertWebpImage bool // 是否转换Webp图片
|
||||||
ReportSelfMessage bool // 是否上报自身消息
|
ReportSelfMessage bool // 是否上报自身消息
|
||||||
UseSSOAddress bool // 是否使用服务器下发的新地址进行重连
|
UseSSOAddress bool // 是否使用服务器下发的新地址进行重连
|
||||||
LogForceNew bool // 是否在每次启动时强制创建全新的文件储存日志
|
LogForceNew bool // 是否在每次启动时强制创建全新的文件储存日志
|
||||||
LogColorful bool // 是否启用日志颜色
|
LogColorful bool // 是否启用日志颜色
|
||||||
FastStart bool // 是否为快速启动
|
FastStart bool // 是否为快速启动
|
||||||
AllowTempSession bool // 是否允许发送临时会话信息
|
AllowTempSession bool // 是否允许发送临时会话信息
|
||||||
UpdateProtocol bool // 是否更新协议
|
UpdateProtocol bool // 是否更新协议
|
||||||
SignServerOverwrite string // 使用特定的服务器进行签名
|
SignServers []config.SignServer // 使用特定的服务器进行签名
|
||||||
HTTPTimeout int
|
IsBelow110 bool // 签名服务器版本是否低于1.1.0及以下
|
||||||
|
HTTPTimeout int // download 超时时间
|
||||||
|
SignServerTimeout int // 签名服务器超时时间
|
||||||
|
|
||||||
PostFormat string // 上报格式 string or array
|
PostFormat string // 上报格式 string or array
|
||||||
Proxy string // 存储 proxy_rewrite,用于设置代理
|
Proxy string // 存储 proxy_rewrite,用于设置代理
|
||||||
@ -64,7 +66,6 @@ func Parse() {
|
|||||||
d := flag.Bool("D", false, "debug mode")
|
d := flag.Bool("D", false, "debug mode")
|
||||||
flag.BoolVar(&FastStart, "faststart", false, "skip waiting 5 seconds")
|
flag.BoolVar(&FastStart, "faststart", false, "skip waiting 5 seconds")
|
||||||
flag.BoolVar(&UpdateProtocol, "update-protocol", false, "update protocol")
|
flag.BoolVar(&UpdateProtocol, "update-protocol", false, "update protocol")
|
||||||
flag.StringVar(&SignServerOverwrite, "sign-server", "", "use special server to sign tlv")
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if *d {
|
if *d {
|
||||||
@ -89,7 +90,10 @@ func Init() {
|
|||||||
ReportSelfMessage = conf.Message.ReportSelfMessage
|
ReportSelfMessage = conf.Message.ReportSelfMessage
|
||||||
UseSSOAddress = conf.Account.UseSSOAddress
|
UseSSOAddress = conf.Account.UseSSOAddress
|
||||||
AllowTempSession = conf.Account.AllowTempSession
|
AllowTempSession = conf.Account.AllowTempSession
|
||||||
|
SignServers = conf.Account.SignServers
|
||||||
|
IsBelow110 = conf.Account.IsBelow110
|
||||||
HTTPTimeout = conf.Message.HTTPTimeout
|
HTTPTimeout = conf.Message.HTTPTimeout
|
||||||
|
SignServerTimeout = int(conf.Account.SignServerTimeout)
|
||||||
}
|
}
|
||||||
{ // others
|
{ // others
|
||||||
Proxy = conf.Message.ProxyRewrite
|
Proxy = conf.Message.ProxyRewrite
|
||||||
|
@ -15,26 +15,15 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/RomiChan/syncx"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
|
|
||||||
"github.com/Mrs4s/go-cqhttp/internal/base"
|
"github.com/Mrs4s/go-cqhttp/internal/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
var client = &http.Client{
|
var client = newClient(time.Second * 15)
|
||||||
Transport: &http.Transport{
|
var clients syncx.Map[time.Duration, *http.Client]
|
||||||
Proxy: func(request *http.Request) (*url.URL, error) {
|
|
||||||
if base.Proxy == "" {
|
|
||||||
return http.ProxyFromEnvironment(request)
|
|
||||||
}
|
|
||||||
return url.Parse(base.Proxy)
|
|
||||||
},
|
|
||||||
// Disable http2
|
|
||||||
TLSNextProto: map[string]func(authority string, c *tls.Conn) http.RoundTripper{},
|
|
||||||
MaxIdleConnsPerHost: 999,
|
|
||||||
},
|
|
||||||
Timeout: time.Second * 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
var clienth2 = &http.Client{
|
var clienth2 = &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
@ -47,7 +36,24 @@ var clienth2 = &http.Client{
|
|||||||
ForceAttemptHTTP2: true,
|
ForceAttemptHTTP2: true,
|
||||||
MaxIdleConnsPerHost: 999,
|
MaxIdleConnsPerHost: 999,
|
||||||
},
|
},
|
||||||
Timeout: time.Second * 5,
|
Timeout: time.Second * 15,
|
||||||
|
}
|
||||||
|
|
||||||
|
func newClient(t time.Duration) *http.Client {
|
||||||
|
return &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
Proxy: func(request *http.Request) (*url.URL, error) {
|
||||||
|
if base.Proxy == "" {
|
||||||
|
return http.ProxyFromEnvironment(request)
|
||||||
|
}
|
||||||
|
return url.Parse(base.Proxy)
|
||||||
|
},
|
||||||
|
// Disable http2
|
||||||
|
TLSNextProto: map[string]func(authority string, c *tls.Conn) http.RoundTripper{},
|
||||||
|
MaxIdleConnsPerHost: 999,
|
||||||
|
},
|
||||||
|
Timeout: t,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrOverSize 响应主体过大时返回此错误
|
// ErrOverSize 响应主体过大时返回此错误
|
||||||
@ -56,6 +62,18 @@ var ErrOverSize = errors.New("oversize")
|
|||||||
// UserAgent HTTP请求时使用的UA
|
// UserAgent HTTP请求时使用的UA
|
||||||
const UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66"
|
const UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66"
|
||||||
|
|
||||||
|
// WithTimeout get a download instance with timeout t
|
||||||
|
func (r Request) WithTimeout(t time.Duration) *Request {
|
||||||
|
if c, ok := clients.Load(t); ok {
|
||||||
|
r.custcli = c
|
||||||
|
} else {
|
||||||
|
c := newClient(t)
|
||||||
|
clients.Store(t, c)
|
||||||
|
r.custcli = c
|
||||||
|
}
|
||||||
|
return &r
|
||||||
|
}
|
||||||
|
|
||||||
// SetTimeout set internal/download client timeout
|
// SetTimeout set internal/download client timeout
|
||||||
func SetTimeout(t time.Duration) {
|
func SetTimeout(t time.Duration) {
|
||||||
if t == 0 {
|
if t == 0 {
|
||||||
@ -67,14 +85,18 @@ func SetTimeout(t time.Duration) {
|
|||||||
|
|
||||||
// Request is a file download request
|
// Request is a file download request
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Method string
|
Method string
|
||||||
URL string
|
URL string
|
||||||
Header map[string]string
|
Header map[string]string
|
||||||
Limit int64
|
Limit int64
|
||||||
Body io.Reader
|
Body io.Reader
|
||||||
|
custcli *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Request) client() *http.Client {
|
func (r Request) client() *http.Client {
|
||||||
|
if r.custcli != nil {
|
||||||
|
return r.custcli
|
||||||
|
}
|
||||||
if strings.Contains(r.URL, "go-cqhttp.org") {
|
if strings.Contains(r.URL, "go-cqhttp.org") {
|
||||||
return clienth2
|
return clienth2
|
||||||
}
|
}
|
||||||
@ -123,6 +145,7 @@ func (r Request) Bytes() ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rd.Close()
|
defer rd.Close()
|
||||||
|
defer r.client().CloseIdleConnections()
|
||||||
return io.ReadAll(rd)
|
return io.ReadAll(rd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +156,7 @@ func (r Request) JSON() (gjson.Result, error) {
|
|||||||
return gjson.Result{}, err
|
return gjson.Result{}, err
|
||||||
}
|
}
|
||||||
defer rd.Close()
|
defer rd.Close()
|
||||||
|
defer r.client().CloseIdleConnections()
|
||||||
|
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
_, err = io.Copy(&sb, rd)
|
_, err = io.Copy(&sb, rd)
|
||||||
@ -160,6 +184,7 @@ func (r Request) WriteToFile(path string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer rd.Close()
|
defer rd.Close()
|
||||||
|
defer r.client().CloseIdleConnections()
|
||||||
return writeToFile(rd, path)
|
return writeToFile(rd, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +194,7 @@ func (r Request) WriteToFileMultiThreading(path string, thread int) error {
|
|||||||
return r.WriteToFile(path)
|
return r.WriteToFile(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer r.client().CloseIdleConnections()
|
||||||
limit := r.Limit
|
limit := r.Limit
|
||||||
type BlockMetaData struct {
|
type BlockMetaData struct {
|
||||||
BeginOffset int64
|
BeginOffset int64
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
package encryption
|
|
||||||
|
|
||||||
var T544Signer = map[string]func(int64, []byte) []byte{}
|
|
File diff suppressed because one or more lines are too long
@ -1,65 +0,0 @@
|
|||||||
//go:build amd64
|
|
||||||
|
|
||||||
package t544
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"hash/crc32"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
var crc32Table = func() (tab crc32.Table) {
|
|
||||||
f, err := cryptoZip.Open("crc32.bin")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
data, err := io.ReadAll(f)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for i := range tab {
|
|
||||||
tab[i] = binary.LittleEndian.Uint32(data[i*4 : (i+1)*4])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}()
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func tencentCrc32(tab *crc32.Table, b []byte) uint32
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func sub_a([]byte, []uint32)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func sub_b([]byte, []uint32)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func sub_c(*[16][16]byte, []byte)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func sub_d(*[16]byte, []byte)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func sub_e(*[256][6]byte, []byte)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func sub_f(*[16]byte, *[15]uint32, *[16][16]byte) (w [44]uint32)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func sub_aa(int, *[16][2][16][16]byte, *[16]byte, []byte) byte
|
|
||||||
|
|
||||||
// transformInner see com/tencent/mobileqq/dt/model/FEBound
|
|
||||||
//
|
|
||||||
//go:noescape
|
|
||||||
func transformInner(*[0x15]byte, *[32][16]byte)
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func initState(*state, []byte, []byte, uint64)
|
|
||||||
|
|
||||||
func (c *state) init(key []byte, data []byte, counter uint64, nr uint8) {
|
|
||||||
c.nr = nr
|
|
||||||
c.p = 0
|
|
||||||
initState(c, key, data, counter)
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
func refreshState(c *state)
|
|
@ -1,669 +0,0 @@
|
|||||||
//go:build amd64
|
|
||||||
// +build amd64
|
|
||||||
|
|
||||||
#include "textflag.h"
|
|
||||||
|
|
||||||
DATA LC0<>+0(SB)/4, $1634760805
|
|
||||||
DATA LC0<>+4(SB)/4, $857760878
|
|
||||||
DATA LC0<>+8(SB)/4, $2036477234
|
|
||||||
DATA LC0<>+12(SB)/4, $1797285236
|
|
||||||
GLOBL LC0<>(SB), NOPTR, $16
|
|
||||||
|
|
||||||
TEXT ·sub_a(SB), NOSPLIT, $0-48
|
|
||||||
MOVQ a+0(FP), DI
|
|
||||||
MOVQ b+24(FP), CX
|
|
||||||
MOVQ CX, DX
|
|
||||||
MOVBLZX 3(CX), CX
|
|
||||||
XORB CX, (DI)
|
|
||||||
MOVBLZX 2(DX), CX
|
|
||||||
XORB CX, 1(DI)
|
|
||||||
MOVBLZX 1(DX), CX
|
|
||||||
XORB CX, 2(DI)
|
|
||||||
MOVBLZX (DX), CX
|
|
||||||
XORB CX, 3(DI)
|
|
||||||
MOVBLZX 7(DX), CX
|
|
||||||
XORB CX, 4(DI)
|
|
||||||
MOVBLZX 6(DX), CX
|
|
||||||
XORB CX, 5(DI)
|
|
||||||
MOVBLZX 5(DX), CX
|
|
||||||
XORB CX, 6(DI)
|
|
||||||
MOVBLZX 4(DX), CX
|
|
||||||
XORB CX, 7(DI)
|
|
||||||
MOVBLZX 11(DX),CX
|
|
||||||
XORB CX, 8(DI)
|
|
||||||
MOVBLZX 10(DX),CX
|
|
||||||
XORB CX, 9(DI)
|
|
||||||
MOVBLZX 9(DX), CX
|
|
||||||
XORB CX,10(DI)
|
|
||||||
MOVBLZX 8(DX), CX
|
|
||||||
XORB CX,11(DI)
|
|
||||||
MOVBLZX 15(DX),CX
|
|
||||||
XORB CX,12(DI)
|
|
||||||
MOVBLZX 14(DX),CX
|
|
||||||
XORB CX,13(DI)
|
|
||||||
MOVBLZX 13(DX),CX
|
|
||||||
XORB CX,14(DI)
|
|
||||||
MOVBLZX 12(DX),DX
|
|
||||||
XORB DL,15(DI)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·sub_b(SB), NOSPLIT, $0-48
|
|
||||||
MOVQ a+0(FP), DI
|
|
||||||
MOVQ b+24(FP), CX
|
|
||||||
MOVQ CX, DX
|
|
||||||
MOVBLZX 3(CX), CX
|
|
||||||
XORB CX, (DI)
|
|
||||||
MOVBLZX 6(DX), CX
|
|
||||||
XORB CX, 1(DI)
|
|
||||||
MOVBLZX 9(DX), CX
|
|
||||||
XORB CX, 2(DI)
|
|
||||||
MOVBLZX 12(DX),CX
|
|
||||||
XORB CX, 3(DI)
|
|
||||||
MOVBLZX 7(DX), CX
|
|
||||||
XORB CX, 4(DI)
|
|
||||||
MOVBLZX 10(DX),CX
|
|
||||||
XORB CX, 5(DI)
|
|
||||||
MOVBLZX 13(DX),CX
|
|
||||||
XORB CX, 6(DI)
|
|
||||||
MOVBLZX (DX), CX
|
|
||||||
XORB CX,7(DI)
|
|
||||||
MOVBLZX 11(DX),CX
|
|
||||||
XORB CX,8(DI)
|
|
||||||
MOVBLZX 14(DX),CX
|
|
||||||
XORB CX,9(DI)
|
|
||||||
MOVBLZX 1(DX), CX
|
|
||||||
XORB CX,10(DI)
|
|
||||||
MOVBLZX 4(DX), CX
|
|
||||||
XORB CX,11(DI)
|
|
||||||
MOVBLZX 15(DX),CX
|
|
||||||
XORB CX,12(DI)
|
|
||||||
MOVBLZX 2(DX), CX
|
|
||||||
XORB CX,13(DI)
|
|
||||||
MOVBLZX 5(DX), CX
|
|
||||||
XORB CX,14(DI)
|
|
||||||
MOVBLZX 8(DX), DX
|
|
||||||
XORB DL,15(DI)
|
|
||||||
RET
|
|
||||||
|
|
||||||
|
|
||||||
TEXT ·sub_c(SB), NOSPLIT, $0-32
|
|
||||||
MOVQ a+0(FP), DI
|
|
||||||
MOVQ b+8(FP), SI
|
|
||||||
MOVQ SI, AX
|
|
||||||
MOVBLZX (SI), SI
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 1(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, (AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 2(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 1(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 3(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 2(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 4(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 3(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 5(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 4(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 6(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 5(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 7(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 6(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 8(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 7(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 9(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 8(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 10(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 9(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 11(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 10(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 12(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 11(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 13(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 12(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 14(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 13(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX 15(AX), SI
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 14(AX)
|
|
||||||
MOVL SI, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
SHRL $4, CX
|
|
||||||
SHLL $4, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVLQSX CX, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
MOVB CX, 15(AX)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·sub_d(SB), NOSPLIT, $24-32
|
|
||||||
MOVQ t+0(FP), BX
|
|
||||||
MOVQ s+8(FP), DI
|
|
||||||
MOVOU (DI), X0
|
|
||||||
MOVOU X0, in-16(SP)
|
|
||||||
MOVQ $16, CX
|
|
||||||
ADDQ $15, DI
|
|
||||||
PUSHFQ
|
|
||||||
STD
|
|
||||||
lop:
|
|
||||||
LEAQ -1(CX), AX
|
|
||||||
XLAT
|
|
||||||
LEAQ in-16(SP)(AX*1), SI
|
|
||||||
MOVSB
|
|
||||||
LOOP lop
|
|
||||||
POPFQ
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·sub_e(SB), NOSPLIT, $0-32
|
|
||||||
MOVQ a+0(FP), DI
|
|
||||||
MOVQ n+8(FP), SI
|
|
||||||
MOVQ $4, AX
|
|
||||||
lop:
|
|
||||||
MOVBQZX -4(SI)(AX*4), DX
|
|
||||||
MOVBQZX -3(SI)(AX*4), CX
|
|
||||||
MOVBQZX -2(SI)(AX*4), R10
|
|
||||||
MOVBQZX -1(SI)(AX*4), R8
|
|
||||||
LEAQ (DX)(DX*2), R9
|
|
||||||
LEAQ (R9*2), R9
|
|
||||||
LEAQ (CX)(CX*2), R11
|
|
||||||
LEAQ (R11*2), R11
|
|
||||||
LEAQ (R10)(R10*2), BX
|
|
||||||
LEAQ (BX*2), BX
|
|
||||||
MOVB DX, R13
|
|
||||||
XORB CX, DX
|
|
||||||
XORB R10, CX
|
|
||||||
MOVB (DI)(R9*1), R12
|
|
||||||
XORB 1(DI)(R11*1), R12
|
|
||||||
XORB R8, R10
|
|
||||||
XORB R12, R10
|
|
||||||
MOVB R10, -4(SI)(AX*4)
|
|
||||||
MOVB (DI)(R11*1), R10
|
|
||||||
XORB 1(DI)(BX*1), R10
|
|
||||||
XORB R8, R13
|
|
||||||
XORB R10, R13
|
|
||||||
MOVB R13, -3(SI)(AX*4)
|
|
||||||
MOVB (DI)(BX*1), R10
|
|
||||||
LEAQ (R8)(R8*2), R8
|
|
||||||
LEAQ (R8*2), R8
|
|
||||||
XORB 1(DI)(R8*1), R10
|
|
||||||
XORB R10, DX
|
|
||||||
MOVB DX, -2(SI)(AX*4)
|
|
||||||
MOVB 1(DI)(R9*1), DX
|
|
||||||
XORB (DI)(R8*1), DX
|
|
||||||
XORB DX, CX
|
|
||||||
MOVB CX, -1(SI)(AX*4)
|
|
||||||
DECB AX
|
|
||||||
JNZ lop
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT sub_ab<>(SB), NOSPLIT, $0-24
|
|
||||||
MOVQ s+0(FP), DI
|
|
||||||
MOVQ w+8(FP), SI
|
|
||||||
MOVL SI, AX
|
|
||||||
MOVL SI, CX
|
|
||||||
MOVL SI, DX
|
|
||||||
SHRL $28, AX
|
|
||||||
SHRL $24, CX
|
|
||||||
ANDL $15, CX
|
|
||||||
SALL $4, AX
|
|
||||||
ADDL CX, AX
|
|
||||||
MOVBLZX SI, CX
|
|
||||||
MOVBLZX (DI)(AX*1), AX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
SALL $24, AX
|
|
||||||
ORL CX, AX
|
|
||||||
MOVL SI, CX
|
|
||||||
SHRL $8, SI
|
|
||||||
SHRL $8, CX
|
|
||||||
ANDL $15, SI
|
|
||||||
ANDL $240, CX
|
|
||||||
ADDL SI, CX
|
|
||||||
MOVBLZX (DI)(CX*1), CX
|
|
||||||
SALL $8, CX
|
|
||||||
ORL CX, AX
|
|
||||||
MOVL DX, CX
|
|
||||||
SHRL $16, DX
|
|
||||||
SHRL $16, CX
|
|
||||||
ANDL $15, DX
|
|
||||||
ANDL $240, CX
|
|
||||||
ADDL CX, DX
|
|
||||||
MOVBLZX (DI)(DX*1), DX
|
|
||||||
SALL $16, DX
|
|
||||||
ORL DX, AX
|
|
||||||
MOVQ AX, retval+16(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·sub_f(SB), NOSPLIT, $24-68
|
|
||||||
MOVQ k+0(FP), DI
|
|
||||||
MOVQ r+8(FP), SI
|
|
||||||
MOVQ s+16(FP), DX
|
|
||||||
MOVQ $w+24(FP), CX
|
|
||||||
MOVQ CX, R10
|
|
||||||
MOVQ SI, R9
|
|
||||||
MOVQ DX, R8
|
|
||||||
MOVL $4, BX
|
|
||||||
MOVL (DI), AX
|
|
||||||
BSWAPL AX
|
|
||||||
MOVL AX, (CX)
|
|
||||||
MOVL 4(DI), AX
|
|
||||||
BSWAPL AX
|
|
||||||
MOVL AX, 4(CX)
|
|
||||||
MOVL 8(DI), AX
|
|
||||||
BSWAPL AX
|
|
||||||
MOVL AX, 8(CX)
|
|
||||||
MOVL 12(DI), AX
|
|
||||||
BSWAPL AX
|
|
||||||
MOVL AX, 12(CX)
|
|
||||||
JMP inner
|
|
||||||
for:
|
|
||||||
XORL -16(R10)(BX*4), AX
|
|
||||||
MOVL AX, (R10)(BX*4)
|
|
||||||
ADDQ $1, BX
|
|
||||||
CMPQ BX, $44
|
|
||||||
JE end
|
|
||||||
inner:
|
|
||||||
MOVL -4(R10)(BX*4), AX
|
|
||||||
TESTB $3, BX
|
|
||||||
JNE for
|
|
||||||
ROLL $8, AX
|
|
||||||
MOVQ R8, 0(SP)
|
|
||||||
MOVL AX, 8(SP)
|
|
||||||
CALL sub_ab<>(SB)
|
|
||||||
MOVQ 16(SP), AX
|
|
||||||
LEAL -1(BX), DX
|
|
||||||
SARL $2, DX
|
|
||||||
MOVLQSX DX, DX
|
|
||||||
XORL (R9)(DX*4), AX
|
|
||||||
JMP for
|
|
||||||
end:
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·sub_aa(SB), NOSPLIT, $0-56
|
|
||||||
MOVQ i+0(FP), DI
|
|
||||||
MOVQ t+8(FP), SI
|
|
||||||
MOVQ b+16(FP), DX
|
|
||||||
MOVQ m+24(FP), CX
|
|
||||||
MOVL DI, AX
|
|
||||||
MOVLQSX DI, DI
|
|
||||||
MOVQ SI, R8
|
|
||||||
MOVQ DX, SI
|
|
||||||
MOVBLZX (CX)(DI*1), CX
|
|
||||||
ANDL $15, AX
|
|
||||||
MOVBLZX (SI)(AX*1), SI
|
|
||||||
MOVQ AX, DX
|
|
||||||
MOVL CX, AX
|
|
||||||
SALQ $9, DX
|
|
||||||
ANDL $15, CX
|
|
||||||
SHRB $4, AX
|
|
||||||
MOVL SI, DI
|
|
||||||
ADDQ R8, DX
|
|
||||||
SALQ $4, CX
|
|
||||||
ANDL $15, AX
|
|
||||||
SHRB $4, DI
|
|
||||||
ANDL $15, SI
|
|
||||||
SALQ $4, AX
|
|
||||||
ANDL $15, DI
|
|
||||||
ADDQ DX, AX
|
|
||||||
ADDQ CX, DX
|
|
||||||
MOVBLZX (AX)(DI*1), AX
|
|
||||||
SALL $4, AX
|
|
||||||
ORB 256(SI)(DX*1), AX
|
|
||||||
MOVQ AX, retval+48(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
// func transformInner(x *[0x15]byte, tab *[32][16]byte)
|
|
||||||
TEXT ·transformInner(SB), NOSPLIT, $0-16
|
|
||||||
MOVQ x+0(FP), DI
|
|
||||||
MOVQ tab+8(FP), SI
|
|
||||||
MOVQ DI, AX
|
|
||||||
MOVL $1, CX
|
|
||||||
MOVQ SI, DI
|
|
||||||
MOVQ AX, SI
|
|
||||||
lop:
|
|
||||||
MOVBLZX (SI), R8
|
|
||||||
LEAL -1(CX), AX
|
|
||||||
ADDQ $1, SI
|
|
||||||
ANDL $31, AX
|
|
||||||
MOVL R8, DX
|
|
||||||
SALL $4, AX
|
|
||||||
ANDL $15, R8
|
|
||||||
SHRB $4, DX
|
|
||||||
MOVBLZX DX, DX
|
|
||||||
ADDL DX, AX
|
|
||||||
CDQE
|
|
||||||
MOVBLSX (DI)(AX*1), AX
|
|
||||||
SALL $4, AX
|
|
||||||
MOVL AX, DX
|
|
||||||
MOVL CX, AX
|
|
||||||
ADDL $2, CX
|
|
||||||
ANDL $31, AX
|
|
||||||
SALL $4, AX
|
|
||||||
ADDL R8, AX
|
|
||||||
CDQE
|
|
||||||
ORB (DI)(AX*1), DX
|
|
||||||
MOVB DX, -1(SI)
|
|
||||||
CMPL CX, $43
|
|
||||||
JNE lop
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·initState(SB), NOSPLIT, $0-64
|
|
||||||
MOVQ c+0(FP), DI
|
|
||||||
MOVQ key+8(FP), SI
|
|
||||||
MOVQ data+32(FP), R8
|
|
||||||
MOVQ counter+56(FP), AX
|
|
||||||
MOVOA LC0<>(SB), X0
|
|
||||||
MOVUPS X0, (DI)
|
|
||||||
MOVOU (SI), X1
|
|
||||||
MOVOU (DI), X3
|
|
||||||
MOVUPS X1, 16(DI)
|
|
||||||
MOVOU 16(SI), X2
|
|
||||||
MOVQ AX, 48(DI)
|
|
||||||
MOVUPS X2, 32(DI)
|
|
||||||
MOVQ (R8), AX
|
|
||||||
MOVUPS X3, 64(DI)
|
|
||||||
MOVQ AX, 56(DI)
|
|
||||||
MOVQ 48(DI), AX
|
|
||||||
MOVUPS X1, 80(DI)
|
|
||||||
MOVUPS X2, 96(DI)
|
|
||||||
MOVUPS X6,112(DI)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT sub_ad<>(SB), NOSPLIT, $8-8
|
|
||||||
MOVQ a+0(FP), DI
|
|
||||||
MOVQ DI, AX
|
|
||||||
MOVL 40(DI), R10
|
|
||||||
MOVL 12(DI), R12
|
|
||||||
MOVL 44(DI), BP
|
|
||||||
MOVL 16(DI), DX
|
|
||||||
MOVL (DI), R15
|
|
||||||
MOVL 48(DI), R9
|
|
||||||
MOVL 20(DI), SI
|
|
||||||
MOVL 32(DI), R11
|
|
||||||
ADDL DX, R15
|
|
||||||
MOVL 4(DI), R14
|
|
||||||
MOVL 52(DI), R8
|
|
||||||
XORL R15, R9
|
|
||||||
MOVL 24(DI), CX
|
|
||||||
MOVL 8(DI), R13
|
|
||||||
ROLL $16, R9
|
|
||||||
ADDL SI, R14
|
|
||||||
MOVL 36(DI), BX
|
|
||||||
MOVL 56(DI), DI
|
|
||||||
ADDL R9, R11
|
|
||||||
XORL R14, R8
|
|
||||||
ADDL CX, R13
|
|
||||||
XORL R11, DX
|
|
||||||
ROLL $16, R8
|
|
||||||
XORL R13, DI
|
|
||||||
ROLL $12, DX
|
|
||||||
ADDL R8, BX
|
|
||||||
ROLL $16, DI
|
|
||||||
ADDL DX, R15
|
|
||||||
XORL BX, SI
|
|
||||||
ADDL DI, R10
|
|
||||||
XORL R15, R9
|
|
||||||
ROLL $12, SI
|
|
||||||
XORL R10, CX
|
|
||||||
ROLL $8, R9
|
|
||||||
ADDL SI, R14
|
|
||||||
ROLL $12, CX
|
|
||||||
ADDL R9, R11
|
|
||||||
XORL R14, R8
|
|
||||||
ADDL CX, R13
|
|
||||||
XORL R11, DX
|
|
||||||
ROLL $8, R8
|
|
||||||
XORL R13, DI
|
|
||||||
ROLL $7, DX
|
|
||||||
LEAL (BX)(R8*1), BX
|
|
||||||
ROLL $8, DI
|
|
||||||
MOVL DX, tmp0-8(SP)
|
|
||||||
MOVL 28(AX), DX
|
|
||||||
XORL BX, SI
|
|
||||||
MOVL BX, tmp1-4(SP)
|
|
||||||
MOVL R10, BX
|
|
||||||
MOVL 60(AX), R10
|
|
||||||
ROLL $7, SI
|
|
||||||
ADDL DI, BX
|
|
||||||
ADDL DX, R12
|
|
||||||
ADDL SI, R15
|
|
||||||
XORL R12, R10
|
|
||||||
XORL BX, CX
|
|
||||||
ROLL $16, R10
|
|
||||||
ROLL $7, CX
|
|
||||||
ADDL R10, BP
|
|
||||||
ADDL CX, R14
|
|
||||||
XORL BP, DX
|
|
||||||
XORL R14, R9
|
|
||||||
ROLL $12, DX
|
|
||||||
ROLL $16, R9
|
|
||||||
ADDL DX, R12
|
|
||||||
XORL R12, R10
|
|
||||||
ROLL $8, R10
|
|
||||||
ADDL R10, BP
|
|
||||||
XORL R15, R10
|
|
||||||
ROLL $16, R10
|
|
||||||
XORL BP, DX
|
|
||||||
ADDL R9, BP
|
|
||||||
ADDL R10, BX
|
|
||||||
ROLL $7, DX
|
|
||||||
XORL BP, CX
|
|
||||||
XORL BX, SI
|
|
||||||
ROLL $12, SI
|
|
||||||
ADDL SI, R15
|
|
||||||
XORL R15, R10
|
|
||||||
MOVL R15, (AX)
|
|
||||||
ROLL $8, R10
|
|
||||||
ADDL R10, BX
|
|
||||||
MOVL R10, 60(AX)
|
|
||||||
XORL BX, SI
|
|
||||||
MOVD BX, X1
|
|
||||||
ROLL $7, SI
|
|
||||||
ROLL $12, CX
|
|
||||||
ADDL DX, R13
|
|
||||||
XORL R13, R8
|
|
||||||
ADDL CX, R14
|
|
||||||
MOVL SI, 20(AX)
|
|
||||||
ROLL $16, R8
|
|
||||||
XORL R14, R9
|
|
||||||
MOVL R14, 4(AX)
|
|
||||||
ADDL R8, R11
|
|
||||||
ROLL $8, R9
|
|
||||||
XORL R11, DX
|
|
||||||
ADDL R9, BP
|
|
||||||
MOVL R9, 48(AX)
|
|
||||||
ROLL $12, DX
|
|
||||||
XORL BP, CX
|
|
||||||
MOVD BP, X2
|
|
||||||
ADDL DX, R13
|
|
||||||
ROLL $7, CX
|
|
||||||
PUNPCKLLQ X2, X1
|
|
||||||
XORL R13, R8
|
|
||||||
MOVL CX, 24(AX)
|
|
||||||
ROLL $8, R8
|
|
||||||
MOVL R13, 8(AX)
|
|
||||||
ADDL R8, R11
|
|
||||||
XORL R11, DX
|
|
||||||
MOVD R11, X0
|
|
||||||
ROLL $7, DX
|
|
||||||
MOVL DX, 28(AX)
|
|
||||||
MOVL R8, 52(AX)
|
|
||||||
MOVL tmp0-8(SP), SI
|
|
||||||
MOVL tmp1-4(SP), CX
|
|
||||||
ADDL SI, R12
|
|
||||||
XORL R12, DI
|
|
||||||
ROLL $16, DI
|
|
||||||
ADDL DI, CX
|
|
||||||
XORL CX, SI
|
|
||||||
MOVL SI, DX
|
|
||||||
ROLL $12, DX
|
|
||||||
ADDL DX, R12
|
|
||||||
XORL R12, DI
|
|
||||||
MOVL R12, 12(AX)
|
|
||||||
ROLL $8, DI
|
|
||||||
ADDL DI, CX
|
|
||||||
MOVL DI, 56(AX)
|
|
||||||
MOVD CX, X3
|
|
||||||
XORL CX, DX
|
|
||||||
PUNPCKLLQ X3, X0
|
|
||||||
ROLL $7, DX
|
|
||||||
PUNPCKLQDQ X1, X0
|
|
||||||
MOVL DX, 16(AX)
|
|
||||||
MOVUPS X0, 32(AX)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·refreshState(SB), NOSPLIT, $16-8
|
|
||||||
MOVQ i+0(FP), BX
|
|
||||||
MOVB 128(BX), CX
|
|
||||||
JE ad
|
|
||||||
SHRQ $1, CX
|
|
||||||
fr:
|
|
||||||
MOVQ BX, 0(SP)
|
|
||||||
MOVQ CX, c-8(SP)
|
|
||||||
CALL sub_ad<>(SB)
|
|
||||||
MOVQ c-8(SP), CX
|
|
||||||
MOVQ i+0(FP), BX
|
|
||||||
LOOP fr
|
|
||||||
ad:
|
|
||||||
MOVOU (BX), X0
|
|
||||||
MOVOU 64(BX), X1
|
|
||||||
MOVOU 80(BX), X2
|
|
||||||
MOVOU 96(BX), X3
|
|
||||||
PADDD X1, X0
|
|
||||||
MOVOU 48(BX), X4
|
|
||||||
MOVUPS X0, (BX)
|
|
||||||
MOVOU 16(BX), X0
|
|
||||||
PADDD X2, X0
|
|
||||||
MOVUPS X0, 16(BX)
|
|
||||||
MOVOU 32(BX), X0
|
|
||||||
PADDD X3, X0
|
|
||||||
MOVUPS X0, 32(BX)
|
|
||||||
MOVOU 112(BX), X0
|
|
||||||
PADDD X4, X0
|
|
||||||
MOVUPS X0, 48(BX)
|
|
||||||
RET
|
|
||||||
|
|
||||||
// func tencentCrc32(tab *crc32.Table, b []byte) uint32
|
|
||||||
TEXT ·tencentCrc32(SB), NOSPLIT, $0-40
|
|
||||||
MOVQ tab+0(FP), DI
|
|
||||||
MOVQ bptr+8(FP), SI
|
|
||||||
MOVQ bngas+16(FP), DX
|
|
||||||
TESTQ DX, DX
|
|
||||||
JE quickend
|
|
||||||
ADDQ SI, DX
|
|
||||||
MOVL $-1, AX
|
|
||||||
lop:
|
|
||||||
MOVBLZX (SI), CX
|
|
||||||
ADDQ $1, SI
|
|
||||||
XORL AX, CX
|
|
||||||
SHRL $8, AX
|
|
||||||
MOVBLZX CX, CX
|
|
||||||
XORL (DI)(CX*4), AX
|
|
||||||
CMPQ SI, DX
|
|
||||||
JNE lop
|
|
||||||
NOTL AX
|
|
||||||
MOVQ AX, bngas+32(FP)
|
|
||||||
RET
|
|
||||||
quickend:
|
|
||||||
XORL AX, AX
|
|
||||||
RET
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
|||||||
//go:build amd64
|
|
||||||
|
|
||||||
package t544
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
type encryptionData struct {
|
|
||||||
tableA [16][2][16][16]byte
|
|
||||||
tableB [16][16]byte
|
|
||||||
tableC [256][6]byte
|
|
||||||
tableD [16]byte
|
|
||||||
tableE [16]byte
|
|
||||||
tableF [15]uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type state struct {
|
|
||||||
state [16]uint32 // 16
|
|
||||||
orgstate [16]uint32 // 16
|
|
||||||
nr uint8
|
|
||||||
p uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
var crypto = encryptionData{
|
|
||||||
tableA: readData[[16][2][16][16]byte]("table_a.bin"),
|
|
||||||
tableB: readData[[16][16]byte]("table_b.bin"),
|
|
||||||
tableC: readData[[256][6]byte]("table_c.bin"),
|
|
||||||
tableD: readData[[16]byte]("table_d.bin"),
|
|
||||||
tableE: readData[[16]byte]("table_e.bin"),
|
|
||||||
tableF: func() (tab [15]uint32) {
|
|
||||||
f, err := cryptoZip.Open("table_f.bin")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
data, err := io.ReadAll(f)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for i := range tab {
|
|
||||||
tab[i] = binary.LittleEndian.Uint32(data[i*4 : (i+1)*4])
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}(),
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encryptionData) tencentEncryptB(p1 []byte, p2 []uint32) {
|
|
||||||
const c = 10
|
|
||||||
for r := 0; r < 9; r++ {
|
|
||||||
sub_d(&e.tableD, p1)
|
|
||||||
sub_b(p1, p2[r*4:(r+1)*4])
|
|
||||||
sub_c(&e.tableB, p1)
|
|
||||||
sub_e(&e.tableC, p1)
|
|
||||||
}
|
|
||||||
sub_d(&e.tableD, p1)
|
|
||||||
sub_b(p1, p2[(c-1)*4:c*4])
|
|
||||||
sub_c(&e.tableB, p1)
|
|
||||||
sub_a(p1, p2[c*4:(c+1)*4])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *encryptionData) tencentEncryptionB(c []byte, m []byte) (out [0x15]byte) {
|
|
||||||
var buf [16]byte
|
|
||||||
w := sub_f(&e.tableE, &e.tableF, &e.tableB)
|
|
||||||
|
|
||||||
for i := range out {
|
|
||||||
if (i & 0xf) == 0 {
|
|
||||||
copy(buf[:], c)
|
|
||||||
e.tencentEncryptB(buf[:], w[:])
|
|
||||||
for j := 15; j >= 0; j-- {
|
|
||||||
c[j]++
|
|
||||||
if c[j] != 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out[i] = sub_aa(i, &e.tableA, &buf, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func tencentEncryptionA(input, key, data []byte) {
|
|
||||||
var s state
|
|
||||||
s.init(key, data, 0, 20)
|
|
||||||
s.encrypt(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *state) encrypt(data []byte) {
|
|
||||||
bp := 0
|
|
||||||
dataLen := uint32(len(data))
|
|
||||||
for dataLen > 0 {
|
|
||||||
if c.p == 0 {
|
|
||||||
refreshState(c)
|
|
||||||
}
|
|
||||||
var sb [16 * 4]byte
|
|
||||||
for i, v := range c.state {
|
|
||||||
binary.LittleEndian.PutUint32(sb[i*4:(i+1)*4], v)
|
|
||||||
}
|
|
||||||
for c.p != 64 && dataLen != 0 {
|
|
||||||
data[bp] ^= sb[c.p]
|
|
||||||
c.p++
|
|
||||||
bp++
|
|
||||||
dataLen--
|
|
||||||
}
|
|
||||||
if c.p >= 64 {
|
|
||||||
c.p = 0
|
|
||||||
c.orgstate[12]++
|
|
||||||
c.state = c.orgstate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
//go:build amd64
|
|
||||||
|
|
||||||
package t544
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/rc4"
|
|
||||||
"encoding/binary"
|
|
||||||
"math/rand"
|
|
||||||
|
|
||||||
"github.com/Mrs4s/go-cqhttp/internal/encryption"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
keyTable = "$%&()+,-456789:?ABCDEEFGHIJabcdefghijkopqrstuvwxyz"
|
|
||||||
table2 = "!#$%&)+.0123456789:=>?@ABCDEFGKMNabcdefghijkopqrst"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
magic = uint64(0x6EEDCF0DC4675540)
|
|
||||||
key1 = [8]byte{'a', '$', '(', 'e', 'T', '7', '*', '@'}
|
|
||||||
key2 = [8]byte{'&', 'O', '9', '!', '>', '6', 'X', ')'}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
encryption.T544Signer["8.9.35.10440"] = sign
|
|
||||||
encryption.T544Signer["8.9.38.10545"] = sign
|
|
||||||
}
|
|
||||||
|
|
||||||
// sign t544 algorithm
|
|
||||||
// special thanks to the anonymous contributor who provided the algorithm
|
|
||||||
func sign(curr int64, input []byte) []byte {
|
|
||||||
var crcData [0x15]byte
|
|
||||||
curr %= 1000000
|
|
||||||
binary.BigEndian.PutUint32(crcData[:4], uint32(curr))
|
|
||||||
input = append(input, crcData[:4]...)
|
|
||||||
var kt [4 + 32 + 4]byte
|
|
||||||
r := rand.New(rand.NewSource(curr))
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
kt[i] = keyTable[r.Int()%0x32] + 50
|
|
||||||
}
|
|
||||||
kt[2] = kt[1] + 20
|
|
||||||
kt[3] = kt[2] + 20
|
|
||||||
key3 := kt[4 : 4+10]
|
|
||||||
k3calc := key3[2:10]
|
|
||||||
copy(k3calc, key1[:4])
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
k3calc[4+i] = key2[i] ^ kt[i]
|
|
||||||
}
|
|
||||||
key3[0], key3[1] = k3calc[6], k3calc[7]
|
|
||||||
key3 = key3[:8]
|
|
||||||
k3calc[6], k3calc[7] = 0, 0
|
|
||||||
rc4Cipher, _ := rc4.NewCipher(key3)
|
|
||||||
rc4Cipher.XORKeyStream(key3, key3)
|
|
||||||
binary.LittleEndian.PutUint64(crcData[4:4+8], magic)
|
|
||||||
tencentEncryptionA(input, kt[4:4+32], crcData[4:4+8])
|
|
||||||
result := md5.Sum(input)
|
|
||||||
crcData[2] = 1
|
|
||||||
crcData[4] = 1
|
|
||||||
copy(crcData[5:9], kt[:4])
|
|
||||||
binary.BigEndian.PutUint32(crcData[9:13], uint32(curr))
|
|
||||||
copy(crcData[13:], result[:8])
|
|
||||||
calcCrc := tencentCrc32(&crc32Table, crcData[2:])
|
|
||||||
binary.LittleEndian.PutUint32(kt[4+32:4+32+4], calcCrc)
|
|
||||||
crcData[0] = kt[4+32]
|
|
||||||
crcData[1] = kt[4+32+3]
|
|
||||||
nonce := uint32(r.Int() ^ r.Int() ^ r.Int())
|
|
||||||
on := kt[:16]
|
|
||||||
binary.BigEndian.PutUint32(on[:4], nonce)
|
|
||||||
copy(on[4:8], on[:4])
|
|
||||||
copy(on[8:16], on[:8])
|
|
||||||
ts.transformEncode(&crcData)
|
|
||||||
encryptedData := crypto.tencentEncryptionB(on, crcData[:])
|
|
||||||
ts.transformDecode(&encryptedData)
|
|
||||||
output := kt[:39]
|
|
||||||
output[0] = 0x0C
|
|
||||||
output[1] = 0x05
|
|
||||||
binary.BigEndian.PutUint32(output[2:6], nonce)
|
|
||||||
copy(output[6:27], encryptedData[:])
|
|
||||||
binary.LittleEndian.PutUint32(output[27:31], 0)
|
|
||||||
output[31] = table2[r.Int()%0x32]
|
|
||||||
output[32] = table2[r.Int()%0x32]
|
|
||||||
addition := r.Int() % 9
|
|
||||||
for addition&1 == 0 {
|
|
||||||
addition = r.Int() % 9
|
|
||||||
}
|
|
||||||
output[33] = output[31] + byte(addition)
|
|
||||||
output[34] = output[32] + byte(9-addition) + 1
|
|
||||||
binary.LittleEndian.PutUint32(output[35:39], 0)
|
|
||||||
return output
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
//go:build !amd64
|
|
||||||
|
|
||||||
package t544
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package t544
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestT544(t *testing.T) {
|
|
||||||
r := hex.EncodeToString(sign(0, []byte{}))
|
|
||||||
if r != "0c05d28b405bce1595c70ffa694ff163d4b600f229482e07de32c8000000003525382c00000000" {
|
|
||||||
t.Fatal(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCrash(t *testing.T) {
|
|
||||||
brand := make([]byte, 4096)
|
|
||||||
for i := 1; i <= 1024; i++ {
|
|
||||||
rand.Reader.Read(brand)
|
|
||||||
sign(123, brand)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
//go:build amd64
|
|
||||||
|
|
||||||
package t544
|
|
||||||
|
|
||||||
type transformer struct {
|
|
||||||
encode [32][16]byte
|
|
||||||
decode [32][16]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ts *transformer) transformEncode(bArr *[0x15]byte) {
|
|
||||||
transformInner(bArr, &ts.encode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ts *transformer) transformDecode(bArr *[0x15]byte) {
|
|
||||||
transformInner(bArr, &ts.decode)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ts = transformer{
|
|
||||||
encode: readData[[32][16]byte]("encode.bin"),
|
|
||||||
decode: readData[[32][16]byte]("decode.bin"),
|
|
||||||
}
|
|
@ -28,13 +28,28 @@ type Reconnect struct {
|
|||||||
|
|
||||||
// Account 账号配置
|
// Account 账号配置
|
||||||
type Account struct {
|
type Account struct {
|
||||||
Uin int64 `yaml:"uin"`
|
Uin int64 `yaml:"uin"`
|
||||||
Password string `yaml:"password"`
|
Password string `yaml:"password"`
|
||||||
Encrypt bool `yaml:"encrypt"`
|
Encrypt bool `yaml:"encrypt"`
|
||||||
Status int `yaml:"status"`
|
Status int `yaml:"status"`
|
||||||
ReLogin *Reconnect `yaml:"relogin"`
|
ReLogin *Reconnect `yaml:"relogin"`
|
||||||
UseSSOAddress bool `yaml:"use-sso-address"`
|
UseSSOAddress bool `yaml:"use-sso-address"`
|
||||||
AllowTempSession bool `yaml:"allow-temp-session"`
|
AllowTempSession bool `yaml:"allow-temp-session"`
|
||||||
|
SignServers []SignServer `yaml:"sign-servers"`
|
||||||
|
RuleChangeSignServer int `yaml:"rule-change-sign-server"`
|
||||||
|
MaxCheckCount uint `yaml:"max-check-count"`
|
||||||
|
SignServerTimeout uint `yaml:"sign-server-timeout"`
|
||||||
|
IsBelow110 bool `yaml:"is-below-110"`
|
||||||
|
AutoRegister bool `yaml:"auto-register"`
|
||||||
|
AutoRefreshToken bool `yaml:"auto-refresh-token"`
|
||||||
|
RefreshInterval int64 `yaml:"refresh-interval"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignServer 签名服务器
|
||||||
|
type SignServer struct {
|
||||||
|
URL string `yaml:"url"`
|
||||||
|
Key string `yaml:"key"`
|
||||||
|
Authorization string `yaml:"authorization"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config 总配置文件
|
// Config 总配置文件
|
||||||
|
@ -16,6 +16,57 @@ account: # 账号相关
|
|||||||
# 是否允许发送临时会话消息
|
# 是否允许发送临时会话消息
|
||||||
allow-temp-session: false
|
allow-temp-session: false
|
||||||
|
|
||||||
|
# 数据包的签名服务器列表,第一个作为主签名服务器,后续作为备用
|
||||||
|
# 兼容 https://github.com/fuqiuluo/unidbg-fetch-qsign
|
||||||
|
# 如果遇到 登录 45 错误, 或者发送信息风控的话需要填入一个或多个服务器
|
||||||
|
# 不建议设置过多,设置主备各一个即可,超过 5 个只会取前五个
|
||||||
|
# 示例:
|
||||||
|
# sign-servers:
|
||||||
|
# - url: 'http://127.0.0.1:8080' # 本地签名服务器
|
||||||
|
# key: "114514" # 相应 key
|
||||||
|
# authorization: "-" # authorization 内容, 依服务端设置
|
||||||
|
# - url: 'https://signserver.example.com' # 线上签名服务器
|
||||||
|
# key: "114514"
|
||||||
|
# authorization: "-"
|
||||||
|
# ...
|
||||||
|
#
|
||||||
|
# 服务器可使用docker在本地搭建或者使用他人开放的服务
|
||||||
|
sign-servers:
|
||||||
|
- url: '-' # 主签名服务器地址, 必填
|
||||||
|
key: '114514' # 签名服务器所需要的apikey, 如果签名服务器的版本在1.1.0及以下则此项无效
|
||||||
|
authorization: '-' # authorization 内容, 依服务端设置,如 'Bearer xxxx'
|
||||||
|
- url: '-' # 备用
|
||||||
|
key: '114514'
|
||||||
|
authorization: '-'
|
||||||
|
|
||||||
|
# 判断签名服务不可用(需要切换)的额外规则
|
||||||
|
# 0: 不设置 (此时仅在请求无法返回结果时判定为不可用)
|
||||||
|
# 1: 在获取到的 sign 为空 (若选此建议关闭 auto-register,一般为实例未注册但是请求签名的情况)
|
||||||
|
# 2: 在获取到的 sign 或 token 为空(若选此建议关闭 auto-refresh-token )
|
||||||
|
rule-change-sign-server: 1
|
||||||
|
|
||||||
|
# 连续寻找可用签名服务器最大尝试次数
|
||||||
|
# 为 0 时会在连续 3 次没有找到可用签名服务器后保持使用主签名服务器,不再尝试进行切换备用
|
||||||
|
# 否则会在达到指定次数后 **退出** 主程序
|
||||||
|
max-check-count: 0
|
||||||
|
# 签名服务请求超时时间(s)
|
||||||
|
sign-server-timeout: 60
|
||||||
|
# 如果签名服务器的版本在1.1.0及以下, 请将下面的参数改成true
|
||||||
|
# 建议使用 1.1.6 以上版本,低版本普遍半个月冻结一次
|
||||||
|
is-below-110: false
|
||||||
|
# 在实例可能丢失(获取到的签名为空)时是否尝试重新注册
|
||||||
|
# 为 true 时,在签名服务不可用时可能每次发消息都会尝试重新注册并签名。
|
||||||
|
# 为 false 时,将不会自动注册实例,在签名服务器重启或实例被销毁后需要重启 go-cqhttp 以获取实例
|
||||||
|
# 否则后续消息将不会正常签名。关闭此项后可以考虑开启签名服务器端 auto_register 避免需要重启
|
||||||
|
# 由于实现问题,当前建议关闭此项,推荐开启签名服务器的自动注册实例
|
||||||
|
auto-register: false
|
||||||
|
# 是否在 token 过期后立即自动刷新签名 token(在需要签名时才会检测到,主要防止 token 意外丢失)
|
||||||
|
# 独立于定时刷新
|
||||||
|
auto-refresh-token: false
|
||||||
|
# 定时刷新 token 间隔时间,单位为分钟, 建议 30~40 分钟, 不可超过 60 分钟
|
||||||
|
# 目前丢失token也不会有太大影响,可设置为 0 以关闭,推荐开启
|
||||||
|
refresh-interval: 40
|
||||||
|
|
||||||
heartbeat:
|
heartbeat:
|
||||||
# 心跳频率, 单位秒
|
# 心跳频率, 单位秒
|
||||||
# -1 为关闭心跳
|
# -1 为关闭心跳
|
||||||
@ -45,6 +96,8 @@ message:
|
|||||||
skip-mime-scan: false
|
skip-mime-scan: false
|
||||||
# 是否自动转换 WebP 图片
|
# 是否自动转换 WebP 图片
|
||||||
convert-webp-image: false
|
convert-webp-image: false
|
||||||
|
# download 超时时间(s)
|
||||||
|
http-timeout: 15
|
||||||
|
|
||||||
output:
|
output:
|
||||||
# 日志等级 trace,debug,info,warn,error
|
# 日志等级 trace,debug,info,warn,error
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/usr/bin/env bash
|
||||||
echo "Start GOCQHTTP~~~"
|
function index.main_handler() {
|
||||||
|
echo "Start GOCQHTTP~~~"
|
||||||
cp -f config.yml /tmp/config.yml
|
cp -f config.yml /tmp/config.yml
|
||||||
cp -f device.json /tmp/device.json
|
cp -f device.json /tmp/device.json
|
||||||
./go-cqhttp -w="/tmp/" faststart
|
./go-cqhttp -w="/tmp/" faststart
|
||||||
|
}
|
||||||
|
index.main_handler
|
||||||
|
@ -71,7 +71,7 @@ func (c *wsConn) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
var upgrader = websocket.Upgrader{
|
||||||
CheckOrigin: func(r *http.Request) bool {
|
CheckOrigin: func(_ *http.Request) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user