From 8b69410ded748e7bd6388994eb84d14e7a0a5104 Mon Sep 17 00:00:00 2001 From: Redmomn <109732988+Redmomn@users.noreply.github.com> Date: Sat, 11 Jan 2025 16:13:40 +0800 Subject: [PATCH] update: LagrangeGo --- docs/.vitepress/nav.ts | 4 - docs/LagrangeGo/CreateBot/index.md | 67 --------------- docs/LagrangeGo/Example/index.md | 129 +++++++++++++++++++++++++---- docs/LagrangeGo/Login/index.md | 113 ++++++++++++++++++++----- docs/LagrangeGo/index.md | 5 +- 5 files changed, 211 insertions(+), 107 deletions(-) delete mode 100644 docs/LagrangeGo/CreateBot/index.md diff --git a/docs/.vitepress/nav.ts b/docs/.vitepress/nav.ts index ef1450d3..6a701c5c 100644 --- a/docs/.vitepress/nav.ts +++ b/docs/.vitepress/nav.ts @@ -64,10 +64,6 @@ export const goNav = { text: "LagrangeGo", link: "/LagrangeGo/", }, - { - text: "Bot 实例", - link: "/LagrangeGo/CreateBot/", - }, { text: "登录", link: "/LagrangeGo/Login/", diff --git a/docs/LagrangeGo/CreateBot/index.md b/docs/LagrangeGo/CreateBot/index.md deleted file mode 100644 index 365290b4..00000000 --- a/docs/LagrangeGo/CreateBot/index.md +++ /dev/null @@ -1,67 +0,0 @@ -# 创建一个bot实例 - -## QQClient - -位于`github.com/LagrangeDev/LagrangeGo/client` - -> 创建一个QQClient,参数分别是qq号,appinfo,sign地址... - -方法签名: - -```go -func NewClient(uin uint32, appInfo *auth.AppInfo, signUrl ...string) *QQClient -``` - -示例 - -```go -qqclient := client.NewClient(0, appInfo,"https://sign.lagrangecore.org/api/sign") -``` - -## DeviceInfo - -```go -// 创建一个新的DeviceInfo,可使用随机数字作为参数 -deviceInfo := NewDeviceInfo(114514) -``` - -```go -// 加载DeviceInfo,如果指定的路径不存在,则返回一个新的info并保存 -deviceInfo := auth.LoadOrSaveDevice(path) - -// 保存DeviceInfo -deviceInfo.Save(path) -``` - -```go -qqclient.UseDevice(deviceInfo) -``` - -## SigInfo - -```go -// 序列化,得到的data可自行存储 -data, err := sig.Marshal() - -// 反序列化 -sig, err := UnmarshalSigInfo(data, true) -``` - -```go -// 存储与加载sig示例 -data, err := os.ReadFile("sig.bin") - if err != nil { - logrus.Warnln("read sig error:", err) - } else { - sig, err := auth.UnmarshalSigInfo(data, true) - if err != nil { - logrus.Warnln("load sig error:", err) - } else { - qqclient.UseSig(sig) - } - } -``` - -```go -qqclient.UseSig(sig) -``` diff --git a/docs/LagrangeGo/Example/index.md b/docs/LagrangeGo/Example/index.md index 41105770..f8b2fe69 100644 --- a/docs/LagrangeGo/Example/index.md +++ b/docs/LagrangeGo/Example/index.md @@ -3,10 +3,10 @@ 项目提供了示例模板`main.go`,可供开发者进行概念验证和功能测试 ```go -// nolint package main import ( + "errors" "fmt" "os" "os/signal" @@ -15,12 +15,13 @@ import ( "syscall" "time" + "github.com/mattn/go-colorable" + "github.com/sirupsen/logrus" + "github.com/LagrangeDev/LagrangeGo/client" "github.com/LagrangeDev/LagrangeGo/client/auth" "github.com/LagrangeDev/LagrangeGo/message" "github.com/LagrangeDev/LagrangeGo/utils" - "github.com/mattn/go-colorable" - "github.com/sirupsen/logrus" ) var ( @@ -28,29 +29,43 @@ var ( ) func main() { - appInfo := auth.AppList["linux"]["3.1.2-13107"] + // 使用特定的协议版本 + appInfo := auth.AppList["linux"]["3.2.15-30366"] + // 创建设备信息 deviceInfo := &auth.DeviceInfo{ - Guid: "cfcd208495d565ef66e7dff9f98764da", + GUID: "cfcd208495d565ef66e7dff9f98764da", DeviceName: "Lagrange-DCFCD07E", SystemKernel: "Windows 10.0.22631", KernelVersion: "10.0.22631", } - - qqclient := client.NewClient(0, appInfo, "https://sign.lagrangecore.org/api/sign") + + // 创建qqclient实例 + qqclient := client.NewClient(0, "") + // 设置qqclient的logger qqclient.SetLogger(protocolLogger{}) + // 使用协议版本 + qqclient.UseVersion(appInfo) + // 添加signserver,注意要和appinfo版本匹配 + qqclient.AddSignServer("https://sign.lagrangecore.org/api/sign/30366") + // 使用设备信息 qqclient.UseDevice(deviceInfo) + + // 从保存的sig.bin文件读取登录信息 data, err := os.ReadFile("sig.bin") if err != nil { logrus.Warnln("read sig error:", err) } else { + // 将登录信息反序列化 sig, err := auth.UnmarshalSigInfo(data, true) if err != nil { logrus.Warnln("load sig error:", err) } else { + // 如果登录信息有效,则使用登录信息登录 qqclient.UseSig(sig) } } - + + // 订阅群消息事件 qqclient.GroupMessageEvent.Subscribe(func(client *client.QQClient, event *message.GroupMessage) { if event.ToString() == "114514" { img, _ := message.NewFileImage("testgroup.png") @@ -69,26 +84,113 @@ func main() { } }) - err = qqclient.Login("", "qrcode.png") + qqclient.DisconnectedEvent.Subscribe(func(client *client.QQClient, event *client.DisconnectedEvent) { + logger.Infof("连接已断开:%v", event.Message) + }) + + err = func(c *client.QQClient, passwordLogin bool) error { + logger.Info("login with password") + // 如果登录信息存在,可以使用fastlogin + err := c.FastLogin() + if err == nil { + return nil + } + + if passwordLogin { + // 密码登录,目前无法使用 + ret, err := c.PasswordLogin() + for { + if err != nil { + logger.Errorf("密码登录失败: %s", err) + break + } + if ret.Success { + return nil + } + switch ret.Error { + case client.SliderNeededError: + logger.Warnln("captcha verification required") + logger.Warnln(ret.VerifyURL) + aid := strings.Split(strings.Split(ret.VerifyURL, "sid=")[1], "&")[0] + logger.Warnln("ticket?->") + ticket := utils.ReadLine() + logger.Warnln("rand_str?->") + randStr := utils.ReadLine() + ret, err = c.SubmitCaptcha(ticket, randStr, aid) + continue + case client.UnsafeDeviceError: + vf, err := c.GetNewDeviceVerifyURL() + if err != nil { + return err + } + logger.Infoln(vf) + err = c.NewDeviceVerify(vf) + if err != nil { + return err + } + default: + logger.Errorf("Unhandled exception raised: %s", ret.ErrorMessage) + } + } + } + logger.Infoln("login with qrcode") + + // 扫码登录流程 + // 首先获取二维码 + png, _, err := c.FetchQRCodeDefault() + if err != nil { + return err + } + qrcodePath := "qrcode.png" + // 保存到本地以供扫码 + err = os.WriteFile(qrcodePath, png, 0666) + if err != nil { + return err + } + logger.Infof("qrcode saved to %s", qrcodePath) + for { + // 轮询二维码扫描结果 + retCode, err := c.GetQRCodeResult() + if err != nil { + logger.Errorln(err) + return err + } + // 等待扫码 + if retCode.Waitable() { + time.Sleep(3 * time.Second) + continue + } + if !retCode.Success() { + return errors.New(retCode.Name()) + } + break + } + // 扫码完成后就可以进行登录 + _, err = c.QRCodeLogin() + return err + }(qqclient, false) + if err != nil { - logrus.Errorln("login err:", err) + logger.Errorln("login err:", err) return } + logger.Infoln("login successed") defer qqclient.Release() defer func() { + // 序列化登录信息以便下次使用 data, err = qqclient.Sig().Marshal() if err != nil { - logrus.Errorln("marshal sig.bin err:", err) + logger.Errorln("marshal sig.bin err:", err) return } err = os.WriteFile("sig.bin", data, 0644) if err != nil { - logrus.Errorln("write sig.bin err:", err) + logger.Errorln("write sig.bin err:", err) return } - logrus.Infoln("sig saved into sig.bin") + logger.Infoln("sig saved into sig.bin") }() // setup the main stop channel @@ -179,5 +281,4 @@ func (f *ColoredFormatter) Format(entry *logrus.Entry) ([]byte, error) { return utils.S2B(fmt.Sprintf("[%s] [%s%s%s]: %s\n", timestamp, levelColor, strings.ToUpper(entry.Level.String()), colorReset, entry.Message)), nil } - ``` diff --git a/docs/LagrangeGo/Login/index.md b/docs/LagrangeGo/Login/index.md index f169a2e9..b86e7afb 100644 --- a/docs/LagrangeGo/Login/index.md +++ b/docs/LagrangeGo/Login/index.md @@ -1,40 +1,115 @@ -# 登录 +# 登录前的准备 + +首先需要确保你已经生成了设备信息(DeviceInfo)和版本信息(AppInfo),以及与版本信息对应的签名服务器 + +## 创建设备信息 -## 自动选择登录方式(建议使用此方式) +> `import "github.com/LagrangeDev/LagrangeGo/client/auth"` ```go -err = qqclient.Login("password", "path/of/qrcode.png") +// 手动定义各个字段 +deviceInfo := &auth.DeviceInfo{ + GUID: "cfac208495d565ef66e7dff9f98764da", + DeviceName: "Lagrange-DCFCD07E", + SystemKernel: "Windows 10.0.22631", + KernelVersion: "10.0.22631", +} ``` -:::tip 提示 -当sig内有登录信息时,会优先进行快速登录 +```go +// 自动生成 +deviceInfo := auth.NewDeviceInfo(114514) +``` -密码为空则是扫码登录 -::: +```go +// 从文件读取 +deviceInfo,err := auth.LoadOrSaveDevice("path/to/deviceinfo.json") +``` -## 二维码登录 +## 创建版本信息 -> 首先获取登录二维码 +> `import "github.com/LagrangeDev/LagrangeGo/client/auth"` +[内置版本信息](https://github.com/LagrangeDev/LagrangeGo/blob/master/client/auth/app.go) ```go -qrcode, url, err = qqclient.FecthQRCode() +// 使用内置的版本信息 +appInfo := auth.AppList["linux"]["3.2.15-30366"] ``` -返回的元组包括 -| 字段 | 类型 | 备注 | -|:------:|:------:|:-------:| -| `qrcode` | []byte | 二维码图片数据 | -| `url` | string | 二维码内容链接 | -| `err` | error | 错误信息 | - :::tip 提示 -二维码内容链接需要被转换为二维码图片后通过手机 App 扫码登录, 不要直接访问链接 +此外,你还需要准备好与版本对应的签名服务器url ::: +## 创建一个`qqclient`实例 + +> `import "github.com/LagrangeDev/LagrangeGo/client"` + +```go +// 创建一个空的client +qqclient := client.NewClientEmpty() +``` + +## 将之前生成的信息加载进`qqclient` + +```go +// 设备信息 +qqclient.UseDevice(deviceInfo) +// 版本信息 +qqclient.UseVersion(appInfo) +``` + +## 添加签名服务器 + +```go +qqclient.AddSignServer("https://sign.lagrangecore.org/api/sign/30366") +``` + +# 登录 + +## 二维码登录 + +1. 首先获取登录二维码 + + ```go + qrcode, url, err = qqclient.FecthQRCode() + // 你可以将二维码保存到本地以便扫码 + os.WriteFile("path/to/qrcode.png", qrcode, 0666) + ``` + + 返回的元组包括 + | 字段 | 类型 | 备注 | + |:------:|:------:|:-------:| + | `qrcode` | []byte | 二维码图片数据 | + | `url` | string | 二维码内容链接 | + | `err` | error | 错误信息 | + + :::tip 提示 + 二维码内容链接需要被转换为二维码图片后通过手机 App 扫码登录, 不要直接访问链接 + ::: + +2. 轮询二维码扫码状态 + + ```go + retCode, err := c.GetQRCodeResult() + if retCode.Waitable() { + // 二维码在等待扫码或等待确认 + } + if retCode.Success() { + // 二维码扫码成功 + } + ``` + +3. 登录 + + ```go + // 等待扫码完成后即可登录 + _, err := qqclient.QRCodeLogin() + ``` + ## 密码登录 > 不保证可用性 ```go -err = qqclient.PasswordLogin("password") +err = qqclient.PasswordLogin() ``` diff --git a/docs/LagrangeGo/index.md b/docs/LagrangeGo/index.md index 4160b494..6dc82dd0 100644 --- a/docs/LagrangeGo/index.md +++ b/docs/LagrangeGo/index.md @@ -6,9 +6,8 @@ 1. 引入包 - ` go get -u github.com/LagrangeDev/LagrangeGo` -2. [创建 Bot 实例](CreateBot/) -3. [登录](Login/) -4. [监听并处理 Bot 收到的消息等事件](Event/) +2. [登录](Login/) +3. [监听并处理 Bot 收到的消息等事件](Event/) [查看示例](Example/)