From 0312f05f6e74856bf6863da0c6ef448270f714c6 Mon Sep 17 00:00:00 2001 From: Mrs4s Date: Wed, 15 Mar 2023 02:33:04 +0800 Subject: [PATCH] feat: basic protocol auto-updater --- cmd/gocq/main.go | 46 +++++++++++++++++++++++++++++++ global/fs.go | 2 ++ go.mod | 2 +- go.sum | 4 +-- modules/config/config.go | 15 +++++----- modules/config/default_config.yml | 2 ++ 6 files changed, 61 insertions(+), 10 deletions(-) diff --git a/cmd/gocq/main.go b/cmd/gocq/main.go index e5e201f..65ff11a 100644 --- a/cmd/gocq/main.go +++ b/cmd/gocq/main.go @@ -14,8 +14,10 @@ import ( "github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/client" + "github.com/Mrs4s/go-cqhttp/internal/download" para "github.com/fumiama/go-hide-param" rotatelogs "github.com/lestrrat-go/file-rotatelogs" + "github.com/pkg/errors" log "github.com/sirupsen/logrus" "golang.org/x/crypto/pbkdf2" "golang.org/x/term" @@ -102,6 +104,7 @@ func PrepareData() { mkCacheDir(global.VideoPath, "视频") mkCacheDir(global.CachePath, "发送图片") mkCacheDir(path.Join(global.ImagePath, "guild-images"), "频道图片缓存") + mkCacheDir(global.VersionsPath, "版本缓存") cache.Init() db.Init() @@ -221,6 +224,17 @@ func LoginInteract() { cli.UseDevice(device) isQRCodeLogin := (base.Account.Uin == 0 || len(base.Account.Password) == 0) && !base.Account.Encrypt isTokenLogin := false + + // 加载本地版本信息, 一般是在上次登录时保存的 + versionFile := path.Join(global.VersionsPath, fmt.Sprint(int(cli.Device().Protocol))+".json") + if global.PathExists(versionFile) { + b, err := os.ReadFile(versionFile) + if err == nil { + _ = cli.Device().Protocol.Version().UpdateFromJson(b) + } + log.Infof("从文件 %s 读取协议版本 %v.", versionFile, cli.Device().Protocol.Version()) + } + saveToken := func() { base.AccountToken = cli.GenToken() _ = os.WriteFile("session.token", base.AccountToken, 0o644) @@ -262,6 +276,20 @@ func LoginInteract() { cli.PasswordMd5 = base.PasswordHash } if !isTokenLogin { + if !base.Account.DisableProtocolUpdate { + oldVersionName := device.Protocol.Version().String() + remoteVersion, err := getRemoteLatestProtocolVersion(int(device.Protocol.Version().Protocol)) + if err == nil { + if err = device.Protocol.Version().UpdateFromJson(remoteVersion); err == nil { + if device.Protocol.Version().String() != oldVersionName { + log.Infof("已自动更新协议版本: %s -> %s", oldVersionName, device.Protocol.Version().String()) + } + _ = os.WriteFile(versionFile, remoteVersion, 0o644) + } + } else if err.Error() != "remote version unavailable" { + log.Warnf("检查协议更新失败: %v", err) + } + } if !isQRCodeLogin { if err := commonLogin(); err != nil { log.Fatalf("登录时发生致命错误: %v", err) @@ -408,6 +436,24 @@ func newClient() *client.QQClient { return c } +// TODO: mirror support +var remoteVersions = map[int]string{ + 1: "https://raw.githubusercontent.com/RomiChan/protocol-versions/master/android_phone.json", + 6: "https://raw.githubusercontent.com/RomiChan/protocol-versions/master/android_pad.json", +} + +func getRemoteLatestProtocolVersion(protocolType int) ([]byte, error) { + url, ok := remoteVersions[protocolType] + if !ok { + return nil, errors.New("remote version unavailable") + } + response, err := download.Request{URL: url}.Bytes() + if err != nil { + return nil, err + } + return response, nil +} + type protocolLogger struct{} const fromProtocol = "Protocol -> " diff --git a/global/fs.go b/global/fs.go index aebcf51..cfa9bd3 100644 --- a/global/fs.go +++ b/global/fs.go @@ -27,6 +27,8 @@ const ( VoicePath = "data/voices" // VideoPath go-cqhttp使用的视频缓存目录 VideoPath = "data/videos" + // VersionsPath go-cqhttp使用的版本信息目录 + VersionsPath = "data/versions" // CachePath go-cqhttp使用的缓存目录 CachePath = "data/cache" // DumpsPath go-cqhttp使用错误转储目录 diff --git a/go.mod b/go.mod index ec1d3e8..d7abd94 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/FloatTech/sqlite v1.5.7 github.com/Microsoft/go-winio v0.6.0 - github.com/Mrs4s/MiraiGo v0.0.0-20230312141222-653b853ca5ac + github.com/Mrs4s/MiraiGo v0.0.0-20230314181550-5e7ade149fff github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e github.com/RomiChan/websocket v1.4.3-0.20220123145318-307a86b127bc github.com/fumiama/go-base16384 v1.6.1 diff --git a/go.sum b/go.sum index be40eae..76c1d5f 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b h1:tvciXWq2nuvTbFeJG github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs= github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= -github.com/Mrs4s/MiraiGo v0.0.0-20230312141222-653b853ca5ac h1:DhqFiVOZeBpKtcJHdrLPmCSxmqRUi7RwxbwiOqg8ScI= -github.com/Mrs4s/MiraiGo v0.0.0-20230312141222-653b853ca5ac/go.mod h1:mU3fBFU+7eO0kaGes7YRKtzIDtwIU84nSSwTV7NK2b0= +github.com/Mrs4s/MiraiGo v0.0.0-20230314181550-5e7ade149fff h1:VOc0uHpfTQde3c+1hdXbvuZiinF3bm3Qc7eNf6waonk= +github.com/Mrs4s/MiraiGo v0.0.0-20230314181550-5e7ade149fff/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/go.mod h1:2Ie+hdBFQpQFDHfeklgxoFmQRCE7O+KwFpISeXq7OwA= github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA= diff --git a/modules/config/config.go b/modules/config/config.go index 22d9879..53e2abf 100644 --- a/modules/config/config.go +++ b/modules/config/config.go @@ -28,13 +28,14 @@ type Reconnect struct { // Account 账号配置 type Account struct { - Uin int64 `yaml:"uin"` - Password string `yaml:"password"` - Encrypt bool `yaml:"encrypt"` - Status int `yaml:"status"` - ReLogin *Reconnect `yaml:"relogin"` - UseSSOAddress bool `yaml:"use-sso-address"` - AllowTempSession bool `yaml:"allow-temp-session"` + Uin int64 `yaml:"uin"` + Password string `yaml:"password"` + Encrypt bool `yaml:"encrypt"` + Status int `yaml:"status"` + ReLogin *Reconnect `yaml:"relogin"` + UseSSOAddress bool `yaml:"use-sso-address"` + AllowTempSession bool `yaml:"allow-temp-session"` + DisableProtocolUpdate bool `yaml:"disable-protocol-update"` } // Config 总配置文件 diff --git a/modules/config/default_config.yml b/modules/config/default_config.yml index 9e4acd8..56d51f7 100644 --- a/modules/config/default_config.yml +++ b/modules/config/default_config.yml @@ -15,6 +15,8 @@ account: # 账号相关 use-sso-address: true # 是否允许发送临时会话消息 allow-temp-session: false + # 是否禁用协议更新 + disable-protocol-update: false heartbeat: # 心跳频率, 单位秒