├── .github └── workflows │ ├── ci.yml │ └── test_and_lint.yml ├── .gitignore ├── .golangci.yml ├── LICENSE ├── Makefile ├── README.md ├── client ├── album.go ├── auth │ ├── app.go │ ├── device.go │ └── sig.go ├── base.go ├── cache.go ├── client.go ├── entities.go ├── entity │ ├── avatar.go │ ├── group.go │ ├── group_airecord.go │ ├── group_file.go │ ├── group_honor.go │ ├── group_member.go │ ├── group_notice.go │ ├── rkey.go │ └── user.go ├── event.go ├── event │ ├── friend.go │ ├── group.go │ ├── impl.go │ └── self.go ├── global.go ├── handler.go ├── highway.go ├── internal │ ├── cache │ │ ├── base.go │ │ ├── cache.go │ │ └── operation.go │ ├── highway │ │ ├── bdh.go │ │ ├── frame.go │ │ └── highway.go │ ├── network │ │ ├── conn.go │ │ ├── packet.go │ │ ├── request.go │ │ ├── response.go │ │ └── transport.go │ └── oicq │ │ ├── ecdh.go │ │ └── oicq.go ├── listener.go ├── log.go ├── loginerror_string.go ├── message.go ├── network.go ├── ntlogin.go ├── oicq.go ├── online_status.go ├── operation.go ├── packet.go ├── packets │ ├── album │ │ └── get_media_list.go │ ├── highway │ │ └── highway_url.go │ ├── message │ │ ├── multi_msg_download.go │ │ └── multi_msg_upload.go │ ├── oidb │ │ ├── builder.go │ │ ├── check_url_safely.go │ │ ├── delete_friend.go │ │ ├── fetch_client_key.go │ │ ├── fetch_cookie.go │ │ ├── fetch_friends.go │ │ ├── fetch_group.go │ │ ├── fetch_group_system_messages.go │ │ ├── fetch_groups.go │ │ ├── fetch_member.go │ │ ├── fetch_members.go │ │ ├── fetch_rkey.go │ │ ├── fetch_user_info.go │ │ ├── friend_like.go │ │ ├── get_group_atall_remain.go │ │ ├── group_airecord.go │ │ ├── group_file_count.go │ │ ├── group_file_delete.go │ │ ├── group_file_list.go │ │ ├── group_file_move.go │ │ ├── group_file_rename.go │ │ ├── group_file_space.go │ │ ├── group_file_upload.go │ │ ├── group_folder_create.go │ │ ├── group_folder_delete.go │ │ ├── group_folder_rename.go │ │ ├── group_fs_download.go │ │ ├── group_image_download.go │ │ ├── group_image_upload.go │ │ ├── group_record_download.go │ │ ├── group_record_upload.go │ │ ├── group_send_file.go │ │ ├── group_sign.go │ │ ├── group_video_download.go │ │ ├── group_video_upload.go │ │ ├── image_ocr.go │ │ ├── kick_group_member.go │ │ ├── poke.go │ │ ├── private_file_download.go │ │ ├── private_file_upload.go │ │ ├── private_image_download.go │ │ ├── private_image_upload.go │ │ ├── private_record_download.go │ │ ├── private_record_upload.go │ │ ├── private_video_download.go │ │ ├── private_video_upload.go │ │ ├── set_essence_message.go │ │ ├── set_friend_request.go │ │ ├── set_group_admin.go │ │ ├── set_group_global_mute.go │ │ ├── set_group_leave.go │ │ ├── set_group_member_mute.go │ │ ├── set_group_member_name.go │ │ ├── set_group_member_special_title.go │ │ ├── set_group_name.go │ │ ├── set_group_reaction.go │ │ ├── set_group_remark.go │ │ └── set_group_request.go │ ├── pb │ │ ├── action │ │ │ ├── action.pb.go │ │ │ └── action.proto │ │ ├── login │ │ │ ├── ecdh.pb.go │ │ │ ├── ecdh.proto │ │ │ ├── ntlogin.pb.go │ │ │ └── ntlogin.proto │ │ ├── message │ │ │ ├── action.pb.go │ │ │ ├── action.proto │ │ │ ├── c2c.pb.go │ │ │ ├── c2c.proto │ │ │ ├── component.pb.go │ │ │ ├── component.proto │ │ │ ├── element.pb.go │ │ │ ├── element.proto │ │ │ ├── message.pb.go │ │ │ ├── message.proto │ │ │ ├── notify.pb.go │ │ │ ├── notify.proto │ │ │ ├── routing.pb.go │ │ │ └── routing.proto │ │ ├── service │ │ │ ├── album │ │ │ │ ├── QunMedia_GetMediaList.pb.go │ │ │ │ └── QunMedia_GetMediaList.proto │ │ │ ├── highway │ │ │ │ ├── highway.pb.go │ │ │ │ └── highway.proto │ │ │ ├── oidb │ │ │ │ ├── NTV2RichMediaReq.pb.go │ │ │ │ ├── NTV2RichMediaReq.proto │ │ │ │ ├── NTV2RichMediaResp.pb.go │ │ │ │ ├── NTV2RichMediaResp.proto │ │ │ │ ├── OidbSvcTrpcTcp0x102A_0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x102A_0.proto │ │ │ │ ├── OidbSvcTrpcTcp0x102A_1.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x102A_1.proto │ │ │ │ ├── OidbSvcTrpcTcp0x1096_1.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x1096_1.proto │ │ │ │ ├── OidbSvcTrpcTcp0x1097_1.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x1097_1.proto │ │ │ │ ├── OidbSvcTrpcTcp0x10C0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x10C0.proto │ │ │ │ ├── OidbSvcTrpcTcp0x10C8.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x10C8.proto │ │ │ │ ├── OidbSvcTrpcTcp0x1253_1.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x1253_1.proto │ │ │ │ ├── OidbSvcTrpcTcp0x126B_0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x126B_0.proto │ │ │ │ ├── OidbSvcTrpcTcp0x5CF_11.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x5CF_11.proto │ │ │ │ ├── OidbSvcTrpcTcp0x6D6.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x6D6.proto │ │ │ │ ├── OidbSvcTrpcTcp0x6D7.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x6D7.proto │ │ │ │ ├── OidbSvcTrpcTcp0x6D8.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x6D8.proto │ │ │ │ ├── OidbSvcTrpcTcp0x6D9_4.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x6D9_4.proto │ │ │ │ ├── OidbSvcTrpcTcp0x7E5_104.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x7E5_104.proto │ │ │ │ ├── OidbSvcTrpcTcp0x88D_0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x88D_0.proto │ │ │ │ ├── OidbSvcTrpcTcp0x89A_0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x89A_0.proto │ │ │ │ ├── OidbSvcTrpcTcp0x89A_15.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x89A_15.proto │ │ │ │ ├── OidbSvcTrpcTcp0x89E_0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x89E_0.proto │ │ │ │ ├── OidbSvcTrpcTcp0x8A0_1.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x8A0_1.proto │ │ │ │ ├── OidbSvcTrpcTcp0x8A7_0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x8A7_0.proto │ │ │ │ ├── OidbSvcTrpcTcp0x8FC.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x8FC.proto │ │ │ │ ├── OidbSvcTrpcTcp0x9082.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x9082.proto │ │ │ │ ├── OidbSvcTrpcTcp0x929B_0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x929B_0.proto │ │ │ │ ├── OidbSvcTrpcTcp0x929D_0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x929D_0.proto │ │ │ │ ├── OidbSvcTrpcTcp0x972_6.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0x972_6.proto │ │ │ │ ├── OidbSvcTrpcTcp0xB5D_44.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xB5D_44.proto │ │ │ │ ├── OidbSvcTrpcTcp0xBCB_0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xBCB_0.proto │ │ │ │ ├── OidbSvcTrpcTcp0xE07_0.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xE07_0.proto │ │ │ │ ├── OidbSvcTrpcTcp0xE37_1200.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xE37_1200.proto │ │ │ │ ├── OidbSvcTrpcTcp0xE37_1700.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xE37_1700.proto │ │ │ │ ├── OidbSvcTrpcTcp0xE37_800.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xE37_800.proto │ │ │ │ ├── OidbSvcTrpcTcp0xEAC.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xEAC.proto │ │ │ │ ├── OidbSvcTrpcTcp0xEB7_1.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xEB7_1.proto │ │ │ │ ├── OidbSvcTrpcTcp0xED3_1.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xED3_1.proto │ │ │ │ ├── OidbSvcTrpcTcp0xF16_1.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xF16_1.proto │ │ │ │ ├── OidbSvcTrpcTcp0xFD4_1.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xFD4_1.proto │ │ │ │ ├── OidbSvcTrpcTcp0xFE1_2.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xFE1_2.proto │ │ │ │ ├── OidbSvcTrpcTcp0xFE5_2.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xFE5_2.proto │ │ │ │ ├── OidbSvcTrpcTcp0xFE7_3.pb.go │ │ │ │ ├── OidbSvcTrpcTcp0xFE7_3.proto │ │ │ │ ├── base.pb.go │ │ │ │ ├── base.proto │ │ │ │ ├── generics.pb.go │ │ │ │ └── generics.proto │ │ │ ├── service.pb.go │ │ │ └── service.proto │ │ ├── system │ │ │ ├── system.pb.go │ │ │ └── system.proto │ │ ├── tlv543.pb.go │ │ └── tlv543.proto │ ├── tlv │ │ ├── common.go │ │ └── qrcode.go │ └── wtlogin │ │ ├── exchange.go │ │ ├── loginstate │ │ └── enum.go │ │ ├── qrcodestate │ │ └── enum.go │ │ └── statusService.go ├── richmedia.go ├── sign │ ├── http.go │ ├── provider.go │ └── sign.go ├── statistics.go └── ticket.go ├── go.mod ├── go.sum ├── internal └── proto │ ├── dynamic.go │ ├── dynamic_test.go │ └── wrapper.go ├── main.go ├── message ├── build.go ├── default_thumb.jpg ├── elements.go ├── essence.go ├── message.go ├── multi.go └── source.go └── utils ├── audio ├── info.go └── type.go ├── binary ├── builder.go ├── builder_test.go ├── network.go ├── pool.go ├── reader.go └── utils.go ├── crypto ├── aes.go ├── ecdh │ ├── curve.go │ ├── define.go │ ├── ecdh.go │ ├── impl.go │ └── point.go ├── hash.go ├── rand.go ├── rand_1.21.go └── rand_1.22.go ├── img.go ├── log └── log.go ├── operator.go ├── platform └── platform.go ├── string.go ├── tcping.go └── time.go /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - 'master' 5 | paths: 6 | - '**.go' 7 | - 'go.mod' 8 | - '**.yml' 9 | 10 | name: ci 11 | 12 | env: 13 | GO111MODULE: on 14 | 15 | jobs: 16 | ci: 17 | runs-on: ubuntu-latest 18 | 19 | concurrency: 20 | group: ${{ github.ref }} 21 | cancel-in-progress: true 22 | 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v4 26 | 27 | - name: Install Go 28 | uses: actions/setup-go@v5 29 | with: 30 | go-version: ^1.23 31 | cache: false 32 | 33 | - name: Sort Imports 34 | run: | 35 | export PATH="$PATH:$GOPATH/bin" 36 | go install -v github.com/incu6us/goimports-reviser/v3@latest 37 | make sort 38 | 39 | - name: GolangCI-Lint 40 | uses: golangci/golangci-lint-action@v6 41 | with: 42 | version: 'v1.61.0' 43 | args: '--timeout 9999s' 44 | only-new-issues: true 45 | skip-save-cache: true 46 | 47 | - name: commit back 48 | if: github.repository_owner == 'LagrangeDev' 49 | continue-on-error: true 50 | run: | 51 | git config --local user.name 'github-actions[bot]' 52 | git config --local user.email '41898282+github-actions[bot]@users.noreply.github.com' 53 | git add . 54 | git commit -m "ci(chore): Fix stylings" 55 | git push 56 | -------------------------------------------------------------------------------- /.github/workflows/test_and_lint.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | paths: 4 | - '**.go' 5 | - 'go.mod' 6 | - '**.yml' 7 | pull_request: 8 | paths: 9 | - '**.go' 10 | - 'go.mod' 11 | - '**.yml' 12 | 13 | name: Test & Lint 14 | 15 | env: 16 | GO111MODULE: on 17 | 18 | jobs: 19 | test: 20 | runs-on: ubuntu-latest 21 | 22 | strategy: 23 | matrix: 24 | go-version: [ '1.20', '1.21', '1.22', '1.23' ] 25 | 26 | steps: 27 | - name: Code 28 | uses: actions/checkout@v4 29 | 30 | - name: Install Go 31 | uses: actions/setup-go@v5 32 | with: 33 | go-version: ${{ matrix.go-version }} 34 | cache: false 35 | - run: go get 36 | - run: go test -v -race ./... 37 | 38 | lint: 39 | runs-on: ubuntu-latest 40 | 41 | strategy: 42 | matrix: 43 | go-version: [ '1.20', '1.21', '1.22', '1.23' ] 44 | 45 | steps: 46 | - name: Code 47 | uses: actions/checkout@v4 48 | 49 | - name: Install Go 50 | uses: actions/setup-go@v5 51 | with: 52 | go-version: ${{ matrix.go-version }} 53 | cache: false 54 | 55 | - run: go get 56 | 57 | - name: Go vet 58 | run: go vet ./... 59 | 60 | - name: GolangCI-Lint 61 | uses: golangci/golangci-lint-action@v6 62 | with: 63 | version: 'v1.61.0' 64 | args: '--timeout 9999s' 65 | only-new-issues: ${{ github.event.name == 'pull_request' }} 66 | skip-save-cache: true 67 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errcheck: 3 | exclude-functions: 4 | - fmt:.* 5 | - io/ioutil:^Read.* 6 | 7 | goimports: 8 | local-prefixes: github.com/LagrangeDev/LagrangeGo 9 | 10 | forbidigo: 11 | forbid: 12 | - p: ^errors\.Errorf.*$ 13 | msg: Use fmt.Errorf with %w to replace it. 14 | 15 | linters: 16 | # please, do not use `enable-all`: it's deprecated and will be removed soon. 17 | # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint 18 | disable-all: true 19 | fast: false 20 | enable: 21 | - bodyclose 22 | #- depguard 23 | - dogsled 24 | - errcheck 25 | - copyloopvar 26 | - exhaustive 27 | #- funlen 28 | #- goconst 29 | - gocritic 30 | #- gocyclo 31 | - gofmt 32 | - goimports 33 | - goprintffuncname 34 | #- gosec 35 | - gosimple 36 | - govet 37 | - ineffassign 38 | #- misspell 39 | - nolintlint 40 | - rowserrcheck 41 | - staticcheck 42 | - stylecheck 43 | - typecheck 44 | - unconvert 45 | - unparam 46 | - unused 47 | - whitespace 48 | - prealloc 49 | - predeclared 50 | - asciicheck 51 | - revive 52 | - forbidigo 53 | - makezero 54 | 55 | 56 | run: 57 | # default concurrency is a available CPU number. 58 | # concurrency: 4 # explicitly omit this value to fully utilize available resources. 59 | timeout: 5m 60 | issues-exit-code: 1 61 | tests: false 62 | go: '1.23' 63 | 64 | # output configuration options 65 | output: 66 | formats: 67 | - format: "colored-line-number" 68 | path: stdout 69 | print-issued-lines: true 70 | print-linter-name: true 71 | uniq-by-line: true 72 | 73 | issues: 74 | # Fix found issues (if it's supported by the linter) 75 | fix: true 76 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # from https://github.com/Mrs4s/MiraiGo/blob/master/Makefile 2 | .PHONY: protoc-gen-golite-version clean install-protoc-plugin proto 3 | .DEFAULT_GOAL := proto 4 | 5 | PROTO_DIR=client/packets/pb 6 | PROTO_OUTPUT_PATH=client/packets 7 | PROTO_IMPORT_PATH=client/packets 8 | 9 | TARGET ?= default 10 | 11 | PROTO_FILES := \ 12 | $(PROTO_DIR)/action/*.proto \ 13 | $(PROTO_DIR)/login/*.proto \ 14 | $(PROTO_DIR)/message/*.proto \ 15 | $(PROTO_DIR)/system/*.proto \ 16 | $(PROTO_DIR)/service/*.proto \ 17 | $(PROTO_DIR)/service/highway/*.proto \ 18 | $(PROTO_DIR)/service/oidb/*.proto \ 19 | $(PROTO_DIR)/*.proto 20 | 21 | 22 | PROTOC_GEN_GOLITE_VERSION := \ 23 | $(shell grep "github.com/RomiChan/protobuf" go.mod | awk -F v '{print "v"$$2}') 24 | 25 | 26 | protoc-gen-golite-version: 27 | @echo "Use protoc-gen-golite version: $(PROTOC_GEN_GOLITE_VERSION)" 28 | 29 | clean: 30 | find . -name "*.pb.go" | xargs rm -f 31 | 32 | install-protoc-plugin: protoc-gen-golite-version 33 | go install github.com/RomiChan/protobuf/cmd/protoc-gen-golite@$(PROTOC_GEN_GOLITE_VERSION) 34 | 35 | proto: install-protoc-plugin 36 | protoc --golite_out=$(PROTO_OUTPUT_PATH) --golite_opt=paths=source_relative -I=$(PROTO_IMPORT_PATH) $(PROTO_FILES) 37 | 38 | protoFiles: 39 | protoc --golite_out=$(PROTO_OUTPUT_PATH) --golite_opt=paths=source_relative -I=$(PROTO_IMPORT_PATH) $(PROTO_DIR)/$(TARGET) 40 | 41 | fmt: 42 | go vet -stdmethods=false ./... 43 | 44 | sort: 45 | goimports-reviser -imports-order std,blanked,general,company,project -excludes .git/,client/packets/pb/*.go -recursive ./.. 46 | 47 | .EXPORT_ALL_VARIABLES: 48 | GO111MODULE = on 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LagrangeGo 2 | ntqq 协议的golang实现 移植于 [Lagrange.Core](https://github.com/KonataDev/Lagrange.Core) / 3 | [lagrange-python](https://github.com/LagrangeDev/lagrange-python) / [MiraiGo](https://github.com/Mrs4s/MiraiGo) 4 | 5 | ## 使用前声明 6 | 本项目为协议实现,不推荐直接使用。 7 | 8 | 基于此项目的[go-cqhttp](https://github.com/LagrangeDev/go-cqhttp)已经基本完善 [下载链接](https://github.com/LagrangeDev/go-cqhttp/actions/workflows/ci.yml) 9 | 10 | 也可使用模板框架 [LagrangeGo-Template](https://github.com/ExquisiteCore/LagrangeGo-Template) 进行开发。 11 | 12 | ## 使用方法 13 | 14 | ```bash 15 | go get -u github.com/LagrangeDev/LagrangeGo 16 | ``` 17 | 18 | ## 支持的功能 19 | 20 | ## 协议支持 21 | 22 |
23 | 已完成功能/开发计划列表 24 | 25 | **登录** 26 | - [x] ~~账号密码登录~~ 27 | - [x] 二维码登录 28 | - [ ] 验证码提交 29 | - [ ] 设备锁验证 30 | - [ ] 错误信息解析 31 | 32 | **消息类型** 33 | - [x] 文本 34 | - [x] 图片 35 | - [x] 语音 36 | - [x] 表情 37 | - [x] At 38 | - [x] 回复 39 | - [x] 长消息 40 | - [ ] 链接分享 41 | - [x] 小程序(暂只支持RAW) 42 | - [x] 短视频 43 | - [x] 合并转发 44 | - [x] 私聊文件&群文件(上传与接收信息) 45 | 46 | **事件** 47 | - [x] 好友消息 48 | - [x] 群消息 49 | - [ ] 临时会话消息 50 | - [x] 登录号加群 51 | - [x] 登录号退群(包含T出) 52 | - [x] 新成员进群/退群 53 | - [x] 群/好友消息撤回 54 | - [x] 群禁言 55 | - [x] 群成员权限变更 56 | - [x] 收到邀请进群通知 57 | - [x] 收到其他用户进群请求 58 | - [ ] 新好友 59 | - [x] 新好友请求 60 | - [ ] 客户端离线 61 | - [ ] 群提示 (戳一戳/运气王等)(部分) 62 | 63 | **主动操作** 64 | 65 | _为防止滥用,不支持主动邀请新成员进群_ 66 | 67 | - [x] 发送群消息 68 | - [x] 发送好友消息 69 | - [ ] 发送临时会话消息 70 | - [x] 获取/刷新群列表 71 | - [x] 获取/刷新群成员列表 72 | - [x] 获取/刷新好友列表 73 | - [x] 获取群荣誉 (龙王/群聊火焰等) 74 | - [x] 处理加群请求 75 | - [x] 处理被邀请加群请求 76 | - [x] 处理好友请求 77 | - [x] 撤回群消息 78 | - [x] 群公告设置 79 | - [x] 获取群文件下载链接 80 | - [x] 群设置 (全体禁言/群名) 81 | - [x] 修改群成员Card 82 | - [x] 修改群成员头衔 83 | - [ ] ~~群成员邀请~~ 84 | - [x] 群成员禁言/解除禁言 85 | - [x] T出群成员 86 | - [x] 戳一戳群友 87 | - [x] 获取陌生人信息 88 | 89 |
90 | 91 | ### 不支持的协议 92 | **基于 [QQ钱包支付用户服务协议](https://www.tenpay.com/v2/html5/basic/public/agreement/protocol_mqq_pay.shtml) 不支持一切有关QQ钱包的协议** 93 | 94 | >4.13 您不得利用本服务实施下列任一的行为: 95 | >\ 96 | > (9) **侵害QQ钱包支付服务系統;** 97 | 98 | - [ ] ~~QQ钱包协议(收款/付款等)~~ 99 | 100 | ### 贡献者 101 | 102 | [![Contributors](https://contributors-img.web.app/image?repo=LagrangeDev/LagrangeGo)](https://github.com/LagrangeDev/LagrangeGo/graphs/contributors) 103 | 104 | [MiraiGo](https://github.com/Mrs4s/MiraiGo) 105 | [![Contributors](https://contributors-img.web.app/image?repo=Mrs4s/MiraiGo)](https://github.com/Mrs4s/MiraiGo/graphs/contributors) 106 | 107 | -------------------------------------------------------------------------------- /client/auth/device.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "os" 7 | "strconv" 8 | 9 | "github.com/LagrangeDev/LagrangeGo/utils" 10 | "github.com/LagrangeDev/LagrangeGo/utils/crypto" 11 | "github.com/LagrangeDev/LagrangeGo/utils/platform" 12 | ) 13 | 14 | type DeviceInfo struct { 15 | GUID string `json:"guid"` 16 | DeviceName string `json:"device_name"` 17 | SystemKernel string `json:"system_kernel"` 18 | KernelVersion string `json:"kernel_version"` 19 | } 20 | 21 | func NewDeviceInfo(uin int) *DeviceInfo { 22 | return &DeviceInfo{ 23 | GUID: fmt.Sprintf("%X", crypto.MD5Digest(utils.S2B(strconv.Itoa(uin)))), 24 | DeviceName: fmt.Sprintf("Lagrange-%X", crypto.MD5Digest(utils.S2B(strconv.Itoa(uin)))[0:4]), 25 | SystemKernel: fmt.Sprintf("%s %s", platform.System(), platform.Version()), 26 | KernelVersion: platform.Version(), 27 | } 28 | } 29 | 30 | func LoadOrSaveDevice(path string) (*DeviceInfo, error) { 31 | data, err := os.ReadFile(path) 32 | if err != nil { 33 | deviceinfo := NewDeviceInfo(int(crypto.RandU32())) 34 | return deviceinfo, deviceinfo.Save(path) 35 | } 36 | var dinfo DeviceInfo 37 | err = json.Unmarshal(data, &dinfo) 38 | if err != nil { 39 | deviceinfo := NewDeviceInfo(int(crypto.RandU32())) 40 | return deviceinfo, deviceinfo.Save(path) 41 | } 42 | return &dinfo, nil 43 | } 44 | 45 | func (deviceInfo *DeviceInfo) Save(path string) error { 46 | data, err := json.Marshal(deviceInfo) 47 | if err != nil { 48 | return err 49 | } 50 | err = os.WriteFile(path, data, 0666) 51 | if err != nil { 52 | return err 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /client/auth/sig.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "bytes" 5 | "encoding/gob" 6 | "errors" 7 | 8 | "github.com/LagrangeDev/LagrangeGo/utils/binary" 9 | "github.com/LagrangeDev/LagrangeGo/utils/crypto" 10 | ) 11 | 12 | var ( 13 | ErrDataHashMismatch = errors.New("data hash mismatch") 14 | ) 15 | 16 | type SigInfo struct { 17 | Uin uint32 18 | Sequence uint32 19 | UID string 20 | 21 | Tgtgt []byte 22 | Tgt []byte 23 | D2 []byte 24 | D2Key []byte 25 | 26 | Qrsig []byte 27 | ExchangeKey []byte 28 | KeySig []byte 29 | Cookies string 30 | UnusualSig []byte 31 | TempPwd []byte 32 | CaptchaInfo [3]string 33 | 34 | NewDeviceVerifyURL string 35 | 36 | Nickname string 37 | Age uint8 38 | Gender uint8 39 | } 40 | 41 | func init() { 42 | // 这里不注册好像也可以 43 | gob.Register(SigInfo{}) 44 | } 45 | 46 | func (sig *SigInfo) ClearSession() { 47 | sig.D2 = make([]byte, 0) 48 | sig.Tgt = make([]byte, 0) 49 | sig.D2Key = make([]byte, 16) 50 | } 51 | 52 | func (sig *SigInfo) Marshal() ([]byte, error) { 53 | buffer := binary.NewBuilder() 54 | err := gob.NewEncoder(buffer).Encode(sig) 55 | if err != nil { 56 | return nil, err 57 | } 58 | data := buffer.ToBytes() 59 | dataHash := crypto.MD5Digest(data) 60 | return binary.NewBuilder(). 61 | WriteLenBytes(dataHash). 62 | WriteLenBytes(data). 63 | ToBytes(), nil 64 | } 65 | 66 | func UnmarshalSigInfo(buf []byte, verify bool) (siginfo SigInfo, err error) { 67 | reader := binary.NewReader(buf) 68 | dataHash := reader.ReadBytesWithLength("u16", false) 69 | data := reader.ReadBytesWithLength("u16", false) 70 | 71 | if verify && !bytes.Equal(dataHash, crypto.MD5Digest(data)) { 72 | err = ErrDataHashMismatch 73 | return 74 | } 75 | 76 | err = gob.NewDecoder(bytes.NewReader(data)).Decode(&siginfo) 77 | return 78 | } 79 | -------------------------------------------------------------------------------- /client/entities.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/client/entities.go 4 | 5 | import ( 6 | "errors" 7 | 8 | "github.com/LagrangeDev/LagrangeGo/message" 9 | ) 10 | 11 | var ( 12 | ErrAlreadyOnline = errors.New("already online") 13 | ErrNotOnline = errors.New("not online") 14 | ErrMemberNotFound = errors.New("member not found") 15 | ErrNotExists = errors.New("not exists") 16 | ) 17 | 18 | type DisconnectedEvent struct { 19 | Message string 20 | } 21 | 22 | type groupMessageReceiptEvent struct { 23 | Rand int32 24 | Seq int32 25 | Msg *message.GroupMessage 26 | } 27 | -------------------------------------------------------------------------------- /client/entity/avatar.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import "fmt" 4 | 5 | func UserAvatar(uin uint32) string { 6 | return fmt.Sprintf("https://q1.qlogo.cn/g?b=qq&nk=%v&s=640", uin) 7 | } 8 | 9 | func GroupAvatar(groupUin uint32) string { 10 | return fmt.Sprintf("https://p.qlogo.cn/gh/%v/%v/0/", groupUin, groupUin) 11 | } 12 | -------------------------------------------------------------------------------- /client/entity/group_airecord.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type ChatType uint32 4 | 5 | const ( 6 | ChatTypeVoice ChatType = 1 7 | ChatTypeSong ChatType = 2 8 | ) 9 | 10 | type ( 11 | AiCharacter struct { 12 | Name string `json:"name"` 13 | VoiceID string `json:"voice_id"` 14 | VoiceURL string `json:"voice_url"` 15 | } 16 | 17 | AiCharacterInfo struct { 18 | Type string `json:"type"` 19 | Characters []AiCharacter `json:"characters"` 20 | } 21 | 22 | AiCharacterList struct { 23 | Type ChatType `json:"type"` 24 | List []AiCharacterInfo `json:"chats"` 25 | } 26 | ) 27 | -------------------------------------------------------------------------------- /client/entity/group_file.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type GroupFileSystemInfo struct { 4 | GroupUin uint32 `json:"group_id"` 5 | FileCount uint32 `json:"file_count"` 6 | LimitCount uint32 `json:"limit_count"` 7 | UsedSpace uint64 `json:"used_space"` 8 | TotalSpace uint64 `json:"total_space"` 9 | } 10 | 11 | type GroupFile struct { 12 | GroupUin uint32 `json:"group_id"` 13 | FileID string `json:"file_id"` 14 | FileName string `json:"file_name"` 15 | BusID uint32 `json:"busid"` 16 | FileSize uint64 `json:"file_size"` 17 | UploadTime uint32 `json:"upload_time"` 18 | DeadTime uint32 `json:"dead_time"` 19 | ModifyTime uint32 `json:"modify_time"` 20 | DownloadTimes uint32 `json:"download_times"` 21 | Uploader uint32 `json:"uploader"` 22 | UploaderName string `json:"uploader_name"` 23 | } 24 | 25 | type GroupFolder struct { 26 | GroupUin uint32 `json:"group_id"` 27 | FolderID string `json:"folder_id"` 28 | FolderName string `json:"folder_name"` 29 | CreateTime uint32 `json:"create_time"` 30 | Creator uint32 `json:"creator"` 31 | CreatorName string `json:"creator_name"` 32 | TotalFileCount uint32 `json:"total_file_count"` 33 | } 34 | -------------------------------------------------------------------------------- /client/entity/group_honor.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | // reference https://github.com/Mrs4s/MiraiGo/blob/master/client/http_api.go 4 | type ( 5 | HonorType int 6 | 7 | GroupHonorInfo struct { 8 | GroupCode string `json:"gc"` 9 | Uin string `json:"uin"` 10 | Type HonorType `json:"type"` 11 | TalkativeList []HonorMemberInfo `json:"talkativeList"` 12 | CurrentTalkative CurrentTalkative `json:"currentTalkative"` 13 | ActorList []HonorMemberInfo `json:"actorList"` 14 | LegendList []HonorMemberInfo `json:"legendList"` 15 | StrongNewbieList []HonorMemberInfo `json:"strongnewbieList"` 16 | EmotionList []HonorMemberInfo `json:"emotionList"` 17 | } 18 | 19 | HonorMemberInfo struct { 20 | Uin int64 `json:"uin"` 21 | Avatar string `json:"avatar"` 22 | Name string `json:"name"` 23 | Desc string `json:"desc"` 24 | } 25 | 26 | CurrentTalkative struct { 27 | Uin int64 `json:"uin"` 28 | DayCount int32 `json:"day_count"` 29 | Avatar string `json:"avatar"` 30 | Name string `json:"nick"` 31 | } 32 | ) 33 | 34 | const ( 35 | Talkative HonorType = 1 // 龙王 36 | Performer HonorType = 2 // 群聊之火 37 | Legend HonorType = 3 // 群聊炙焰 38 | StrongNewbie HonorType = 5 // 冒尖小春笋 39 | Emotion HonorType = 6 // 快乐源泉 40 | ) 41 | -------------------------------------------------------------------------------- /client/entity/group_member.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type GroupMemberPermission uint32 4 | 5 | const ( 6 | Member GroupMemberPermission = iota 7 | Owner 8 | Admin 9 | ) 10 | 11 | type GroupMember struct { 12 | User 13 | Permission GroupMemberPermission 14 | GroupLevel uint32 15 | MemberCard string 16 | SpecialTitle string 17 | JoinTime uint32 18 | LastMsgTime uint32 19 | ShutUpTime uint32 20 | } 21 | 22 | func (m *GroupMember) DisplayName() string { 23 | if m.MemberCard != "" { 24 | return m.MemberCard 25 | } 26 | return m.Nickname 27 | } 28 | -------------------------------------------------------------------------------- /client/entity/group_notice.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | // reference https://github.com/Mrs4s/MiraiGo/blob/master/client/http_api.go 4 | 5 | type ( 6 | GroupNoticeRsp struct { 7 | Feeds []*GroupNoticeFeed `json:"feeds"` 8 | Inst []*GroupNoticeFeed `json:"inst"` 9 | } 10 | 11 | GroupNoticeFeed struct { 12 | NoticeID string `json:"fid"` 13 | SenderID uint32 `json:"u"` 14 | PublishTime uint64 `json:"pubt"` 15 | Message struct { 16 | Text string `json:"text"` 17 | Images []NoticeImage `json:"pics"` 18 | } `json:"msg"` 19 | } 20 | 21 | NoticePicUpResponse struct { 22 | ErrorCode int `json:"ec"` 23 | ErrorMessage string `json:"em"` 24 | ID string `json:"id"` 25 | } 26 | 27 | NoticeImage struct { 28 | Height string `json:"h"` 29 | Width string `json:"w"` 30 | ID string `json:"id"` 31 | } 32 | 33 | NoticeSendResp struct { 34 | NoticeID string `json:"new_fid"` 35 | } 36 | ) 37 | -------------------------------------------------------------------------------- /client/entity/rkey.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type ( 4 | RKeyType uint32 5 | RKeyMap map[RKeyType]*RKeyInfo 6 | ) 7 | 8 | const ( 9 | FriendRKey RKeyType = 10 10 | GroupRKey RKeyType = 20 11 | ) 12 | 13 | type RKeyInfo struct { 14 | RKeyType RKeyType 15 | RKey string 16 | CreateTime uint64 17 | ExpireTime uint64 18 | } 19 | -------------------------------------------------------------------------------- /client/entity/user.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type User struct { 4 | Uin uint32 5 | UID string 6 | Nickname string 7 | Remarks string 8 | PersonalSign string 9 | Avatar string 10 | Age uint32 11 | Sex uint32 // 1男 2女 255不可见 12 | Level uint32 13 | Source string // 好友来源 14 | 15 | QID string 16 | 17 | Country string 18 | City string 19 | School string 20 | 21 | VipLevel uint32 22 | } 23 | -------------------------------------------------------------------------------- /client/event.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/client/events.go 4 | 5 | import ( 6 | "runtime/debug" 7 | "sync" 8 | ) 9 | 10 | // protected all EventHandle, since write is very rare, use 11 | // only one lock to save memory 12 | var eventMu sync.RWMutex 13 | 14 | type EventHandle[T any] struct { 15 | // QQClient? 16 | handlers []func(client *QQClient, event T) 17 | } 18 | 19 | func (handle *EventHandle[T]) Subscribe(handler func(client *QQClient, event T)) { 20 | eventMu.Lock() 21 | defer eventMu.Unlock() 22 | // shrink the slice 23 | newHandlers := make([]func(client *QQClient, event T), len(handle.handlers)+1) 24 | copy(newHandlers, handle.handlers) 25 | newHandlers[len(handle.handlers)] = handler 26 | handle.handlers = newHandlers 27 | } 28 | 29 | func (handle *EventHandle[T]) dispatch(client *QQClient, event T) { 30 | eventMu.RLock() 31 | defer func() { 32 | eventMu.RUnlock() 33 | if pan := recover(); pan != nil { 34 | client.error("event error: %v\n%s", pan, debug.Stack()) 35 | } 36 | }() 37 | for _, handler := range handle.handlers { 38 | handler(client, event) 39 | } 40 | } 41 | 42 | type eventHandlers struct { 43 | subscribedEventHandlers []any 44 | groupMessageReceiptHandlers sync.Map 45 | } 46 | 47 | func (c *QQClient) SubscribeEventHandler(handler any) { 48 | c.eventHandlers.subscribedEventHandlers = append(c.eventHandlers.subscribedEventHandlers, handler) 49 | } 50 | 51 | func (c *QQClient) onGroupMessageReceipt(id string, f ...func(*QQClient, *groupMessageReceiptEvent)) { 52 | if len(f) == 0 { 53 | c.eventHandlers.groupMessageReceiptHandlers.Delete(id) 54 | return 55 | } 56 | c.eventHandlers.groupMessageReceiptHandlers.LoadOrStore(id, f[0]) 57 | } 58 | -------------------------------------------------------------------------------- /client/event/impl.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | type INotifyEvent interface { 4 | From() uint32 5 | Content() string 6 | } 7 | -------------------------------------------------------------------------------- /client/event/self.go: -------------------------------------------------------------------------------- 1 | package event 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/auth" 5 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/message" 6 | ) 7 | 8 | func ParseSelfRenameEvent(event *message.SelfRenameMsg, sig *auth.SigInfo) *Rename { 9 | sig.Nickname = event.Body.RenameData.NickName 10 | return &Rename{ 11 | Uin: event.Body.Uin, 12 | Nickname: event.Body.RenameData.NickName, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /client/global.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/client/global.go 4 | 5 | import ( 6 | "net" 7 | "time" 8 | 9 | "github.com/pkg/errors" 10 | ) 11 | 12 | func qualityTest(addr string) (int64, error) { 13 | // see QualityTestManager 14 | start := time.Now() 15 | conn, err := net.DialTimeout("tcp", addr, time.Second*5) 16 | if err != nil { 17 | return 0, errors.Wrap(err, "failed to connect to server during quality test") 18 | } 19 | _ = conn.Close() 20 | return time.Since(start).Milliseconds(), nil 21 | } 22 | -------------------------------------------------------------------------------- /client/handler.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import "github.com/LagrangeDev/LagrangeGo/client/internal/network" 4 | 5 | // handlerInfo from https://github.com/Mrs4s/MiraiGo/blob/54bdd873e3fed9fe1c944918924674dacec5ac76/client/client.go#L137 6 | type handlerInfo struct { 7 | fun func(i any, err error) 8 | dynamic bool 9 | params network.RequestParams 10 | } 11 | 12 | func (h *handlerInfo) getParams() network.RequestParams { 13 | if h == nil { 14 | return nil 15 | } 16 | return h.params 17 | } 18 | -------------------------------------------------------------------------------- /client/internal/cache/operation.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/entity" 5 | ) 6 | 7 | func (c *Cache) RefreshAll( 8 | friendCache map[uint32]*entity.User, 9 | groupCache map[uint32]*entity.Group, 10 | groupMemberCache map[uint32]map[uint32]*entity.GroupMember, 11 | rkeyCache entity.RKeyMap, 12 | ) { 13 | c.RefreshAllFriend(friendCache) 14 | c.RefreshAllGroup(groupCache) 15 | c.RefreshAllGroupMembers(groupMemberCache) 16 | c.RefreshAllRKeyInfo(rkeyCache) 17 | } 18 | 19 | // RefreshFriend 刷新一个好友的缓存 20 | func (c *Cache) RefreshFriend(friend *entity.User) { 21 | setCacheOf(c, friend.Uin, friend) 22 | } 23 | 24 | // RefreshAllFriend 刷新所有好友缓存 25 | func (c *Cache) RefreshAllFriend(friendCache map[uint32]*entity.User) { 26 | refreshAllCacheOf(c, friendCache) 27 | } 28 | 29 | // RefreshGroupMember 刷新指定群的一个群成员缓存 30 | func (c *Cache) RefreshGroupMember(groupUin uint32, groupMember *entity.GroupMember) { 31 | group, ok := getCacheOf[Cache](c, groupUin) 32 | if !ok { 33 | group = &Cache{} 34 | setCacheOf(c, groupUin, group) 35 | } 36 | setCacheOf(group, groupMember.Uin, groupMember) 37 | } 38 | 39 | // RefreshGroupMembers 刷新一个群内的所有群成员缓存 40 | func (c *Cache) RefreshGroupMembers(groupUin uint32, groupMembers map[uint32]*entity.GroupMember) { 41 | newc := &Cache{} 42 | refreshAllCacheOf(newc, groupMembers) 43 | setCacheOf(c, groupUin, newc) 44 | } 45 | 46 | // RefreshAllGroupMembers 刷新所有群的群员缓存 47 | func (c *Cache) RefreshAllGroupMembers(groupMemberCache map[uint32]map[uint32]*entity.GroupMember) { 48 | newc := make(map[uint32]*Cache, len(groupMemberCache)*2) 49 | for groupUin, v := range groupMemberCache { 50 | group := &Cache{} 51 | refreshAllCacheOf(group, v) 52 | newc[groupUin] = group 53 | } 54 | refreshAllCacheOf(c, newc) 55 | } 56 | 57 | // RefreshGroup 刷新一个群的群信息缓存 58 | func (c *Cache) RefreshGroup(group *entity.Group) { 59 | setCacheOf(c, group.GroupUin, group) 60 | } 61 | 62 | // RefreshAllGroup 刷新所有群的群信息缓存 63 | func (c *Cache) RefreshAllGroup(groupCache map[uint32]*entity.Group) { 64 | refreshAllCacheOf(c, groupCache) 65 | } 66 | 67 | // RefreshAllRKeyInfo 刷新所有RKey缓存 68 | func (c *Cache) RefreshAllRKeyInfo(rkeyCache entity.RKeyMap) { 69 | refreshAllCacheOf(c, rkeyCache) 70 | } 71 | -------------------------------------------------------------------------------- /client/internal/highway/frame.go: -------------------------------------------------------------------------------- 1 | package highway 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/tree/master/client/internal/highway/frame.go 4 | 5 | import ( 6 | "encoding/binary" 7 | "net" 8 | ) 9 | 10 | var etx = []byte{0x29} 11 | 12 | // Frame 包格式 13 | // 14 | // - STX: 0x28(40) 15 | // - head length 16 | // - body length 17 | // - head data 18 | // - body data 19 | // - ETX: 0x29(41) 20 | // 21 | // 节省内存, 可被go runtime优化为writev操作 22 | func Frame(head []byte, body []byte) net.Buffers { 23 | buffers := make(net.Buffers, 4) 24 | // buffer0 format: 25 | // - STX 26 | // - head length 27 | // - body length 28 | buffer0 := make([]byte, 9) 29 | buffer0[0] = 0x28 30 | binary.BigEndian.PutUint32(buffer0[1:], uint32(len(head))) 31 | binary.BigEndian.PutUint32(buffer0[5:], uint32(len(body))) 32 | buffers[0] = buffer0 33 | buffers[1] = head 34 | buffers[2] = body 35 | buffers[3] = etx 36 | return buffers 37 | } 38 | -------------------------------------------------------------------------------- /client/internal/network/packet.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/client/internal/network/packet.go 4 | 5 | type Packet struct { 6 | SequenceID uint32 7 | CommandName string 8 | Payload []byte 9 | Params RequestParams 10 | } 11 | 12 | type RequestParams map[string]any 13 | 14 | func (p RequestParams) Bool(k string) bool { 15 | if p == nil { 16 | return false 17 | } 18 | i, ok := p[k] 19 | if !ok { 20 | return false 21 | } 22 | return i.(bool) 23 | } 24 | 25 | func (p RequestParams) Int32(k string) int32 { 26 | if p == nil { 27 | return 0 28 | } 29 | i, ok := p[k] 30 | if !ok { 31 | return 0 32 | } 33 | return i.(int32) 34 | } 35 | -------------------------------------------------------------------------------- /client/internal/network/request.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import "github.com/LagrangeDev/LagrangeGo/client/sign" 4 | 5 | // from https://github.com/Mrs4s/MiraiGo/blob/master/client/internal/network/request.go 6 | 7 | type RequestType uint32 8 | 9 | const ( 10 | RequestTypeLogin = 0x0A 11 | RequestTypeSimple = 0x0B 12 | RequestTypeNT = 0x0C 13 | ) 14 | 15 | type EncryptType uint32 16 | 17 | const ( 18 | EncryptTypeNoEncrypt EncryptType = iota // 0x00 19 | EncryptTypeD2Key // 0x01 20 | EncryptTypeEmptyKey // 0x02 21 | ) 22 | 23 | type Request struct { 24 | SequenceID uint32 25 | Uin int64 26 | Sign *sign.Response 27 | CommandName string 28 | Body []byte 29 | } 30 | -------------------------------------------------------------------------------- /client/internal/network/transport.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/client/internal/network/transport.go 4 | 5 | import ( 6 | "strconv" 7 | 8 | tea "github.com/fumiama/gofastTEA" 9 | 10 | "github.com/LagrangeDev/LagrangeGo/client/auth" 11 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 12 | "github.com/LagrangeDev/LagrangeGo/utils" 13 | "github.com/LagrangeDev/LagrangeGo/utils/binary" 14 | ) 15 | 16 | // Transport is a network transport. 17 | type Transport struct { 18 | Sig auth.SigInfo 19 | Version *auth.AppInfo 20 | Device *auth.DeviceInfo 21 | } 22 | 23 | // PackPacket packs a packet. 24 | func (t *Transport) PackPacket(req *Request) []byte { 25 | head := proto.DynamicMessage{ 26 | 15: utils.NewTrace(), 27 | 16: t.Sig.UID, 28 | } 29 | 30 | if req.Sign != nil { 31 | sign := req.Sign.Value 32 | head[24] = proto.DynamicMessage{ 33 | 1: []byte(sign.Sign), 34 | 2: []byte(sign.Token), 35 | 3: []byte(sign.Extra), 36 | } 37 | } 38 | 39 | ssoHeader := binary.NewBuilder(). 40 | WriteU32(req.SequenceID). 41 | WriteU32(uint32(t.Version.SubAppID)). 42 | WriteU32(2052). // locate id 43 | WriteBytes(append([]byte{0x02}, make([]byte, 11)...)). //020000000000000000000000 44 | WritePacketBytes(t.Sig.Tgt, "u32", true). 45 | WritePacketString(req.CommandName, "u32", true). 46 | WritePacketBytes(nil, "u32", true). 47 | WritePacketBytes(utils.MustParseHexStr(t.Device.GUID), "u32", true). 48 | WritePacketBytes(nil, "u32", true). 49 | WritePacketString(t.Version.CurrentVersion, "u16", true). 50 | WritePacketBytes(head.Encode(), "u32", true). 51 | ToBytes() 52 | 53 | ssoPacket := binary.NewBuilder(). 54 | WritePacketBytes(ssoHeader, "u32", true). 55 | WritePacketBytes(req.Body, "u32", true). 56 | ToBytes() 57 | 58 | encrypted := tea.NewTeaCipher(t.Sig.D2Key).Encrypt(ssoPacket) 59 | 60 | var _s uint8 61 | if len(t.Sig.D2) == 0 { 62 | _s = 2 63 | } else { 64 | _s = 1 65 | } 66 | 67 | service := binary.NewBuilder(). 68 | WriteU32(12). 69 | WriteU8(_s). 70 | WritePacketBytes(t.Sig.D2, "u32", true). 71 | WriteU8(0). 72 | WritePacketString(strconv.Itoa(int(req.Uin)), "u32", true). 73 | WriteBytes(encrypted). 74 | ToBytes() 75 | 76 | return binary.NewBuilder(). 77 | WritePacketBytes(service, "u32", true). 78 | ToBytes() 79 | } 80 | -------------------------------------------------------------------------------- /client/internal/oicq/ecdh.go: -------------------------------------------------------------------------------- 1 | package oicq 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/client/internal/oicq/ecdh.go 4 | 5 | import ( 6 | "crypto/ecdh" 7 | "crypto/md5" 8 | "crypto/rand" 9 | "encoding/hex" 10 | "encoding/json" 11 | "net/http" 12 | "strconv" 13 | ) 14 | 15 | // session is ecdh session in oicq. 16 | type session struct { 17 | SvrPublicKeyVer uint16 18 | PublicKey []byte 19 | ShareKey []byte 20 | } 21 | 22 | const serverPublicKey = "04EBCA94D733E399B2DB96EACDD3F69A8BB0F74224E2B44E3357812211D2E62EFBC91BB553098E25E33A799ADC7F76FEB208DA7C6522CDB0719A305180CC54A82E" 23 | 24 | func newSession() *session { 25 | e := &session{ 26 | SvrPublicKeyVer: 1, 27 | } 28 | key, _ := hex.DecodeString(serverPublicKey) 29 | e.init(key) 30 | return e 31 | } 32 | 33 | type pubKeyResp struct { 34 | Meta struct { 35 | PubKeyVer uint16 `json:"KeyVer"` 36 | PubKey string `json:"PubKey"` 37 | } `json:"PubKeyMeta"` 38 | } 39 | 40 | // fetchPubKey 从服务器获取PubKey 41 | func (e *session) fetchPubKey(uin int64) { 42 | resp, err := http.Get("https://keyrotate.qq.com/rotate_key?cipher_suite_ver=305&uin=" + strconv.FormatInt(uin, 10)) 43 | if err != nil { 44 | return 45 | } 46 | defer func() { _ = resp.Body.Close() }() 47 | pubKey := pubKeyResp{} 48 | err = json.NewDecoder(resp.Body).Decode(&pubKey) 49 | if err != nil { 50 | return 51 | } 52 | e.SvrPublicKeyVer = pubKey.Meta.PubKeyVer 53 | key, _ := hex.DecodeString(pubKey.Meta.PubKey) 54 | e.init(key) // todo check key sign 55 | } 56 | 57 | func (e *session) init(svrPubKey []byte) { 58 | p256 := ecdh.P256() 59 | local, _ := p256.GenerateKey(rand.Reader) 60 | remote, _ := p256.NewPublicKey(svrPubKey) 61 | share, _ := local.ECDH(remote) 62 | 63 | hash := md5.New() 64 | hash.Write(share[:16]) 65 | e.ShareKey = hash.Sum(nil) 66 | e.PublicKey = local.PublicKey().Bytes() 67 | } 68 | -------------------------------------------------------------------------------- /client/log.go: -------------------------------------------------------------------------------- 1 | //nolint:unused 2 | package client 3 | 4 | // from https://github.com/Mrs4s/MiraiGo/blob/master/client/log.go 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/LagrangeDev/LagrangeGo/utils/log" 10 | ) 11 | 12 | func (c *QQClient) SetLogger(logger log.Logger) { 13 | c.logger = logger 14 | } 15 | 16 | func (c *QQClient) info(msg string, args ...any) { 17 | if c.logger != nil { 18 | c.logger.Info(msg, args...) 19 | } 20 | } 21 | 22 | func (c *QQClient) infoln(msgs ...any) { 23 | if c.logger != nil { 24 | c.logger.Info(fmt.Sprint(msgs...)) 25 | } 26 | } 27 | 28 | func (c *QQClient) warning(msg string, args ...any) { 29 | if c.logger != nil { 30 | c.logger.Warning(log.Getcaller(msg), args...) 31 | } 32 | } 33 | 34 | func (c *QQClient) warningln(msgs ...any) { 35 | if c.logger != nil { 36 | c.logger.Warning(log.Getcaller(fmt.Sprint(msgs...))) 37 | } 38 | } 39 | 40 | func (c *QQClient) error(msg string, args ...any) { 41 | if c.logger != nil { 42 | c.logger.Error(log.Getcaller(msg), args...) 43 | } 44 | } 45 | 46 | func (c *QQClient) errorln(msgs ...any) { 47 | if c.logger != nil { 48 | c.logger.Error(log.Getcaller(fmt.Sprint(msgs...))) 49 | } 50 | } 51 | 52 | func (c *QQClient) debug(msg string, args ...any) { 53 | if c.logger != nil { 54 | c.logger.Debug(log.Getcaller(msg), args...) 55 | } 56 | } 57 | 58 | func (c *QQClient) debugln(msgs ...any) { 59 | if c.logger != nil { 60 | c.logger.Debug(log.Getcaller(fmt.Sprint(msgs...))) 61 | } 62 | } 63 | 64 | func (c *QQClient) dump(msg string, data []byte, args ...any) { 65 | if c.logger != nil { 66 | c.logger.Dump(data, log.Getcaller(msg), args...) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /client/loginerror_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=LoginError"; DO NOT EDIT. 2 | 3 | package client 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[NeedCaptcha-1] 12 | _ = x[OtherLoginError-3] 13 | _ = x[UnsafeDeviceError-4] 14 | _ = x[SMSNeededError-5] 15 | _ = x[TooManySMSRequestError-6] 16 | _ = x[SMSOrVerifyNeededError-7] 17 | _ = x[SliderNeededError-8] 18 | _ = x[UnknownLoginError - -1] 19 | } 20 | 21 | const ( 22 | _LoginError_name_0 = "UnknownLoginError" 23 | _LoginError_name_1 = "NeedCaptcha" 24 | _LoginError_name_2 = "OtherLoginErrorUnsafeDeviceErrorSMSNeededErrorTooManySMSRequestErrorSMSOrVerifyNeededErrorSliderNeededError" 25 | ) 26 | 27 | var ( 28 | _LoginError_index_2 = [...]uint8{0, 15, 32, 46, 68, 90, 107} 29 | ) 30 | 31 | func (i LoginError) String() string { 32 | switch { 33 | case i == -1: 34 | return _LoginError_name_0 35 | case i == 1: 36 | return _LoginError_name_1 37 | case 3 <= i && i <= 8: 38 | i -= 3 39 | return _LoginError_name_2[_LoginError_index_2[i]:_LoginError_index_2[i+1]] 40 | default: 41 | return "LoginError(" + strconv.FormatInt(int64(i), 10) + ")" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /client/packet.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/client/packet.go 4 | 5 | import ( 6 | "github.com/LagrangeDev/LagrangeGo/client/internal/network" 7 | ) 8 | 9 | func (c *QQClient) uniPacket(command string, body []byte) (uint32, []byte, error) { 10 | seq := c.getAndIncreaseSequence() 11 | sign, err := c.signProvider.Sign(command, seq, body) 12 | if err != nil { 13 | return 0, nil, err 14 | } 15 | req := network.Request{ 16 | SequenceID: seq, 17 | Uin: int64(c.Uin), 18 | Sign: sign, 19 | CommandName: command, 20 | Body: body, 21 | } 22 | return seq, c.transport.PackPacket(&req), nil 23 | } 24 | -------------------------------------------------------------------------------- /client/packets/album/get_media_list.go: -------------------------------------------------------------------------------- 1 | package album 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | 7 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/album" 8 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 9 | "github.com/LagrangeDev/LagrangeGo/utils" 10 | ) 11 | 12 | func BuildGetMediaListReq(selfUin uint32, groupUin uint32, albumID string, pageInfo string) ([]byte, error) { 13 | return proto.Marshal(&album.QzoneGetMediaList{ 14 | Field1: 0, 15 | Field2: "h5_test", 16 | Field3: "h5_test", 17 | Field4: &album.QzoneGetMediaList_F4{ 18 | GroupID: strconv.Itoa(int(groupUin)), 19 | AlbumID: albumID, 20 | Field3: 0, 21 | Field4: "", 22 | PageInfo: pageInfo, 23 | }, 24 | UinTimeStamp: utils.UinTimestamp(selfUin), 25 | Field10: &album.QzoneGetMediaList_F10{ 26 | AppIdFlag: "fc-appid", 27 | AppIdValue: "100", 28 | }, 29 | }) 30 | } 31 | 32 | func ParseGetMediaListResp(data []byte) (resp *album.QzoneGetMediaList_Response, err error) { 33 | resp = &album.QzoneGetMediaList_Response{} 34 | if err = proto.Unmarshal(data, resp); err != nil { 35 | return nil, err 36 | } 37 | if resp.ErrorCode.IsSome() && resp.ErrorMsg.IsSome() { 38 | return nil, errors.New(resp.ErrorMsg.Unwrap()) 39 | } 40 | return resp, nil 41 | } 42 | -------------------------------------------------------------------------------- /client/packets/highway/highway_url.go: -------------------------------------------------------------------------------- 1 | package highway 2 | 3 | import ( 4 | "encoding/hex" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/action" 7 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 8 | ) 9 | 10 | func BuildHighWayURLReq(tgt []byte) ([]byte, error) { 11 | return proto.Marshal(&action.HttpConn0X6Ff_501{ 12 | HttpConn: &action.HttpConn{ 13 | Field1: 0, 14 | Field2: 0, 15 | Field3: 16, 16 | Field4: 1, 17 | Tgt: hex.EncodeToString(tgt), 18 | Field6: 3, 19 | ServiceTypes: []int32{1, 5, 10, 21}, 20 | Field9: 2, 21 | Field10: 9, 22 | Field11: 8, 23 | Ver: "1.0.1", 24 | }, 25 | }) 26 | } 27 | 28 | func ParseHighWayURLReq(data []byte) (req action.HttpConn0X6Ff_501Response, err error) { 29 | err = proto.Unmarshal(data, &req) 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /client/packets/message/multi_msg_download.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/message" 5 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 6 | ) 7 | 8 | func BuildMultiMsgDownloadReq(uid string, resID string) ([]byte, error) { 9 | return proto.Marshal(&message.RecvLongMsgReq{ 10 | Info: &message.RecvLongMsgInfo{ 11 | Uid: &message.LongMsgUid{ 12 | Uid: proto.String(uid), 13 | }, 14 | ResId: proto.String(resID), 15 | Acquire: true, 16 | }, 17 | Settings: &message.LongMsgSettings{ 18 | Field1: 2, 19 | Field2: 0, 20 | Field3: 0, 21 | Field4: 0, 22 | }, 23 | }) 24 | } 25 | 26 | func ParseMultiMsgDownloadResp(data []byte) (resp *message.RecvLongMsgResp, err error) { 27 | resp = &message.RecvLongMsgResp{} 28 | if err = proto.Unmarshal(data, resp); err != nil { 29 | return nil, err 30 | } 31 | return resp, nil 32 | } 33 | -------------------------------------------------------------------------------- /client/packets/message/multi_msg_upload.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/message" 7 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 8 | "github.com/LagrangeDev/LagrangeGo/utils" 9 | "github.com/LagrangeDev/LagrangeGo/utils/binary" 10 | ) 11 | 12 | func BuildMultiMsgUploadReq(selfUID string, groupUin uint32, msg []*message.PushMsgBody) ([]byte, error) { 13 | longMsgResult := &message.LongMsgResult{ 14 | Action: []*message.LongMsgAction{{ 15 | ActionCommand: "MultiMsg", 16 | ActionData: &message.LongMsgContent{ 17 | MsgBody: msg, 18 | }, 19 | }}, 20 | } 21 | longMsgResultData, _ := proto.Marshal(longMsgResult) 22 | payload := binary.GZipCompress(longMsgResultData) 23 | req := &message.SendLongMsgReq{ 24 | Info: &message.SendLongMsgInfo{ 25 | Type: utils.Ternary[uint32](groupUin == 0, 1, 3), 26 | Uid: &message.LongMsgUid{ 27 | Uid: proto.String(utils.Ternary(groupUin == 0, selfUID, strconv.Itoa(int(groupUin)))), 28 | }, 29 | GroupUin: proto.Uint32(groupUin), 30 | Payload: payload, 31 | }, 32 | Settings: &message.LongMsgSettings{ 33 | Field1: 4, 34 | Field2: 1, 35 | Field3: 7, 36 | Field4: 0, 37 | }, 38 | } 39 | return proto.Marshal(req) 40 | } 41 | 42 | func ParseMultiMsgUploadResp(data []byte) (resp *message.SendLongMsgResp, err error) { 43 | resp = &message.SendLongMsgResp{} 44 | if err = proto.Unmarshal(data, resp); err != nil { 45 | return nil, err 46 | } 47 | return resp, nil 48 | } 49 | -------------------------------------------------------------------------------- /client/packets/oidb/builder.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | 7 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 8 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 9 | "github.com/LagrangeDev/LagrangeGo/utils" 10 | ) 11 | 12 | // var oidbLogger = utils.GetLogger("oidb") 13 | 14 | type Packet struct { 15 | Cmd string 16 | Data []byte 17 | ExtraData []byte 18 | } 19 | 20 | func BuildOidbPacket(cmd, subCmd uint32, body any, isLafter, isUID bool) (*Packet, error) { 21 | bodyData, err := proto.Marshal(body) 22 | if err != nil { 23 | return nil, err 24 | } 25 | oidbPkt := &oidb.OidbSvcTrpcTcpBase{ 26 | Command: cmd, 27 | SubCommand: subCmd, 28 | Body: bodyData, 29 | Reserved: int32(utils.Bool2Int(isUID)), 30 | } 31 | if isLafter { 32 | oidbPkt.Lafter = &oidb.OidbLafter{} 33 | } 34 | 35 | data, err := proto.Marshal(oidbPkt) 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | return &Packet{ 41 | Cmd: fmt.Sprintf("OidbSvcTrpcTcp.0x%02x_%d", cmd, subCmd), 42 | Data: data, 43 | }, nil 44 | } 45 | 46 | func ParseOidbPacket(b []byte, pkt any) (oidbBaseResp oidb.OidbSvcTrpcTcpBase, err error) { 47 | err = proto.Unmarshal(b, &oidbBaseResp) 48 | if err != nil { 49 | return 50 | } 51 | if oidbBaseResp.ErrorCode != 0 { 52 | return oidbBaseResp, errors.New(oidbBaseResp.ErrorMsg) 53 | } 54 | if pkt == nil { 55 | return 56 | } 57 | err = proto.Unmarshal(oidbBaseResp.Body, pkt) 58 | return 59 | } 60 | 61 | func CheckError(data []byte) error { 62 | baseResp, err := ParseOidbPacket(data, nil) 63 | if err != nil { 64 | return err 65 | } 66 | if baseResp.ErrorCode != 0 { 67 | return errors.New(baseResp.ErrorMsg) 68 | } 69 | return nil 70 | } 71 | 72 | func CheckTypedError[T any](data []byte) error { 73 | var resp T 74 | baseResp, err := ParseOidbPacket(data, &resp) 75 | if err != nil { 76 | return err 77 | } 78 | if baseResp.ErrorCode != 0 { 79 | return errors.New(baseResp.ErrorMsg) 80 | } 81 | return nil 82 | } 83 | 84 | func ParseTypedError[T any](data []byte) (*T, error) { 85 | var resp T 86 | baseResp, err := ParseOidbPacket(data, &resp) 87 | if err != nil { 88 | return nil, err 89 | } 90 | if baseResp.ErrorCode != 0 { 91 | return nil, errors.New(baseResp.ErrorMsg) 92 | } 93 | return &resp, nil 94 | } 95 | -------------------------------------------------------------------------------- /client/packets/oidb/check_url_safely.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/RomiChan/protobuf/proto" 7 | 8 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 9 | ) 10 | 11 | // ref https://github.com/Mrs4s/MiraiGo/blob/master/client/security.go 12 | 13 | type URLSecurityLevel int 14 | 15 | const ( 16 | URLSecurityLevelSafe URLSecurityLevel = iota + 1 17 | URLSecurityLevelUnknown 18 | URLSecurityLevelDanger 19 | ) 20 | 21 | func (m URLSecurityLevel) String() string { 22 | switch m { 23 | case URLSecurityLevelSafe: 24 | return "safe" 25 | case URLSecurityLevelDanger: 26 | return "danger" 27 | case URLSecurityLevelUnknown: 28 | return "unknown" 29 | default: 30 | return "unknown" 31 | } 32 | } 33 | 34 | func BuildURLCheckRequest(botuin uint32, url string) (*Packet, error) { 35 | body := &oidb.OidbSvcTrpcTcp0XBCB_0_ReqBody{ 36 | CheckUrlReq: &oidb.CheckUrlReq{ 37 | Url: []string{url}, 38 | QqPfTo: proto.String("mqq.group"), 39 | Type: proto.Uint32(2), 40 | SendUin: proto.Uint64(uint64(botuin)), 41 | ReqType: proto.String("webview"), 42 | OriginalUrl: proto.String(url), 43 | IsArk: proto.Bool(false), 44 | IsFinish: proto.Bool(false), 45 | SrcUrls: []string{url}, 46 | SrcPlatform: proto.Uint32(1), 47 | Qua: proto.String("AQQ_2013 4.6/2013 8.4.184945&NA_0/000000&ADR&null18&linux&2017&C2293D02BEE31158&7.1.2&V3"), 48 | }, 49 | } 50 | return BuildOidbPacket(0xBCB, 0, body, false, false) 51 | } 52 | 53 | func ParseURLCheckResponse(data []byte) (URLSecurityLevel, error) { 54 | var rsp oidb.OidbSvcTrpcTcp0XBCB_0_RspBody 55 | _, err := ParseOidbPacket(data, &rsp) 56 | if err != nil { 57 | return URLSecurityLevelUnknown, err 58 | } 59 | if rsp.CheckUrlRsp == nil || len(rsp.CheckUrlRsp.Results) == 0 { 60 | return URLSecurityLevelUnknown, errors.New("response is empty") 61 | } 62 | if rsp.CheckUrlRsp.Results[0].JumpUrl.IsSome() { 63 | return URLSecurityLevelDanger, nil 64 | } 65 | if rsp.CheckUrlRsp.Results[0].UmrType.Unwrap() == 2 { 66 | return URLSecurityLevelSafe, nil 67 | } 68 | return URLSecurityLevelUnknown, nil 69 | } 70 | -------------------------------------------------------------------------------- /client/packets/oidb/delete_friend.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | ) 6 | 7 | func BuildDeleteFriendReq(uid string, block bool) (*Packet, error) { 8 | body := oidb.OidbSvcTrpcTcp0X126B_0{ 9 | Field1: &oidb.OidbSvcTrpcTcp0X126B_0_Field1{ 10 | TargetUid: uid, 11 | Field2: &oidb.OidbSvcTrpcTcp0X126B_0_Field1_2{ 12 | Field1: 130, 13 | Field2: 109, 14 | Field3: &oidb.OidbSvcTrpcTcp0X126B_0_Field1_2_3{ 15 | Field1: 8, 16 | Field2: 8, 17 | Field3: 50, 18 | }, 19 | }, 20 | Block: block, 21 | Field4: true, 22 | }, 23 | } 24 | return BuildOidbPacket(0x126B, 0, &body, false, false) 25 | } 26 | 27 | func ParseDeleteFriendResp(data []byte) error { 28 | return CheckError(data) 29 | } 30 | -------------------------------------------------------------------------------- /client/packets/oidb/fetch_client_key.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 4 | 5 | func BuildFetchClientKeyReq() (*Packet, error) { 6 | body := oidb.OidbSvcTrpcTcp0X102A_1{} 7 | return BuildOidbPacket(0x102A, 1, &body, false, false) 8 | } 9 | 10 | func ParseFetchClientKeyResp(data []byte) (string, error) { 11 | resp, err := ParseTypedError[oidb.OidbSvcTrpcTcp0X102A_1Response](data) 12 | if err != nil { 13 | return "", err 14 | } 15 | return resp.ClientKey, nil 16 | } 17 | -------------------------------------------------------------------------------- /client/packets/oidb/fetch_cookie.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 4 | 5 | func BuildFetchCookieReq(domains []string) (*Packet, error) { 6 | body := oidb.OidbSvcTrpcTcp0X102A_0{Domain: domains} 7 | return BuildOidbPacket(0x102A, 0, &body, false, false) 8 | } 9 | 10 | func ParseFetchCookieResp(data []byte) ([]string, error) { 11 | resp, err := ParseTypedError[oidb.OidbSvcTrpcTcp0X102A_0Response](data) 12 | if err != nil { 13 | return nil, err 14 | } 15 | cookies := make([]string, len(resp.Urls)) 16 | for i, urls := range resp.Urls { 17 | cookies[i] = string(urls.Value) 18 | } 19 | return cookies, nil 20 | } 21 | -------------------------------------------------------------------------------- /client/packets/oidb/fetch_group_system_messages.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/entity" 5 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 6 | "github.com/LagrangeDev/LagrangeGo/utils" 7 | ) 8 | 9 | func BuildFetchGroupSystemMessagesReq(isFiltered bool, count uint32) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0X10C0{ 11 | Count: count, 12 | Field2: 0, 13 | } 14 | return BuildOidbPacket(0x10C0, utils.Ternary[uint32](isFiltered, 2, 1), body, false, false) 15 | } 16 | 17 | func ParseFetchGroupSystemMessagesReq(isFiltered bool, data []byte, groupUin ...uint32) (*entity.GroupSystemMessages, error) { 18 | resp, err := ParseTypedError[oidb.OidbSvcTrpcTcp0X10C0Response](data) 19 | if err != nil { 20 | return nil, err 21 | } 22 | requests := entity.GroupSystemMessages{} 23 | for _, r := range resp.Requests { 24 | if len(groupUin) > 0 && groupUin[0] != r.Group.GroupUin { 25 | continue 26 | } 27 | //nolint 28 | switch entity.EventType(r.EventType) { 29 | case entity.UserJoinRequest, entity.UserInvited: 30 | requests.JoinRequests = append(requests.JoinRequests, &entity.UserJoinGroupRequest{ 31 | GroupUin: r.Group.GroupUin, 32 | InvitorUID: utils.LazyTernary(r.Invitor != nil, func() string { 33 | return r.Invitor.Uid 34 | }, func() string { 35 | return "" 36 | }), 37 | TargetUID: r.Target.Uid, 38 | OperatorUID: utils.LazyTernary(r.Invitor != nil, func() string { 39 | return r.Invitor.Uid 40 | }, func() string { 41 | return "" 42 | }), 43 | Sequence: r.Sequence, 44 | Checked: entity.EventState(r.State) != entity.Unprocessed, 45 | State: entity.EventState(r.State), 46 | EventType: entity.EventType(r.EventType), 47 | Comment: r.Comment, 48 | IsFiltered: isFiltered, 49 | }) 50 | case entity.GroupInvited: 51 | requests.InvitedRequests = append(requests.InvitedRequests, &entity.GroupInvitedRequest{ 52 | GroupUin: r.Group.GroupUin, 53 | InvitorUID: utils.LazyTernary(r.Invitor != nil, func() string { 54 | return r.Invitor.Uid 55 | }, func() string { 56 | return "" 57 | }), 58 | Sequence: r.Sequence, 59 | Checked: entity.EventState(r.State) != entity.Unprocessed, 60 | State: entity.EventState(r.State), 61 | EventType: entity.EventType(r.EventType), 62 | IsFiltered: isFiltered, 63 | }) 64 | default: 65 | } 66 | } 67 | return &requests, nil 68 | } 69 | -------------------------------------------------------------------------------- /client/packets/oidb/fetch_groups.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/entity" 5 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 6 | ) 7 | 8 | func BuildFetchGroupsReq() (*Packet, error) { 9 | body := &oidb.OidbSvcTrpcTcp0XFE5_2{ 10 | Config: &oidb.OidbSvcTrpcTcp0XFE5_2Config{ 11 | Config1: &oidb.OidbSvcTrpcTcp0XFE5_2Config1{ 12 | GroupOwner: true, Field2: true, MemberMax: true, MemberCount: true, GroupName: true, Field8: true, 13 | Field9: true, Field10: true, Field11: true, Field12: true, Field13: true, Field14: true, Field15: true, 14 | Field16: true, Field17: true, Field18: true, Question: true, Field20: true, Field22: true, Field23: true, 15 | Field24: true, Field25: true, Field26: true, Field27: true, Field28: true, Field29: true, Field30: true, 16 | Field31: true, Field32: true, Field5001: true, Field5002: true, Field5003: true, 17 | }, 18 | Config2: &oidb.OidbSvcTrpcTcp0XFE5_2Config2{ 19 | Field1: true, Field2: true, Field3: true, Field4: true, Field5: true, Field6: true, Field7: true, 20 | Field8: true, 21 | }, 22 | Config3: &oidb.OidbSvcTrpcTcp0XFE5_2Config3{ 23 | Field5: true, Field6: true, 24 | }, 25 | }, 26 | } 27 | return BuildOidbPacket(0xFE5, 2, body, false, true) 28 | } 29 | 30 | func ParseFetchGroupsResp(data []byte) ([]*entity.Group, error) { 31 | var resp oidb.OidbSvcTrpcTcp0XFE5_2Response 32 | if _, err := ParseOidbPacket(data, &resp); err != nil { 33 | return nil, err 34 | } 35 | groups := make([]*entity.Group, len(resp.Groups)) 36 | for i, group := range resp.Groups { 37 | groups[i] = &entity.Group{ 38 | GroupUin: group.GroupUin, 39 | GroupName: group.Info.GroupName, 40 | MemberCount: group.Info.MemberCount, 41 | MaxMember: group.Info.MemberMax, 42 | GroupCreateTime: group.Info.CreateTimeStamp, 43 | GroupMemo: group.ExtInfo.GroupMemo, 44 | } 45 | } 46 | return groups, nil 47 | } 48 | -------------------------------------------------------------------------------- /client/packets/oidb/fetch_member.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/entity" 5 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 6 | "github.com/LagrangeDev/LagrangeGo/utils" 7 | ) 8 | 9 | func BuildFetchMemberReq(groupUin uint32, memberUID string) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0XFE7_4{ 11 | GroupUin: groupUin, 12 | Field2: 3, 13 | Field3: 0, 14 | Body: &oidb.OidbSvcTrpcScp0XFE7_3Body{ 15 | MemberName: true, 16 | MemberCard: true, 17 | Level: true, 18 | SpecialTitle: true, 19 | JoinTimestamp: true, 20 | LastMsgTimestamp: true, 21 | ShutUpTimestamp: true, 22 | Permission: true, 23 | }, 24 | Params: &oidb.OidbSvcTrpcScp0XFE7_4Params{Uid: memberUID}, 25 | } 26 | return BuildOidbPacket(0xFE7, 4, body, false, false) 27 | } 28 | 29 | func ParseFetchMemberResp(data []byte) (*entity.GroupMember, error) { 30 | var resp oidb.OidbSvcTrpcTcp0XFE7_4Response 31 | _, err := ParseOidbPacket(data, &resp) 32 | if err != nil { 33 | return nil, err 34 | } 35 | interner := utils.NewStringInterner() 36 | member := resp.Member 37 | m := &entity.GroupMember{ 38 | User: entity.User{ 39 | Uin: member.Uin.Uin, 40 | UID: interner.Intern(member.Uin.Uid), 41 | Nickname: interner.Intern(member.MemberName), 42 | Avatar: interner.Intern(entity.UserAvatar(member.Uin.Uin)), 43 | }, 44 | Permission: entity.GroupMemberPermission(member.Permission), 45 | MemberCard: interner.Intern(member.MemberCard.MemberCard.Unwrap()), 46 | SpecialTitle: interner.Intern(member.SpecialTitle.Unwrap()), 47 | JoinTime: member.JoinTimestamp, 48 | LastMsgTime: member.LastMsgTimestamp, 49 | ShutUpTime: member.ShutUpTimestamp.Unwrap(), 50 | } 51 | if member.Level != nil { 52 | m.GroupLevel = member.Level.Level 53 | } 54 | return m, nil 55 | } 56 | -------------------------------------------------------------------------------- /client/packets/oidb/fetch_members.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/entity" 5 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 6 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 7 | "github.com/LagrangeDev/LagrangeGo/utils" 8 | ) 9 | 10 | func BuildFetchMembersReq(groupUin uint32, token string) (*Packet, error) { 11 | body := &oidb.OidbSvcTrpcTcp0XFE7_3{ 12 | GroupUin: groupUin, 13 | Field2: 5, 14 | Field3: 2, 15 | Body: &oidb.OidbSvcTrpcScp0XFE7_3Body{ 16 | MemberName: true, 17 | MemberCard: true, 18 | Level: true, 19 | SpecialTitle: true, 20 | JoinTimestamp: true, 21 | LastMsgTimestamp: true, 22 | ShutUpTimestamp: true, 23 | Permission: true, 24 | }, 25 | Token: proto.Some(token), 26 | } 27 | return BuildOidbPacket(0xFE7, 3, body, false, false) 28 | } 29 | 30 | func ParseFetchMembersResp(data []byte) ([]*entity.GroupMember, string, error) { 31 | var resp oidb.OidbSvcTrpcTcp0XFE7_2Response 32 | _, err := ParseOidbPacket(data, &resp) 33 | if err != nil { 34 | return nil, "", err 35 | } 36 | interner := utils.NewStringInterner() 37 | members := make([]*entity.GroupMember, len(resp.Members)) 38 | for i, member := range resp.Members { 39 | // 由于protobuf的优化策略,默认值不会被编码进实际的二进制流中 40 | m := &entity.GroupMember{ 41 | User: entity.User{ 42 | Uin: member.Uin.Uin, 43 | UID: interner.Intern(member.Uin.Uid), 44 | Nickname: interner.Intern(member.MemberName), 45 | Avatar: interner.Intern(entity.UserAvatar(member.Uin.Uin)), 46 | }, 47 | Permission: entity.GroupMemberPermission(member.Permission), 48 | MemberCard: interner.Intern(member.MemberCard.MemberCard.Unwrap()), 49 | SpecialTitle: interner.Intern(member.SpecialTitle.Unwrap()), 50 | JoinTime: member.JoinTimestamp, 51 | LastMsgTime: member.LastMsgTimestamp, 52 | ShutUpTime: member.ShutUpTimestamp.Unwrap(), 53 | } 54 | if member.Level != nil { 55 | m.GroupLevel = member.Level.Level 56 | } 57 | members[i] = m 58 | } 59 | return members, resp.Token.Unwrap(), nil 60 | } 61 | -------------------------------------------------------------------------------- /client/packets/oidb/fetch_rkey.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/entity" 5 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 6 | ) 7 | 8 | func BuildFetchRKeyReq() (*Packet, error) { 9 | body := &oidb.NTV2RichMediaReq{ 10 | ReqHead: &oidb.MultiMediaReqHead{ 11 | Common: &oidb.CommonHead{ 12 | RequestId: 1, 13 | Command: 202, 14 | }, 15 | Scene: &oidb.SceneInfo{ 16 | RequestType: 2, 17 | BusinessType: 1, 18 | SceneType: 0, 19 | }, 20 | Client: &oidb.ClientMeta{ 21 | AgentType: 2, 22 | }, 23 | }, 24 | DownloadRKey: &oidb.DownloadRKeyReq{ 25 | Types: []int32{10, 20, 2}, 26 | }, 27 | } 28 | return BuildOidbPacket(0x9067, 202, body, false, false) 29 | } 30 | 31 | func ParseFetchRKeyResp(data []byte) (entity.RKeyMap, error) { 32 | resp := &oidb.NTV2RichMediaResp{} 33 | _, err := ParseOidbPacket(data, resp) 34 | if err != nil { 35 | return nil, err 36 | } 37 | var rKeyInfo = entity.RKeyMap{} 38 | for _, rkey := range resp.DownloadRKey.RKeys { 39 | typ := entity.RKeyType(rkey.Type.Unwrap()) 40 | rKeyInfo[typ] = &entity.RKeyInfo{ 41 | RKey: rkey.Rkey, 42 | RKeyType: typ, 43 | CreateTime: uint64(rkey.RkeyCreateTime.Unwrap()), 44 | ExpireTime: uint64(rkey.RkeyCreateTime.Unwrap()) + rkey.RkeyTtlSec, 45 | } 46 | } 47 | return rKeyInfo, nil 48 | } 49 | -------------------------------------------------------------------------------- /client/packets/oidb/friend_like.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 6 | ) 7 | 8 | func BuildFriendLikeReq(uid string, count uint32) (*Packet, error) { 9 | body := &oidb.OidbSvcTrpcTcp0X7E5_104{ 10 | TargetUid: proto.Some(uid), 11 | Source: 71, 12 | Count: count, 13 | } 14 | return BuildOidbPacket(0x7E5, 104, body, false, false) 15 | } 16 | 17 | func ParseFriendLikeResp(data []byte) error { 18 | return CheckError(data) 19 | } 20 | -------------------------------------------------------------------------------- /client/packets/oidb/get_group_atall_remain.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 4 | 5 | // ref https://github.com/Mrs4s/MiraiGo/blob/54bdd873e3fed9fe1c944918924674dacec5ac76/client/group_msg.go#L213 6 | 7 | func BuildGetAtAllRemainRequest(uin, gin uint32) (*Packet, error) { 8 | body := &oidb.OidbSvcTrpcTcp0X8A7_0_ReqBody{ 9 | SubCmd: 1, 10 | LimitIntervalTypeForUin: 2, 11 | LimitIntervalTypeForGroup: 1, 12 | Uin: uint64(uin), 13 | GroupUin: uint64(gin), 14 | } 15 | return BuildOidbPacket(0x8A7, 0, body, false, true) 16 | } 17 | 18 | type AtAllRemainInfo struct { 19 | CanAtAll bool 20 | CountForGroup uint32 // 当前群默认可用次数 21 | CountForUin uint32 // 当前QQ剩余次数 22 | } 23 | 24 | func ParseGetAtAllRemainResponse(data []byte) (*AtAllRemainInfo, error) { 25 | var rsp oidb.OidbSvcTrpcTcp0X8A7_0_RspBody 26 | _, err := ParseOidbPacket(data, &rsp) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return &AtAllRemainInfo{ 31 | CanAtAll: rsp.CanAtAll, 32 | CountForGroup: rsp.CountForGroup, 33 | CountForUin: rsp.CountForUin, 34 | }, nil 35 | } 36 | -------------------------------------------------------------------------------- /client/packets/oidb/group_file_count.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 4 | 5 | func BuildGroupFileCountReq(groupUin uint32) (*Packet, error) { 6 | body := &oidb.OidbSvcTrpcTcp0X6D8{ 7 | Count: &oidb.OidbSvcTrpcTcp0X6D8Count{ 8 | GroupUin: groupUin, 9 | AppId: 7, 10 | BusId: 6, 11 | }, 12 | } 13 | return BuildOidbPacket(0x6D8, 2, body, false, true) 14 | } 15 | 16 | func ParseGroupFileCountResp(data []byte) (uint32, uint32, error) { 17 | var resp oidb.OidbSvcTrpcTcp0X6D8_1Response 18 | if _, err := ParseOidbPacket(data, &resp); err != nil { 19 | return 0, 0, err 20 | } 21 | return resp.Count.FileCount, resp.Count.LimitCount, nil 22 | } 23 | -------------------------------------------------------------------------------- /client/packets/oidb/group_file_delete.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildGroupFileDeleteReq(groupUin uint32, fileID string) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0X6D6{ 11 | Delete: &oidb.OidbSvcTrpcTcp0X6D6Delete{ 12 | GroupUin: groupUin, 13 | BusId: 102, 14 | FileId: fileID, 15 | }, 16 | } 17 | return BuildOidbPacket(0x6D6, 3, body, false, true) 18 | } 19 | 20 | func ParseGroupFileDeleteResp(data []byte) error { 21 | var resp oidb.OidbSvcTrpcTcp0X6D6Response 22 | if _, err := ParseOidbPacket(data, &resp); err != nil { 23 | return err 24 | } 25 | if resp.Delete.RetCode != 0 { 26 | return errors.New(resp.Delete.ClientWording) 27 | } 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /client/packets/oidb/group_file_list.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildGroupFileListReq(groupUin uint32, targetDirectory string, startIndex uint32, fileCount uint32) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0X6D8{ 11 | List: &oidb.OidbSvcTrpcTcp0X6D8List{ 12 | GroupUin: groupUin, 13 | AppId: 7, 14 | TargetDirectory: targetDirectory, 15 | FileCount: fileCount, 16 | SortBy: 1, 17 | StartIndex: startIndex, 18 | Field17: 2, 19 | Field18: 0, 20 | }, 21 | } 22 | return BuildOidbPacket(0x6D8, 1, body, false, true) 23 | } 24 | 25 | func ParseGroupFileListResp(data []byte) (*oidb.OidbSvcTrpcTcp0X6D8_1Response, error) { 26 | var resp oidb.OidbSvcTrpcTcp0X6D8_1Response 27 | if _, err := ParseOidbPacket(data, &resp); err != nil { 28 | return &resp, err 29 | } 30 | if resp.List.RetCode != 0 { 31 | return &resp, errors.New(resp.List.ClientWording) 32 | } 33 | return &resp, nil 34 | } 35 | -------------------------------------------------------------------------------- /client/packets/oidb/group_file_move.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildGroupFileMoveReq(groupUin uint32, fileID string, parentFolder string, targetFolderID string) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0X6D6{ 11 | Move: &oidb.OidbSvcTrpcTcp0X6D6Move{ 12 | GroupUin: groupUin, 13 | BusId: 102, 14 | FileId: fileID, 15 | ParentDirectory: parentFolder, 16 | TargetDirectory: targetFolderID, 17 | }, 18 | } 19 | return BuildOidbPacket(0x6D6, 5, body, false, true) 20 | } 21 | 22 | func ParseGroupFileMoveResp(data []byte) error { 23 | var resp oidb.OidbSvcTrpcTcp0X6D6Response 24 | if _, err := ParseOidbPacket(data, &resp); err != nil { 25 | return err 26 | } 27 | if resp.Move.RetCode != 0 { 28 | return errors.New(resp.Move.ClientWording) 29 | } 30 | return nil 31 | } 32 | -------------------------------------------------------------------------------- /client/packets/oidb/group_file_rename.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildGroupFileRenameReq(groupUin uint32, fileID string, parentFolder string, newFileName string) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0X6D6{ 11 | Rename: &oidb.OidbSvcTrpcTcp0X6D6Rename{ 12 | GroupUin: groupUin, 13 | BusId: 102, 14 | FileId: fileID, 15 | ParentFolder: parentFolder, 16 | NewFileName: newFileName, 17 | }, 18 | } 19 | return BuildOidbPacket(0x6D6, 4, body, false, true) 20 | } 21 | 22 | func ParseGroupFileRenameResp(data []byte) error { 23 | var resp oidb.OidbSvcTrpcTcp0X6D6Response 24 | if _, err := ParseOidbPacket(data, &resp); err != nil { 25 | return err 26 | } 27 | if resp.Rename.RetCode != 0 { 28 | return errors.New(resp.Rename.ClientWording) 29 | } 30 | return nil 31 | } 32 | -------------------------------------------------------------------------------- /client/packets/oidb/group_file_space.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 4 | 5 | func BuildGroupFileSpaceReq(groupUin uint32) (*Packet, error) { 6 | body := &oidb.OidbSvcTrpcTcp0X6D8{ 7 | Space: &oidb.OidbSvcTrpcTcp0X6D8Space{ 8 | GroupUin: groupUin, 9 | AppId: 7, 10 | }, 11 | } 12 | return BuildOidbPacket(0x6D8, 3, body, false, true) 13 | } 14 | 15 | func ParseGroupFileSpaceResp(data []byte) (uint64, uint64, error) { 16 | var resp oidb.OidbSvcTrpcTcp0X6D8_1Response 17 | if _, err := ParseOidbPacket(data, &resp); err != nil { 18 | return 0, 0, err 19 | } 20 | return resp.Space.TotalSpace, resp.Space.UsedSpace, nil 21 | } 22 | -------------------------------------------------------------------------------- /client/packets/oidb/group_file_upload.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | "github.com/LagrangeDev/LagrangeGo/message" 8 | ) 9 | 10 | func BuildGroupFileUploadReq(groupUin uint32, file *message.FileElement, targetDirectory string) (*Packet, error) { 11 | body := &oidb.OidbSvcTrpcTcp0X6D6{ 12 | File: &oidb.OidbSvcTrpcTcp0X6D6Upload{ 13 | GroupUin: groupUin, 14 | AppId: 4, 15 | BusId: 102, 16 | Entrance: 6, 17 | TargetDirectory: targetDirectory, 18 | FileName: file.FileName, 19 | LocalDirectory: "/" + file.FileName, 20 | FileSize: file.FileSize, 21 | FileSha1: file.FileSha1, 22 | FileSha3: []byte{}, 23 | FileMd5: file.FileMd5, 24 | Field15: true, 25 | }, 26 | } 27 | return BuildOidbPacket(0x6D6, 0, body, false, true) 28 | } 29 | 30 | func ParseGroupFileUploadResp(data []byte) (*oidb.OidbSvcTrpcTcp0X6D6Response, error) { 31 | var resp oidb.OidbSvcTrpcTcp0X6D6Response 32 | if _, err := ParseOidbPacket(data, &resp); err != nil { 33 | return nil, err 34 | } 35 | if resp.Upload.RetCode != 0 { 36 | return nil, errors.New(resp.Upload.ClientWording) 37 | } 38 | return &resp, nil 39 | } 40 | -------------------------------------------------------------------------------- /client/packets/oidb/group_folder_create.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildGroupFolderCreateReq(groupUin uint32, targetDirectory string, folderName string) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0X6D7{ 11 | Create: &oidb.OidbSvcTrpcTcp0X6D7Create{ 12 | GroupUin: groupUin, 13 | TargetDirectory: targetDirectory, 14 | FolderName: folderName, 15 | }, 16 | } 17 | return BuildOidbPacket(0x6D7, 0, body, false, true) 18 | } 19 | 20 | func ParseGroupFolderCreateResp(data []byte) error { 21 | var resp oidb.OidbSvcTrpcTcp0X6D7Response 22 | if _, err := ParseOidbPacket(data, &resp); err != nil { 23 | return err 24 | } 25 | if resp.Create.RetCode != 0 { 26 | return errors.New(resp.Create.ClientWording) 27 | } 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /client/packets/oidb/group_folder_delete.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildGroupFolderDeleteReq(groupUin uint32, folderID string) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0X6D7{ 11 | Delete: &oidb.OidbSvcTrpcTcp0X6D7Delete{ 12 | GroupUin: groupUin, 13 | FolderId: folderID, 14 | }, 15 | } 16 | return BuildOidbPacket(0x6D7, 1, body, false, true) 17 | } 18 | 19 | func ParseGroupFolderDeleteResp(data []byte) error { 20 | var resp oidb.OidbSvcTrpcTcp0X6D7Response 21 | if _, err := ParseOidbPacket(data, &resp); err != nil { 22 | return err 23 | } 24 | if resp.Delete.RetCode != 0 { 25 | return errors.New(resp.Delete.ClientWording) 26 | } 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /client/packets/oidb/group_folder_rename.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildGroupFolderRenameReq(groupUin uint32, folderID string, newFolderName string) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0X6D7{ 11 | Rename: &oidb.OidbSvcTrpcTcp0X6D7Rename{ 12 | GroupUin: groupUin, 13 | FolderId: folderID, 14 | NewFolderName: newFolderName, 15 | }, 16 | } 17 | return BuildOidbPacket(0x6D7, 2, body, false, true) 18 | } 19 | 20 | func ParseGroupFolderRenameResp(data []byte) error { 21 | var resp oidb.OidbSvcTrpcTcp0X6D7Response 22 | if _, err := ParseOidbPacket(data, &resp); err != nil { 23 | return err 24 | } 25 | if resp.Rename.RetCode != 0 { 26 | return errors.New(resp.Rename.ClientWording) 27 | } 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /client/packets/oidb/group_fs_download.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "encoding/hex" 5 | "errors" 6 | "fmt" 7 | 8 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 9 | ) 10 | 11 | func BuildGroupFSDownloadReq(groupUin uint32, fileID string) (*Packet, error) { 12 | body := &oidb.OidbSvcTrpcTcp0X6D6{ 13 | Download: &oidb.OidbSvcTrpcTcp0X6D6Download{ 14 | GroupUin: groupUin, 15 | AppId: 7, 16 | BusId: 102, 17 | FileId: fileID, 18 | }, 19 | } 20 | return BuildOidbPacket(0x6D6, 2, body, false, true) 21 | } 22 | 23 | func ParseGroupFSDownloadResp(data []byte) (string, error) { 24 | var resp oidb.OidbSvcTrpcTcp0X6D6Response 25 | if _, err := ParseOidbPacket(data, &resp); err != nil { 26 | return "", err 27 | } 28 | if resp.Download.RetCode != 0 { 29 | return "", errors.New(resp.Download.ClientWording) 30 | } 31 | hexURL := hex.EncodeToString(resp.Download.DownloadUrl) 32 | url := fmt.Sprintf("https://%s:443/ftn_handler/%s/?fname=", resp.Download.DownloadIp, hexURL) 33 | return url, nil 34 | } 35 | -------------------------------------------------------------------------------- /client/packets/oidb/group_image_download.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildGroupImageDownloadReq(groupUin uint32, node *oidb.IndexNode) (*Packet, error) { 10 | body := &oidb.NTV2RichMediaReq{ 11 | ReqHead: &oidb.MultiMediaReqHead{ 12 | Common: &oidb.CommonHead{ 13 | RequestId: 1, 14 | Command: 200, 15 | }, 16 | Scene: &oidb.SceneInfo{ 17 | RequestType: 2, 18 | BusinessType: 1, 19 | SceneType: 2, 20 | Group: &oidb.NTGroupInfo{GroupUin: groupUin}, 21 | }, 22 | Client: &oidb.ClientMeta{AgentType: 2}, 23 | }, 24 | Download: &oidb.DownloadReq{ 25 | Node: node, 26 | Download: &oidb.DownloadExt{ 27 | Video: &oidb.VideoDownloadExt{ 28 | BusiType: 0, 29 | SceneType: 0, 30 | }, 31 | }, 32 | }, 33 | } 34 | return BuildOidbPacket(0x11C4, 200, body, false, true) 35 | } 36 | 37 | func ParseGroupImageDownloadResp(data []byte) (string, error) { 38 | resp, err := ParseTypedError[oidb.NTV2RichMediaResp](data) 39 | if err != nil { 40 | return "", err 41 | } 42 | body := resp.Download 43 | return fmt.Sprintf("https://%s%s%s", body.Info.Domain, body.Info.UrlPath, body.RKeyParam), nil 44 | } 45 | -------------------------------------------------------------------------------- /client/packets/oidb/group_record_download.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildGroupRecordDownloadReq(grpUin uint32, node *oidb.IndexNode) (*Packet, error) { 10 | body := oidb.NTV2RichMediaReq{ 11 | ReqHead: &oidb.MultiMediaReqHead{ 12 | Common: &oidb.CommonHead{ 13 | RequestId: 4, 14 | Command: 200, 15 | }, 16 | Scene: &oidb.SceneInfo{ 17 | RequestType: 1, 18 | BusinessType: 3, 19 | SceneType: 2, 20 | Group: &oidb.NTGroupInfo{ 21 | GroupUin: grpUin, 22 | }, 23 | }, 24 | Client: &oidb.ClientMeta{ 25 | AgentType: 2, 26 | }, 27 | }, 28 | Download: &oidb.DownloadReq{ 29 | Node: node, 30 | Download: &oidb.DownloadExt{ 31 | Video: &oidb.VideoDownloadExt{ 32 | BusiType: 0, 33 | SceneType: 0, 34 | }, 35 | }, 36 | }, 37 | } 38 | 39 | return BuildOidbPacket(0x126E, 200, &body, false, true) 40 | } 41 | 42 | func ParseGroupRecordDownloadResp(data []byte) (string, error) { 43 | var resp oidb.NTV2RichMediaResp 44 | if _, err := ParseOidbPacket(data, &resp); err != nil { 45 | return "", err 46 | } 47 | body := resp.Download 48 | return fmt.Sprintf("https://%s%s%s", body.Info.Domain, body.Info.UrlPath, body.RKeyParam), nil 49 | } 50 | -------------------------------------------------------------------------------- /client/packets/oidb/group_record_upload.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "encoding/hex" 5 | "errors" 6 | 7 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 8 | "github.com/LagrangeDev/LagrangeGo/message" 9 | "github.com/LagrangeDev/LagrangeGo/utils/crypto" 10 | ) 11 | 12 | func BuildGroupRecordUploadReq(groupUin uint32, record *message.VoiceElement) (*Packet, error) { 13 | if record.Stream == nil { 14 | return nil, errors.New("audio data is nil") 15 | } 16 | md5 := hex.EncodeToString(record.Md5) 17 | sha1 := hex.EncodeToString(record.Sha1) 18 | body := &oidb.NTV2RichMediaReq{ 19 | ReqHead: &oidb.MultiMediaReqHead{ 20 | Common: &oidb.CommonHead{ 21 | RequestId: 1, 22 | Command: 100, 23 | }, 24 | Scene: &oidb.SceneInfo{ 25 | RequestType: 2, 26 | BusinessType: 3, 27 | SceneType: 2, 28 | Group: &oidb.NTGroupInfo{ 29 | GroupUin: groupUin, 30 | }, 31 | }, 32 | Client: &oidb.ClientMeta{ 33 | AgentType: 2, 34 | }, 35 | }, 36 | Upload: &oidb.UploadReq{ 37 | UploadInfo: []*oidb.UploadInfo{ 38 | { 39 | FileInfo: &oidb.FileInfo{ 40 | FileSize: record.Size, 41 | FileHash: md5, 42 | FileSha1: sha1, 43 | FileName: md5 + ".amr", 44 | Type: &oidb.FileType{ 45 | Type: 3, 46 | PicFormat: 0, 47 | VideoFormat: 0, 48 | VoiceFormat: 1, 49 | }, 50 | Width: 0, 51 | Height: 0, 52 | Time: record.Duration, 53 | Original: 0, 54 | }, 55 | SubFileType: 0, 56 | }, 57 | }, 58 | TryFastUploadCompleted: true, 59 | SrvSendMsg: false, 60 | ClientRandomId: uint64(crypto.RandU32()), 61 | CompatQMsgSceneType: 2, 62 | ExtBizInfo: &oidb.ExtBizInfo{ 63 | Pic: &oidb.PicExtBizInfo{ 64 | TextSummary: record.Summary, 65 | }, 66 | Video: &oidb.VideoExtBizInfo{ 67 | BytesPbReserve: make([]byte, 0), 68 | }, 69 | Ptt: &oidb.PttExtBizInfo{ 70 | BytesReserve: make([]byte, 0), 71 | BytesPbReserve: []byte{0x08, 0x00, 0x38, 0x00}, 72 | BytesGeneralFlags: []byte{0x9a, 0x01, 0x07, 0xaa, 0x03, 0x04, 0x08, 0x08, 0x12, 0x00}, 73 | }, 74 | }, 75 | ClientSeq: 0, 76 | NoNeedCompatMsg: false, 77 | }, 78 | } 79 | 80 | return BuildOidbPacket(0x126E, 100, body, false, true) 81 | } 82 | 83 | func ParseGroupRecordUploadResp(data []byte) (*oidb.NTV2RichMediaResp, error) { 84 | return ParseTypedError[oidb.NTV2RichMediaResp](data) 85 | } 86 | -------------------------------------------------------------------------------- /client/packets/oidb/group_send_file.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/RomiChan/protobuf/proto" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | "github.com/LagrangeDev/LagrangeGo/utils/crypto" 8 | ) 9 | 10 | func BuildGroupSendFileReq(groupUin uint32, fileKey string) (*Packet, error) { 11 | body := &oidb.OidbSvcTrpcTcp0X6D9_4{ 12 | Body: &oidb.OidbSvcTrpcTcp0X6D9_4Body{ 13 | GroupUin: groupUin, 14 | Type: 4, 15 | Info: &oidb.OidbSvcTrpcTcp0X6D9_4Info{ 16 | BusiType: 102, 17 | FileId: fileKey, 18 | Field3: crypto.RandU32(), 19 | Field4: proto.String("{}"), 20 | Field5: true, 21 | }, 22 | }, 23 | } 24 | return BuildOidbPacket(0x6D9, 4, body, false, true) 25 | } 26 | 27 | func ParseGroupSendFileResp(data []byte) (*oidb.OidbSvcTrpcTcpBase, error) { 28 | return ParseTypedError[oidb.OidbSvcTrpcTcpBase](data) 29 | } 30 | -------------------------------------------------------------------------------- /client/packets/oidb/group_sign.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | 7 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 8 | ) 9 | 10 | // 群打卡 11 | 12 | type BotGroupClockInResult struct { 13 | Title string // 今日已成功打卡 14 | KeepDayText string // 已打卡N天 15 | GroupRankText string // 群内排名第N位 16 | ClockInUtcTime int64 // 打卡时间 17 | DetailURL string // Detail info url https://qun.qq.com/v2/signin/detail?... 18 | } 19 | 20 | func BuildGroupSignPacket(botUin, groupUin uint32, appVersion string) (*Packet, error) { 21 | body := &oidb.OidbSvcTrpcTcp0XEB7_1_ReqBody{ 22 | SignInWriteReq: &oidb.StSignInWriteReq{ 23 | Uin: strconv.Itoa(int(botUin)), 24 | GroupUin: strconv.Itoa(int(groupUin)), 25 | AppVersion: appVersion, 26 | }, 27 | } 28 | return BuildOidbPacket(0xEB7, 1, body, false, false) 29 | } 30 | 31 | func ParseGroupSignResp(data []byte) (*BotGroupClockInResult, error) { 32 | var rsp oidb.OidbSvcTrpcTcp0XEB7_1_RspBody 33 | _, err := ParseOidbPacket(data, &rsp) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | if rsp.SignInWriteRsp == nil || rsp.SignInWriteRsp.DoneInfo == nil { 39 | return nil, errors.New("SignInWriteRsp or SignInWriteRsp.DoneInfo nil") 40 | } 41 | 42 | ret := &BotGroupClockInResult{ 43 | Title: rsp.SignInWriteRsp.DoneInfo.Title, 44 | KeepDayText: rsp.SignInWriteRsp.DoneInfo.KeepDayText, 45 | DetailURL: rsp.SignInWriteRsp.DoneInfo.DetailUrl, 46 | } 47 | if size := len(rsp.SignInWriteRsp.DoneInfo.ClockInInfo); size > 0 { 48 | ret.GroupRankText = rsp.SignInWriteRsp.DoneInfo.ClockInInfo[0] 49 | if size > 1 { 50 | ret.ClockInUtcTime, _ = strconv.ParseInt(rsp.SignInWriteRsp.DoneInfo.ClockInInfo[1], 10, 64) 51 | } 52 | } 53 | return ret, nil 54 | } 55 | -------------------------------------------------------------------------------- /client/packets/oidb/group_video_download.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | ) 6 | 7 | func BuildGroupVideoDownloadReq(groupUin uint32, node *oidb.IndexNode) (*Packet, error) { 8 | body := &oidb.NTV2RichMediaReq{ 9 | ReqHead: &oidb.MultiMediaReqHead{ 10 | Common: &oidb.CommonHead{ 11 | RequestId: 1, 12 | Command: 200, 13 | }, 14 | Scene: &oidb.SceneInfo{ 15 | RequestType: 2, 16 | BusinessType: 2, 17 | SceneType: 2, 18 | Group: &oidb.NTGroupInfo{ 19 | GroupUin: groupUin, 20 | }, 21 | }, 22 | Client: &oidb.ClientMeta{ 23 | AgentType: 2, 24 | }, 25 | }, 26 | Download: &oidb.DownloadReq{ 27 | Node: node, 28 | Download: &oidb.DownloadExt{ 29 | Video: &oidb.VideoDownloadExt{}, 30 | }, 31 | }, 32 | } 33 | return BuildOidbPacket(0x11E9, 200, body, false, true) 34 | } 35 | -------------------------------------------------------------------------------- /client/packets/oidb/image_ocr.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/pkg/errors" 8 | 9 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 10 | ) 11 | 12 | func BuildImageOcrRequestPacket(url string) (*Packet, error) { 13 | body := &oidb.OidbSvcTrpcTcp0XE07_0{ 14 | Version: 1, 15 | Client: 0, 16 | Entrance: 1, 17 | OcrReqBody: &oidb.OcrReqBody{ 18 | ImageUrl: url, 19 | OriginMd5: "", 20 | AfterCompressMd5: "", 21 | AfterCompressFileSize: "", 22 | AfterCompressWeight: "", 23 | AfterCompressHeight: "", 24 | IsCut: false, 25 | }, 26 | } 27 | return BuildOidbPacket(0xE07, 0, body, false, true) 28 | } 29 | 30 | type ( 31 | OcrResponse struct { 32 | Texts []*TextDetection `json:"texts"` 33 | Language string `json:"language"` 34 | } 35 | TextDetection struct { 36 | Text string `json:"text"` 37 | Confidence int32 `json:"confidence"` 38 | Coordinates []*Coordinate `json:"coordinates"` 39 | } 40 | Coordinate struct { 41 | X int32 `json:"x"` 42 | Y int32 `json:"y"` 43 | } 44 | ) 45 | 46 | func ParseImageOcrResp(data []byte) (*OcrResponse, error) { 47 | var rsp oidb.OidbSvcTrpcTcp0XE07_0_Response 48 | _, err := ParseOidbPacket(data, &rsp) 49 | if err != nil { 50 | return nil, err 51 | } 52 | if rsp.Wording != "" { 53 | if strings.Contains(rsp.Wording, "服务忙") { 54 | return nil, errors.New("未识别到文本") 55 | } 56 | return nil, errors.New(rsp.Wording) 57 | } 58 | if rsp.RetCode != 0 { 59 | return nil, fmt.Errorf("server error, code: %v msg: %v", rsp.RetCode, rsp.ErrMsg) 60 | } 61 | texts := make([]*TextDetection, 0, len(rsp.OcrRspBody.TextDetections)) 62 | for _, text := range rsp.OcrRspBody.TextDetections { 63 | points := make([]*Coordinate, 0, len(text.Polygon.Coordinates)) 64 | for _, c := range text.Polygon.Coordinates { 65 | points = append(points, &Coordinate{ 66 | X: c.X, 67 | Y: c.Y, 68 | }) 69 | } 70 | texts = append(texts, &TextDetection{ 71 | Text: text.DetectedText, 72 | Confidence: text.Confidence, 73 | Coordinates: points, 74 | }) 75 | } 76 | return &OcrResponse{ 77 | Texts: texts, 78 | Language: rsp.OcrRspBody.Language, 79 | }, nil 80 | } 81 | -------------------------------------------------------------------------------- /client/packets/oidb/kick_group_member.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | ) 6 | 7 | func BuildKickGroupMemberReq(groupUin uint32, uid string, rejectAddRequest bool) (*Packet, error) { 8 | body := &oidb.OidbSvcTrpcTcp0X8A0_1{ 9 | GroupUin: groupUin, 10 | TargetUid: uid, 11 | RejectAddRequest: rejectAddRequest, 12 | Field5: "", 13 | } 14 | return BuildOidbPacket(0x8A0, 1, body, false, false) 15 | } 16 | 17 | func ParseKickGroupMemberResp(data []byte) error { 18 | return CheckTypedError[oidb.OidbSvcTrpcTcp0X8A0_1Response](data) 19 | } 20 | -------------------------------------------------------------------------------- /client/packets/oidb/poke.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/RomiChan/protobuf/proto" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildGroupPokeReq(groupUin, uin uint32) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0XED3_1{ 11 | Uin: uin, 12 | GroupUin: groupUin, 13 | Ext: proto.Some[uint32](0), 14 | } 15 | return BuildOidbPacket(0xED3, 1, body, false, false) 16 | } 17 | 18 | func BuildFriendPokeReq(uin uint32) (*Packet, error) { 19 | body := &oidb.OidbSvcTrpcTcp0XED3_1{ 20 | Uin: uin, 21 | FriendUin: uin, 22 | Ext: proto.Some[uint32](0), 23 | } 24 | return BuildOidbPacket(0xED3, 1, body, false, false) 25 | } 26 | 27 | func ParsePokeResp(data []byte) error { 28 | return CheckError(data) 29 | } 30 | -------------------------------------------------------------------------------- /client/packets/oidb/private_file_download.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildPrivateFileDownloadReq(selfUID string, fileUUID string, fileHash string) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0XE37_1200{ 11 | SubCommand: 1200, 12 | Field2: 1, 13 | Body: &oidb.OidbSvcTrpcTcp0XE37_1200Body{ 14 | ReceiverUid: selfUID, 15 | FileUuid: fileUUID, 16 | Type: 2, 17 | FileHash: fileHash, 18 | T2: 0, 19 | }, 20 | Field101: 3, 21 | Field102: 103, 22 | Field200: 1, 23 | Field99999: []byte{0xc0, 0x85, 0x2c, 0x01}, 24 | } 25 | return BuildOidbPacket(0xE37, 1200, body, false, false) 26 | } 27 | 28 | func ParsePrivateFileDownloadResp(data []byte) (string, error) { 29 | resp := new(oidb.OidbSvcTrpcTcp0XE37_1200Response) 30 | if _, err := ParseOidbPacket(data, resp); err != nil { 31 | return "", err 32 | } 33 | url := fmt.Sprintf("http://%s:%d%s&isthumb=0", 34 | resp.Body.Result.Server, 35 | resp.Body.Result.Port, 36 | resp.Body.Result.Url, 37 | ) 38 | return url, nil 39 | } 40 | -------------------------------------------------------------------------------- /client/packets/oidb/private_file_upload.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | "github.com/LagrangeDev/LagrangeGo/message" 6 | "github.com/LagrangeDev/LagrangeGo/utils/crypto" 7 | ) 8 | 9 | func BuildPrivateFileUploadReq(selfUID string, targetUID string, file *message.FileElement) (*Packet, error) { 10 | md510MCheckSum, _ := crypto.ComputeMd5AndLengthWithLimit(file.FileStream, 10*1024*1024) 11 | body := &oidb.OidbSvcTrpcTcp0XE37_1700{ 12 | Command: 1700, 13 | Seq: 0, 14 | Upload: &oidb.ApplyUploadReqV3{ 15 | SenderUid: selfUID, 16 | ReceiverUid: targetUID, 17 | FileSize: uint32(file.FileSize), 18 | FileName: file.FileName, 19 | Md510MCheckSum: md510MCheckSum, 20 | Sha1CheckSum: file.FileSha1, 21 | LocalPath: "/", 22 | Md5CheckSum: file.FileMd5, 23 | Sha3CheckSum: []byte{}, 24 | }, 25 | BusinessId: 3, 26 | ClientType: 1, 27 | FlagSupportMediaPlatform: 1, 28 | } 29 | return BuildOidbPacket(0xE37, 1700, body, false, false) 30 | } 31 | 32 | func ParsePrivateFileUploadResp(data []byte) (*oidb.OidbSvcTrpcTcp0XE37Response, error) { 33 | return ParseTypedError[oidb.OidbSvcTrpcTcp0XE37Response](data) 34 | } 35 | -------------------------------------------------------------------------------- /client/packets/oidb/private_image_download.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildPrivateImageDownloadReq(selfUID string, node *oidb.IndexNode) (*Packet, error) { 10 | body := &oidb.NTV2RichMediaReq{ 11 | ReqHead: &oidb.MultiMediaReqHead{ 12 | Common: &oidb.CommonHead{ 13 | RequestId: 1, 14 | Command: 200, 15 | }, 16 | Scene: &oidb.SceneInfo{ 17 | RequestType: 2, 18 | BusinessType: 1, 19 | SceneType: 1, 20 | C2C: &oidb.C2CUserInfo{ 21 | AccountType: 2, 22 | TargetUid: selfUID, 23 | }, 24 | }, 25 | Client: &oidb.ClientMeta{AgentType: 2}, 26 | }, 27 | Download: &oidb.DownloadReq{ 28 | Node: node, 29 | Download: &oidb.DownloadExt{ 30 | Video: &oidb.VideoDownloadExt{ 31 | BusiType: 0, 32 | SceneType: 0, 33 | }, 34 | }, 35 | }, 36 | } 37 | return BuildOidbPacket(0x11C5, 200, body, false, true) 38 | } 39 | 40 | func ParsePrivateImageDownloadResp(data []byte) (string, error) { 41 | resp, err := ParseTypedError[oidb.NTV2RichMediaResp](data) 42 | if err != nil { 43 | return "", err 44 | } 45 | body := resp.Download 46 | return fmt.Sprintf("https://%s%s%s", body.Info.Domain, body.Info.UrlPath, body.RKeyParam), nil 47 | } 48 | -------------------------------------------------------------------------------- /client/packets/oidb/private_record_download.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | // BuildPrivateRecordDownloadReq 私聊语音 10 | func BuildPrivateRecordDownloadReq(selfUID string, node *oidb.IndexNode) (*Packet, error) { 11 | body := oidb.NTV2RichMediaReq{ 12 | ReqHead: &oidb.MultiMediaReqHead{ 13 | Common: &oidb.CommonHead{ 14 | RequestId: 1, 15 | Command: 200, 16 | }, 17 | Scene: &oidb.SceneInfo{ 18 | RequestType: 1, 19 | BusinessType: 3, 20 | SceneType: 1, 21 | C2C: &oidb.C2CUserInfo{ 22 | AccountType: 2, 23 | TargetUid: selfUID, 24 | }, 25 | }, 26 | Client: &oidb.ClientMeta{ 27 | AgentType: 2, 28 | }, 29 | }, 30 | Download: &oidb.DownloadReq{ 31 | Node: node, 32 | Download: &oidb.DownloadExt{ 33 | Video: &oidb.VideoDownloadExt{ 34 | BusiType: 0, 35 | SceneType: 0, 36 | }, 37 | }, 38 | }, 39 | } 40 | 41 | return BuildOidbPacket(0x126D, 200, &body, false, true) 42 | } 43 | 44 | func ParsePrivateRecordDownloadResp(data []byte) (string, error) { 45 | var resp oidb.NTV2RichMediaResp 46 | if _, err := ParseOidbPacket(data, &resp); err != nil { 47 | return "", err 48 | } 49 | body := resp.Download 50 | return fmt.Sprintf("https://%s%s%s", body.Info.Domain, body.Info.UrlPath, body.RKeyParam), nil 51 | } 52 | -------------------------------------------------------------------------------- /client/packets/oidb/private_record_upload.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "encoding/hex" 5 | "errors" 6 | 7 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 8 | "github.com/LagrangeDev/LagrangeGo/message" 9 | "github.com/LagrangeDev/LagrangeGo/utils/crypto" 10 | ) 11 | 12 | func BuildPrivateRecordUploadReq(targetUID string, record *message.VoiceElement) (*Packet, error) { 13 | if record.Stream == nil { 14 | return nil, errors.New("record data is nil") 15 | } 16 | md5 := hex.EncodeToString(record.Md5) 17 | sha1 := hex.EncodeToString(record.Sha1) 18 | body := &oidb.NTV2RichMediaReq{ 19 | ReqHead: &oidb.MultiMediaReqHead{ 20 | Common: &oidb.CommonHead{ 21 | RequestId: 4, 22 | Command: 100, 23 | }, 24 | Scene: &oidb.SceneInfo{ 25 | RequestType: 2, 26 | BusinessType: 3, 27 | SceneType: 1, 28 | C2C: &oidb.C2CUserInfo{ 29 | AccountType: 2, 30 | TargetUid: targetUID, 31 | }, 32 | }, 33 | Client: &oidb.ClientMeta{ 34 | AgentType: 2, 35 | }, 36 | }, 37 | Upload: &oidb.UploadReq{ 38 | UploadInfo: []*oidb.UploadInfo{{ 39 | FileInfo: &oidb.FileInfo{ 40 | FileSize: record.Size, 41 | FileHash: md5, 42 | FileSha1: sha1, 43 | FileName: md5 + ".amr", 44 | Type: &oidb.FileType{ 45 | Type: 3, 46 | PicFormat: 0, 47 | VideoFormat: 0, 48 | VoiceFormat: 1, 49 | }, 50 | Width: 0, 51 | Height: 0, 52 | Time: record.Duration, 53 | Original: 0, 54 | }, 55 | SubFileType: 0, 56 | }}, 57 | TryFastUploadCompleted: true, 58 | SrvSendMsg: false, 59 | ClientRandomId: uint64(crypto.RandU32()), 60 | CompatQMsgSceneType: 1, 61 | ExtBizInfo: &oidb.ExtBizInfo{ 62 | Pic: &oidb.PicExtBizInfo{ 63 | TextSummary: record.Summary, 64 | }, 65 | Ptt: &oidb.PttExtBizInfo{ 66 | BytesReserve: []byte{0x08, 0x00, 0x38, 0x00}, 67 | BytesGeneralFlags: []byte{0x9a, 0x01, 0x0b, 0xaa, 0x03, 0x08, 0x08, 0x04, 0x12, 0x04, 0x00, 0x00, 0x00, 0x00}, 68 | }, 69 | }, 70 | ClientSeq: 0, 71 | NoNeedCompatMsg: false, 72 | }, 73 | } 74 | return BuildOidbPacket(0x126D, 100, body, false, true) 75 | } 76 | 77 | func ParsePrivateRecordUploadResp(data []byte) (*oidb.NTV2RichMediaResp, error) { 78 | return ParseTypedError[oidb.NTV2RichMediaResp](data) 79 | } 80 | -------------------------------------------------------------------------------- /client/packets/oidb/private_video_download.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildPrivateVideoDownloadReq(selfUID string, node *oidb.IndexNode) (*Packet, error) { 10 | body := &oidb.NTV2RichMediaReq{ 11 | ReqHead: &oidb.MultiMediaReqHead{ 12 | Common: &oidb.CommonHead{ 13 | RequestId: 34, // private 12 14 | Command: 200, 15 | }, 16 | Scene: &oidb.SceneInfo{ 17 | RequestType: 2, 18 | BusinessType: 2, 19 | SceneType: 1, 20 | C2C: &oidb.C2CUserInfo{ 21 | AccountType: 2, 22 | TargetUid: selfUID, 23 | }, 24 | }, 25 | Client: &oidb.ClientMeta{ 26 | AgentType: 2, 27 | }, 28 | }, 29 | Download: &oidb.DownloadReq{ 30 | Node: node, 31 | Download: &oidb.DownloadExt{ 32 | Video: &oidb.VideoDownloadExt{}, 33 | }, 34 | }, 35 | } 36 | return BuildOidbPacket(0x11E9, 200, body, false, true) 37 | } 38 | 39 | func ParseVideoDownloadResp(data []byte) (string, error) { 40 | resp, err := ParseTypedError[oidb.NTV2RichMediaResp](data) 41 | if err != nil { 42 | return "", err 43 | } 44 | body := resp.Download 45 | return fmt.Sprintf("https://%s%s%s", body.Info.Domain, body.Info.UrlPath, body.RKeyParam), nil 46 | } 47 | -------------------------------------------------------------------------------- /client/packets/oidb/set_essence_message.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | "github.com/LagrangeDev/LagrangeGo/utils" 6 | ) 7 | 8 | func BuildSetEssenceMessageReq(groupUin, seq, random uint32, isSet bool) (*Packet, error) { 9 | body := oidb.OidbSvcTrpcTcp0XEAC{ 10 | GroupUin: groupUin, 11 | Sequence: seq, 12 | Random: random, 13 | } 14 | return BuildOidbPacket(0xEAC, utils.Ternary[uint32](isSet, 1, 2), &body, false, false) 15 | } 16 | 17 | func ParseSetEssenceMessageResp(data []byte) error { 18 | return CheckError(data) 19 | } 20 | -------------------------------------------------------------------------------- /client/packets/oidb/set_friend_request.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | "github.com/LagrangeDev/LagrangeGo/utils" 6 | ) 7 | 8 | func BuildSetFriendRequest(accept bool, targetUID string) (*Packet, error) { 9 | body := oidb.OidbSvcTrpcTcp0XB5D_44{ 10 | Accept: utils.Ternary[uint32](accept, 3, 5), 11 | TargetUid: targetUID, 12 | } 13 | return BuildOidbPacket(0xb5d, 44, &body, false, false) 14 | } 15 | 16 | func ParseSetFriendRequestResp(data []byte) error { 17 | 18 | return CheckError(data) 19 | } 20 | -------------------------------------------------------------------------------- /client/packets/oidb/set_group_admin.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | ) 6 | 7 | func BuildSetGroupAdminReq(groupUin uint32, uid string, isAdmin bool) (*Packet, error) { 8 | body := &oidb.OidbSvcTrpcTcp0X1096_1{ 9 | GroupUin: groupUin, 10 | Uid: uid, 11 | IsAdmin: isAdmin, 12 | } 13 | return BuildOidbPacket(0x1096, 1, body, false, false) 14 | } 15 | 16 | func ParseSetGroupAdminResp(data []byte) error { 17 | return CheckError(data) 18 | } 19 | -------------------------------------------------------------------------------- /client/packets/oidb/set_group_global_mute.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "math" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 7 | ) 8 | 9 | func BuildSetGroupGlobalMuteReq(groupUin uint32, isMute bool) (*Packet, error) { 10 | var s uint32 11 | if isMute { 12 | s = math.MaxUint32 13 | } 14 | body := &oidb.OidbSvcTrpcTcp0X89A_0{ 15 | GroupUin: groupUin, 16 | State: &oidb.OidbSvcTrpcTcp0X89A_0State{S: s}, 17 | } 18 | return BuildOidbPacket(0x89A, 0, body, false, false) 19 | } 20 | 21 | func ParseSetGroupGlobalMuteResp(data []byte) error { 22 | return CheckError(data) 23 | } 24 | -------------------------------------------------------------------------------- /client/packets/oidb/set_group_leave.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | ) 6 | 7 | func BuildSetGroupLeaveReq(groupUin uint32) (*Packet, error) { 8 | body := &oidb.OidbSvcTrpcTcp0X1097_1{GroupUin: groupUin} 9 | return BuildOidbPacket(0x1097, 1, body, false, false) 10 | } 11 | 12 | func ParseSetGroupLeaveResp(data []byte) error { 13 | return CheckError(data) 14 | } 15 | -------------------------------------------------------------------------------- /client/packets/oidb/set_group_member_mute.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | ) 6 | 7 | func BuildSetGroupMemberMuteReq(groupUin, duration uint32, uid string) (*Packet, error) { 8 | body := &oidb.OidbSvcTrpcTcp0X1253_1{ 9 | GroupUin: groupUin, 10 | Type: 1, 11 | Body: &oidb.OidbSvcTrpcTcp0X1253_1Body{ 12 | TargetUid: uid, 13 | Duration: duration, 14 | }, 15 | } 16 | return BuildOidbPacket(0x1253, 1, body, false, false) 17 | } 18 | 19 | // ParseSetGroupMemberMuteResp 失败了会返回错误原因 20 | func ParseSetGroupMemberMuteResp(data []byte) error { 21 | return CheckTypedError[oidb.OidbSvcTrpcTcp0X1253_1Response](data) 22 | } 23 | -------------------------------------------------------------------------------- /client/packets/oidb/set_group_member_name.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | ) 6 | 7 | func BuildSetGroupMemberNameReq(groupUin uint32, uid, name string) (*Packet, error) { 8 | body := &oidb.OidbSvcTrpcTcp0X8FC{ 9 | GroupUin: groupUin, 10 | Body: &oidb.OidbSvcTrpcTcp0X8FCBody{ 11 | TargetUid: uid, 12 | TargetName: name, 13 | }, 14 | } 15 | return BuildOidbPacket(0x8FC, 3, body, false, false) 16 | } 17 | 18 | func ParseSetGroupMemberNameResp(data []byte) error { 19 | return CheckError(data) 20 | } 21 | -------------------------------------------------------------------------------- /client/packets/oidb/set_group_member_special_title.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | ) 6 | 7 | func BuildSetGroupMemberSpecialTitleReq(groupUin uint32, uid, title string) (*Packet, error) { 8 | body := &oidb.OidbSvcTrpcTcp0X8FC{ 9 | GroupUin: groupUin, 10 | Body: &oidb.OidbSvcTrpcTcp0X8FCBody{ 11 | TargetUid: uid, 12 | SpecialTitle: title, 13 | SpecialTitleExpireTime: -1, 14 | UinName: title, 15 | }, 16 | } 17 | return BuildOidbPacket(0x8FC, 2, body, false, false) 18 | } 19 | 20 | func ParseSetGroupMemberSpecialTitleResp(data []byte) error { 21 | return CheckError(data) 22 | } 23 | -------------------------------------------------------------------------------- /client/packets/oidb/set_group_name.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | ) 6 | 7 | func BuildSetGroupNameReq(groupUin uint32, name string) (*Packet, error) { 8 | body := &oidb.OidbSvcTrpcTcp0X89A_15{ 9 | GroupUin: groupUin, 10 | Body: &oidb.OidbSvcTrpcTcp0X89A_15Body{TargetName: name}, 11 | } 12 | return BuildOidbPacket(0x89A, 15, body, false, false) 13 | } 14 | 15 | func ParseSetGroupNameResp(data []byte) error { 16 | return CheckError(data) 17 | } 18 | -------------------------------------------------------------------------------- /client/packets/oidb/set_group_reaction.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 6 | "github.com/LagrangeDev/LagrangeGo/utils" 7 | ) 8 | 9 | func BuildSetGroupReactionReq(groupUin, sequence uint32, code string, isAdd bool) (*Packet, error) { 10 | body := &oidb.OidbSvcTrpcTcp0X9082{ 11 | GroupUin: groupUin, 12 | Sequence: sequence, 13 | Code: proto.Some(code), 14 | Type: utils.Ternary[uint32](len(code) > 3, 2, 1), 15 | Field6: false, 16 | Field7: false, 17 | } 18 | return BuildOidbPacket(0x9082, utils.Ternary[uint32](isAdd, 1, 2), body, false, true) 19 | } 20 | 21 | func ParseSetGroupReactionResp(data []byte) error { 22 | return CheckError(data) 23 | } 24 | -------------------------------------------------------------------------------- /client/packets/oidb/set_group_remark.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 5 | ) 6 | 7 | func BuildSetGroupRemarkReq(groupUin uint32, mark string) (*Packet, error) { 8 | body := &oidb.OidbSvcTrpcTcp0XF16_1{ 9 | Body: &oidb.OidbSvcTrpcTcp0XF16_1Body{ 10 | GroupUin: groupUin, 11 | TargetRemark: mark, 12 | }, 13 | } 14 | return BuildOidbPacket(0xF16, 1, body, false, false) 15 | } 16 | 17 | func ParseSetGroupRemarkResp(data []byte) error { 18 | return CheckError(data) 19 | } 20 | -------------------------------------------------------------------------------- /client/packets/oidb/set_group_request.go: -------------------------------------------------------------------------------- 1 | package oidb 2 | 3 | import ( 4 | "github.com/RomiChan/protobuf/proto" 5 | 6 | "github.com/LagrangeDev/LagrangeGo/client/entity" 7 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" 8 | "github.com/LagrangeDev/LagrangeGo/utils" 9 | ) 10 | 11 | func BuildSetGroupRequestReq(isFiltered bool, operate entity.GroupRequestOperate, sequence uint64, typ uint32, groupUin uint32, message string) (*Packet, error) { 12 | body := oidb.OidbSvcTrpcTcp0X10C8{ 13 | Accept: uint32(operate), 14 | Body: &oidb.OidbSvcTrpcTcp0X10C8Body{ 15 | Sequence: sequence, 16 | EventType: typ, 17 | GroupUin: groupUin, 18 | Message: proto.Some(message), 19 | }, 20 | } 21 | return BuildOidbPacket(0x10C8, utils.Ternary[uint32](isFiltered, 2, 1), &body, false, false) 22 | } 23 | 24 | func ParseSetGroupRequestResp(data []byte) error { 25 | return CheckError(data) 26 | } 27 | -------------------------------------------------------------------------------- /client/packets/pb/login/ecdh.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/login/ecdh.proto 3 | 4 | package login 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | type SsoKeyExchange struct { 11 | PubKey []byte `protobuf:"bytes,1,opt"` 12 | Type int32 `protobuf:"varint,2,opt"` 13 | GcmCalc1 []byte `protobuf:"bytes,3,opt"` 14 | Timestamp uint32 `protobuf:"varint,4,opt"` 15 | GcmCalc2 []byte `protobuf:"bytes,5,opt"` 16 | } 17 | 18 | type SsoKeyExchangeResponse struct { 19 | GcmEncrypted []byte `protobuf:"bytes,1,opt"` 20 | Body []byte `protobuf:"bytes,2,opt"` 21 | PublicKey []byte `protobuf:"bytes,3,opt"` 22 | } 23 | 24 | type SsoKeyExchangeDecrypted struct { 25 | GcmKey []byte `protobuf:"bytes,1,opt"` 26 | Sign []byte `protobuf:"bytes,2,opt"` 27 | Expiration uint32 `protobuf:"varint,3,opt"` 28 | } 29 | 30 | type SsoKeyExchangePlain struct { 31 | Uin proto.Option[string] `protobuf:"bytes,1,opt"` 32 | Guid []byte `protobuf:"bytes,2,opt"` 33 | } 34 | -------------------------------------------------------------------------------- /client/packets/pb/login/ecdh.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/login"; 4 | 5 | message SsoKeyExchange { 6 | bytes PubKey = 1; 7 | int32 Type = 2; 8 | bytes GcmCalc1 = 3; 9 | uint32 Timestamp = 4; 10 | bytes GcmCalc2 = 5; 11 | } 12 | 13 | message SsoKeyExchangeResponse { 14 | bytes GcmEncrypted = 1; 15 | bytes Body = 2; 16 | bytes PublicKey = 3; 17 | } 18 | 19 | message SsoKeyExchangeDecrypted { 20 | bytes GcmKey = 1; 21 | bytes Sign = 2; 22 | uint32 Expiration = 3; 23 | } 24 | 25 | message SsoKeyExchangePlain { 26 | optional string Uin = 1; 27 | optional bytes Guid = 2; 28 | } 29 | -------------------------------------------------------------------------------- /client/packets/pb/login/ntlogin.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/login"; 4 | 5 | message SsoNTLoginEncryptedData { 6 | optional bytes Sign = 1; 7 | optional bytes GcmCalc = 3; 8 | int32 Type = 4; 9 | } 10 | 11 | message SsoNTLoginBase { 12 | optional SsoNTLoginHeader Header = 1; 13 | optional bytes Body = 2; 14 | } 15 | 16 | message SsoNTLoginHeader { 17 | optional SsoNTLoginUin Uin = 1; 18 | optional SsoNTLoginSystem System = 2; 19 | optional SsoNTLoginVersion Version = 3; 20 | optional SsoNTLoginError Error = 4; 21 | optional SsoNTLoginCookie Cookie = 5; 22 | } 23 | 24 | message SsoNTLoginResponse { 25 | optional SsoNTLoginCredentials Credentials = 1; 26 | optional SsoNTLoginCaptchaUrl Captcha = 2; 27 | optional SsoNTLoginUnusual Unusual = 3; 28 | optional SsoNTLoginUid Uid = 4; 29 | } 30 | 31 | message SsoNTLoginEasyLogin { 32 | optional bytes TempPassword = 1; 33 | optional SsoNTLoginCaptchaSubmit Captcha = 2; 34 | } 35 | 36 | message SsoNTLoginCaptchaSubmit { 37 | string Ticket = 1; 38 | string RandStr = 2; 39 | string Aid = 3; 40 | } 41 | 42 | message SsoNTLoginCaptchaUrl { 43 | string Url = 3; 44 | } 45 | 46 | message SsoNTLoginCookie { 47 | optional string Cookie = 1; 48 | } 49 | 50 | message SsoNTLoginCredentials { 51 | bytes TempPassword = 3; 52 | bytes Tgt = 4; 53 | bytes D2 = 5; 54 | bytes D2Key = 6; 55 | } 56 | 57 | message SsoNTLoginError { 58 | uint32 ErrorCode = 1; 59 | string Tag = 2; 60 | string Message = 3; 61 | optional string NewDeviceVerifyUrl = 5; 62 | } 63 | 64 | message SsoNTLoginSystem { 65 | optional string OS = 1; 66 | optional string DeviceName = 2; 67 | int32 Type = 3; 68 | optional bytes Guid = 4; 69 | } 70 | 71 | message SsoNTLoginUid { 72 | string Uid = 2; 73 | } 74 | 75 | message SsoNTLoginUin { 76 | optional string Uin = 1; 77 | } 78 | 79 | message SsoNTLoginUnusual { 80 | optional bytes Sig = 2; 81 | } 82 | 83 | message SsoNTLoginVersion { 84 | optional string KernelVersion = 1; 85 | int32 AppId = 2; 86 | optional string PackageName = 3; 87 | } 88 | -------------------------------------------------------------------------------- /client/packets/pb/message/c2c.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/message/c2c.proto 3 | 4 | package message 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | type C2C struct { 11 | Uin proto.Option[uint32] `protobuf:"varint,1,opt"` 12 | Uid proto.Option[string] `protobuf:"bytes,2,opt"` 13 | Field3 proto.Option[uint32] `protobuf:"varint,3,opt"` 14 | Sig proto.Option[uint32] `protobuf:"varint,4,opt"` 15 | ReceiverUin proto.Option[uint32] `protobuf:"varint,5,opt"` 16 | ReceiverUid proto.Option[string] `protobuf:"bytes,6,opt"` 17 | _ [0]func() 18 | } 19 | 20 | type C2CRecallMsg struct { 21 | Type uint32 `protobuf:"varint,1,opt"` 22 | TargetUid string `protobuf:"bytes,3,opt"` 23 | Info *C2CRecallMsgInfo `protobuf:"bytes,4,opt"` 24 | Settings *C2CRecallMsgSettings `protobuf:"bytes,5,opt"` 25 | Field6 bool `protobuf:"varint,6,opt"` 26 | _ [0]func() 27 | } 28 | 29 | type C2CRecallMsgInfo struct { 30 | ClientSequence uint32 `protobuf:"varint,1,opt"` 31 | Random uint32 `protobuf:"varint,2,opt"` 32 | MessageId uint64 `protobuf:"varint,3,opt"` 33 | Timestamp uint32 `protobuf:"varint,4,opt"` 34 | Field5 uint32 `protobuf:"varint,5,opt"` 35 | MessageSequence uint32 `protobuf:"varint,6,opt"` 36 | _ [0]func() 37 | } 38 | 39 | type C2CRecallMsgSettings struct { 40 | Field1 bool `protobuf:"varint,1,opt"` 41 | Field2 bool `protobuf:"varint,2,opt"` 42 | _ [0]func() 43 | } 44 | -------------------------------------------------------------------------------- /client/packets/pb/message/c2c.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/message"; 4 | 5 | message C2C { 6 | optional uint32 Uin = 1; 7 | optional string Uid = 2; 8 | optional uint32 Field3 = 3; 9 | optional uint32 Sig = 4; 10 | optional uint32 ReceiverUin = 5; 11 | optional string ReceiverUid = 6; 12 | } 13 | 14 | message C2CRecallMsg { 15 | uint32 Type = 1; 16 | string TargetUid = 3; 17 | C2CRecallMsgInfo Info = 4; 18 | C2CRecallMsgSettings Settings = 5; 19 | bool Field6 = 6; 20 | } 21 | 22 | message C2CRecallMsgInfo { 23 | uint32 ClientSequence = 1; 24 | uint32 Random = 2; 25 | uint64 MessageId = 3; 26 | uint32 Timestamp = 4; 27 | uint32 Field5 = 5; 28 | uint32 MessageSequence = 6; 29 | } 30 | 31 | message C2CRecallMsgSettings { 32 | bool Field1 = 1; 33 | bool Field2 = 2; 34 | } 35 | -------------------------------------------------------------------------------- /client/packets/pb/message/routing.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/message/routing.proto 3 | 4 | package message 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | type ForwardHead struct { 11 | Field1 proto.Option[uint32] `protobuf:"varint,1,opt"` 12 | Field2 proto.Option[uint32] `protobuf:"varint,2,opt"` 13 | Field3 proto.Option[uint32] `protobuf:"varint,3,opt"` // for friend: 2, for group: null 14 | UnknownBase64 proto.Option[string] `protobuf:"bytes,5,opt"` 15 | Avatar proto.Option[string] `protobuf:"bytes,6,opt"` 16 | _ [0]func() 17 | } 18 | 19 | type Grp struct { 20 | GroupCode proto.Option[uint32] `protobuf:"varint,1,opt"` 21 | _ [0]func() 22 | } 23 | 24 | type GrpTmp struct { 25 | GroupUin proto.Option[uint32] `protobuf:"varint,1,opt"` 26 | ToUin proto.Option[uint32] `protobuf:"varint,2,opt"` 27 | _ [0]func() 28 | } 29 | 30 | type ResponseForward struct { 31 | FriendName proto.Option[string] `protobuf:"bytes,6,opt"` 32 | _ [0]func() 33 | } 34 | 35 | type ResponseGrp struct { 36 | GroupUin uint32 `protobuf:"varint,1,opt"` 37 | MemberName string `protobuf:"bytes,4,opt"` 38 | Unknown5 uint32 `protobuf:"varint,5,opt"` 39 | GroupName string `protobuf:"bytes,7,opt"` 40 | _ [0]func() 41 | } 42 | 43 | type Trans0X211 struct { 44 | ToUin proto.Option[uint64] `protobuf:"varint,1,opt"` 45 | CcCmd proto.Option[uint32] `protobuf:"varint,2,opt"` 46 | Uid proto.Option[string] `protobuf:"bytes,8,opt"` 47 | _ [0]func() 48 | } 49 | 50 | type WPATmp struct { 51 | ToUin uint64 `protobuf:"varint,1,opt"` 52 | Sig []byte `protobuf:"bytes,2,opt"` 53 | } 54 | -------------------------------------------------------------------------------- /client/packets/pb/message/routing.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/message"; 4 | 5 | message ForwardHead { 6 | optional uint32 Field1 = 1; 7 | optional uint32 Field2 = 2; 8 | optional uint32 Field3 = 3; // for friend: 2, for group: null 9 | optional string UnknownBase64 = 5; 10 | optional string Avatar = 6; 11 | } 12 | 13 | message Grp { 14 | optional uint32 GroupCode = 1; 15 | } 16 | 17 | message GrpTmp { 18 | optional uint32 GroupUin = 1; 19 | optional uint32 ToUin = 2; 20 | } 21 | 22 | message ResponseForward { 23 | optional string FriendName = 6; 24 | } 25 | 26 | message ResponseGrp { 27 | uint32 GroupUin = 1; 28 | string MemberName = 4; 29 | uint32 Unknown5 = 5; 30 | string GroupName = 7; 31 | } 32 | 33 | message Trans0X211 { 34 | optional uint64 ToUin = 1; 35 | optional uint32 CcCmd = 2; 36 | optional string Uid = 8; 37 | } 38 | 39 | message WPATmp { 40 | uint64 ToUin = 1; 41 | bytes Sig = 2; 42 | } 43 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x102A_0.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x102A_0.proto 3 | 4 | package oidb 5 | 6 | // Get Cookie 7 | type OidbSvcTrpcTcp0X102A_0 struct { 8 | Domain []string `protobuf:"bytes,1,rep"` 9 | } 10 | 11 | type OidbSvcTrpcTcp0X102A_0Response struct { 12 | Urls []*OidbProperty `protobuf:"bytes,1,rep"` 13 | } 14 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x102A_0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | import "pb/service/oidb/generics.proto"; 6 | 7 | // Get Cookie 8 | message OidbSvcTrpcTcp0x102A_0 { 9 | repeated string Domain = 1; 10 | } 11 | 12 | message OidbSvcTrpcTcp0x102A_0Response { 13 | repeated OidbProperty Urls = 1; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x102A_1.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x102A_1.proto 3 | 4 | package oidb 5 | 6 | // // Fetch Client Key lwx: 我也觉得抽象 可是他真的是空的 7 | type OidbSvcTrpcTcp0X102A_1 struct { 8 | _ [0]func() 9 | } 10 | 11 | type OidbSvcTrpcTcp0X102A_1Response struct { 12 | Field1 uint32 `protobuf:"varint,2,opt"` 13 | ClientKey string `protobuf:"bytes,3,opt"` 14 | Expiration uint32 `protobuf:"varint,4,opt"` 15 | _ [0]func() 16 | } 17 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x102A_1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // // Fetch Client Key lwx: 我也觉得抽象 可是他真的是空的 6 | message OidbSvcTrpcTcp0x102A_1 { 7 | 8 | } 9 | 10 | message OidbSvcTrpcTcp0x102A_1Response { 11 | uint32 Field1 = 2; 12 | string ClientKey = 3; 13 | uint32 Expiration = 4; 14 | } 15 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x1096_1.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x1096_1.proto 3 | 4 | package oidb 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | // GroupSetAdmin 11 | type OidbSvcTrpcTcp0X1096_1 struct { 12 | GroupUin uint32 `protobuf:"varint,1,opt"` 13 | Uid string `protobuf:"bytes,2,opt"` 14 | IsAdmin bool `protobuf:"varint,3,opt"` 15 | _ [0]func() 16 | } 17 | 18 | type OidbSvcTrpcTcp0X1096_1Response struct { 19 | Success proto.Option[string] `protobuf:"bytes,1,opt"` 20 | _ [0]func() 21 | } 22 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x1096_1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // GroupSetAdmin 6 | message OidbSvcTrpcTcp0x1096_1 { 7 | uint32 GroupUin = 1; 8 | string Uid = 2; 9 | bool IsAdmin = 3; 10 | } 11 | 12 | message OidbSvcTrpcTcp0x1096_1Response { 13 | optional string Success = 1; 14 | } 15 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x1097_1.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x1097_1.proto 3 | 4 | package oidb 5 | 6 | // Quit Group 7 | type OidbSvcTrpcTcp0X1097_1 struct { 8 | GroupUin uint32 `protobuf:"varint,1,opt"` 9 | _ [0]func() 10 | } 11 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x1097_1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Quit Group 6 | message OidbSvcTrpcTcp0x1097_1 { 7 | uint32 GroupUin = 1; 8 | } 9 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x10C0.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x10C0.proto 3 | 4 | package oidb 5 | 6 | // Fetch Friends & Group Notification List 7 | type OidbSvcTrpcTcp0X10C0 struct { 8 | Count uint32 `protobuf:"varint,1,opt"` 9 | Field2 uint32 `protobuf:"varint,2,opt"` 10 | _ [0]func() 11 | } 12 | 13 | type OidbSvcTrpcTcp0X10C0Response struct { 14 | Requests []*OidbSvcTrpcTcp0X10C0ResponseRequests `protobuf:"bytes,1,rep"` 15 | Field2 uint64 `protobuf:"varint,2,opt"` 16 | NewLatestSeq uint64 `protobuf:"varint,3,opt"` 17 | Field4 uint32 `protobuf:"varint,4,opt"` 18 | Field5 uint64 `protobuf:"varint,5,opt"` 19 | Field6 uint32 `protobuf:"varint,6,opt"` 20 | } 21 | 22 | type OidbSvcTrpcTcp0X10C0ResponseRequests struct { 23 | Sequence uint64 `protobuf:"varint,1,opt"` 24 | EventType uint32 `protobuf:"varint,2,opt"` 25 | State uint32 `protobuf:"varint,3,opt"` 26 | Group *OidbSvcTrpcTcp0X10C0ResponseGroup `protobuf:"bytes,4,opt"` 27 | Target *OidbSvcTrpcTcp0X10C0ResponseUser `protobuf:"bytes,5,opt"` 28 | Invitor *OidbSvcTrpcTcp0X10C0ResponseUser `protobuf:"bytes,6,opt"` 29 | Operator *OidbSvcTrpcTcp0X10C0ResponseUser `protobuf:"bytes,7,opt"` 30 | Field9 string `protobuf:"bytes,9,opt"` 31 | Comment string `protobuf:"bytes,10,opt"` 32 | _ [0]func() 33 | } 34 | 35 | type OidbSvcTrpcTcp0X10C0ResponseGroup struct { 36 | GroupUin uint32 `protobuf:"varint,1,opt"` 37 | GroupName string `protobuf:"bytes,2,opt"` 38 | _ [0]func() 39 | } 40 | 41 | type OidbSvcTrpcTcp0X10C0ResponseUser struct { 42 | Uid string `protobuf:"bytes,1,opt"` 43 | Name string `protobuf:"bytes,2,opt"` 44 | _ [0]func() 45 | } 46 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x10C0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Fetch Friends & Group Notification List 6 | message OidbSvcTrpcTcp0x10C0 { 7 | uint32 Count = 1; 8 | uint32 Field2 = 2; 9 | } 10 | 11 | message OidbSvcTrpcTcp0x10C0Response { 12 | repeated OidbSvcTrpcTcp0x10C0ResponseRequests Requests = 1; 13 | uint64 Field2 = 2; 14 | uint64 NewLatestSeq = 3; 15 | uint32 Field4 = 4; 16 | uint64 Field5 = 5; 17 | uint32 Field6 = 6; 18 | } 19 | 20 | message OidbSvcTrpcTcp0x10C0ResponseRequests { 21 | uint64 Sequence = 1; 22 | uint32 EventType = 2; 23 | uint32 State = 3; 24 | OidbSvcTrpcTcp0x10C0ResponseGroup Group = 4; 25 | OidbSvcTrpcTcp0x10C0ResponseUser Target = 5; 26 | optional OidbSvcTrpcTcp0x10C0ResponseUser Invitor = 6; 27 | optional OidbSvcTrpcTcp0x10C0ResponseUser Operator = 7; 28 | string Field9 = 9; 29 | string Comment = 10; 30 | } 31 | 32 | message OidbSvcTrpcTcp0x10C0ResponseGroup { 33 | uint32 GroupUin = 1; 34 | string GroupName = 2; 35 | } 36 | 37 | message OidbSvcTrpcTcp0x10C0ResponseUser { 38 | string Uid = 1; 39 | string Name = 2; 40 | } 41 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x10C8.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x10C8.proto 3 | 4 | package oidb 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | // Accept group request 11 | type OidbSvcTrpcTcp0X10C8 struct { 12 | Accept uint32 `protobuf:"varint,1,opt"` // 2 for reject, 1 for accept, 3 for ignore 13 | Body *OidbSvcTrpcTcp0X10C8Body `protobuf:"bytes,2,opt"` 14 | _ [0]func() 15 | } 16 | 17 | type OidbSvcTrpcTcp0X10C8Body struct { 18 | Sequence uint64 `protobuf:"varint,1,opt"` // 1 19 | EventType uint32 `protobuf:"varint,2,opt"` // 2 20 | GroupUin uint32 `protobuf:"varint,3,opt"` // 3 21 | Message proto.Option[string] `protobuf:"bytes,4,opt"` // "" 22 | _ [0]func() 23 | } 24 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x10C8.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Accept group request 6 | message OidbSvcTrpcTcp0x10C8 { 7 | uint32 Accept = 1; // 2 for reject, 1 for accept, 3 for ignore 8 | optional OidbSvcTrpcTcp0x10C8Body Body = 2; 9 | } 10 | 11 | message OidbSvcTrpcTcp0x10C8Body { 12 | uint64 Sequence = 1; // 1 13 | uint32 EventType = 2; // 2 14 | uint32 GroupUin = 3; // 3 15 | optional string Message = 4; // "" 16 | } 17 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x1253_1.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x1253_1.proto 3 | 4 | package oidb 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | // Group Member Mute 11 | type OidbSvcTrpcTcp0X1253_1 struct { 12 | GroupUin uint32 `protobuf:"varint,1,opt"` 13 | Type uint32 `protobuf:"varint,2,opt"` 14 | Body *OidbSvcTrpcTcp0X1253_1Body `protobuf:"bytes,3,opt"` 15 | _ [0]func() 16 | } 17 | 18 | type OidbSvcTrpcTcp0X1253_1Body struct { 19 | TargetUid string `protobuf:"bytes,1,opt"` 20 | Duration uint32 `protobuf:"varint,2,opt"` 21 | _ [0]func() 22 | } 23 | 24 | type OidbSvcTrpcTcp0X1253_1Response struct { 25 | Success proto.Option[string] `protobuf:"bytes,2,opt"` 26 | _ [0]func() 27 | } 28 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x1253_1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Group Member Mute 6 | message OidbSvcTrpcTcp0x1253_1 { 7 | uint32 GroupUin = 1; 8 | uint32 Type = 2; 9 | OidbSvcTrpcTcp0x1253_1Body Body = 3; 10 | } 11 | 12 | message OidbSvcTrpcTcp0x1253_1Body { 13 | string TargetUid = 1; 14 | uint32 Duration = 2; 15 | } 16 | 17 | message OidbSvcTrpcTcp0x1253_1Response { 18 | optional string Success = 2; 19 | } 20 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x126B_0.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x126B_0.proto 3 | 4 | package oidb 5 | 6 | type OidbSvcTrpcTcp0X126B_0 struct { 7 | Field1 *OidbSvcTrpcTcp0X126B_0_Field1 `protobuf:"bytes,1,opt"` 8 | _ [0]func() 9 | } 10 | 11 | type OidbSvcTrpcTcp0X126B_0_Field1 struct { 12 | TargetUid string `protobuf:"bytes,1,opt"` 13 | Field2 *OidbSvcTrpcTcp0X126B_0_Field1_2 `protobuf:"bytes,2,opt"` 14 | Block bool `protobuf:"varint,3,opt"` 15 | Field4 bool `protobuf:"varint,4,opt"` // true 16 | _ [0]func() 17 | } 18 | 19 | type OidbSvcTrpcTcp0X126B_0_Field1_2 struct { 20 | Field1 uint32 `protobuf:"varint,1,opt"` // 130 21 | Field2 uint32 `protobuf:"varint,2,opt"` // 109 22 | Field3 *OidbSvcTrpcTcp0X126B_0_Field1_2_3 `protobuf:"bytes,3,opt"` 23 | _ [0]func() 24 | } 25 | 26 | type OidbSvcTrpcTcp0X126B_0_Field1_2_3 struct { 27 | Field1 uint32 `protobuf:"varint,1,opt"` // 8 28 | Field2 uint32 `protobuf:"varint,2,opt"` // 8 29 | Field3 uint32 `protobuf:"varint,3,opt"` // 50 30 | _ [0]func() 31 | } 32 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x126B_0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | message OidbSvcTrpcTcp0x126B_0 { 6 | OidbSvcTrpcTcp0x126B_0_Field1 Field1 = 1; 7 | } 8 | 9 | message OidbSvcTrpcTcp0x126B_0_Field1 { 10 | string TargetUid = 1; 11 | OidbSvcTrpcTcp0x126B_0_Field1_2 Field2 = 2; 12 | bool block = 3; 13 | bool Field4 = 4; // true 14 | } 15 | 16 | message OidbSvcTrpcTcp0x126B_0_Field1_2 { 17 | uint32 Field1 = 1; // 130 18 | uint32 Field2 = 2; // 109 19 | OidbSvcTrpcTcp0x126B_0_Field1_2_3 Field3 = 3; 20 | } 21 | 22 | message OidbSvcTrpcTcp0x126B_0_Field1_2_3 { 23 | uint32 Field1 = 1; // 8 24 | uint32 Field2 = 2; // 8 25 | uint32 Field3 = 3; // 50 26 | } 27 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x5CF_11.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x5CF_11.proto 3 | 4 | package oidb 5 | 6 | // FetchFriendRequests 7 | type OidbSvcTrpcTcp0X5CF_11 struct { 8 | Field1 int32 `protobuf:"varint,1,opt"` // 1 9 | Field3 int32 `protobuf:"varint,3,opt"` // 6 10 | SelfUid string `protobuf:"bytes,4,opt"` 11 | Field5 int32 `protobuf:"varint,5,opt"` // 0 12 | Field6 int32 `protobuf:"varint,6,opt"` // 80 13 | Field8 int32 `protobuf:"varint,8,opt"` // 2 14 | Field9 int32 `protobuf:"varint,9,opt"` // 0 15 | Field12 int32 `protobuf:"varint,12,opt"` // 1 16 | Field22 int32 `protobuf:"varint,22,opt"` //1 17 | _ [0]func() 18 | } 19 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x5CF_11.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // FetchFriendRequests 6 | message OidbSvcTrpcTcp0x5CF_11 { 7 | int32 Field1 = 1; // 1 8 | int32 Field3 = 3; // 6 9 | string SelfUid = 4; 10 | int32 Field5 = 5; // 0 11 | int32 Field6 = 6; // 80 12 | int32 Field8 = 8; // 2 13 | int32 Field9 = 9; // 0 14 | int32 Field12 = 12; // 1 15 | int32 Field22 = 22; //1 16 | } 17 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x6D7.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | message OidbSvcTrpcTcp0x6D7 { 6 | optional OidbSvcTrpcTcp0x6D7Create Create = 1; 7 | optional OidbSvcTrpcTcp0x6D7Delete Delete = 2; 8 | optional OidbSvcTrpcTcp0x6D7Rename Rename = 3; 9 | } 10 | 11 | message OidbSvcTrpcTcp0x6D7Create{ 12 | uint32 GroupUin = 1; 13 | string TargetDirectory = 3; 14 | string FolderName = 4; 15 | } 16 | 17 | message OidbSvcTrpcTcp0x6D7Delete { 18 | uint32 GroupUin = 1; 19 | string FolderId = 3; 20 | } 21 | 22 | message OidbSvcTrpcTcp0x6D7Rename { 23 | uint32 GroupUin = 1; 24 | string FolderId = 3; 25 | string NewFolderName = 4; 26 | } 27 | 28 | message OidbSvcTrpcTcp0x6D7Response { 29 | OidbSvcTrpcTcp0x6D7_0Response Create = 1; 30 | OidbSvcTrpcTcp0x6D7_1_2Response Delete = 2; 31 | OidbSvcTrpcTcp0x6D7_1_2Response Rename = 3; 32 | } 33 | 34 | message OidbSvcTrpcTcp0x6D7_1_2Response { 35 | int32 RetCode = 1; 36 | string RetMsg = 2; 37 | string ClientWording = 3; 38 | } 39 | 40 | message OidbSvcTrpcTcp0x6D7_0Response { 41 | int32 RetCode = 1; 42 | string RetMsg = 2; 43 | string ClientWording = 3; 44 | OidbSvcTrpcTcp0x6D7_0ResponseFolderInfo FolderInfo = 4; 45 | } 46 | 47 | message OidbSvcTrpcTcp0x6D7_0ResponseFolderInfo { 48 | string FolderId = 1; 49 | string FolderPath = 2; 50 | string FolderName = 3; 51 | uint32 Timestamp4 = 4; 52 | uint32 Timestamp5 = 5; 53 | uint32 OperatorUin6 = 6; 54 | uint32 OperatorUin9 = 9; 55 | } -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x6D9_4.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x6D9_4.proto 3 | 4 | package oidb 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | // Group Send File 11 | type OidbSvcTrpcTcp0X6D9_4 struct { 12 | Body *OidbSvcTrpcTcp0X6D9_4Body `protobuf:"bytes,5,opt"` 13 | _ [0]func() 14 | } 15 | 16 | type OidbSvcTrpcTcp0X6D9_4Body struct { 17 | GroupUin uint32 `protobuf:"varint,1,opt"` 18 | Type uint32 `protobuf:"varint,2,opt"` // 2 19 | Info *OidbSvcTrpcTcp0X6D9_4Info `protobuf:"bytes,3,opt"` 20 | _ [0]func() 21 | } 22 | 23 | type OidbSvcTrpcTcp0X6D9_4Info struct { 24 | BusiType uint32 `protobuf:"varint,1,opt"` // 102 25 | FileId string `protobuf:"bytes,2,opt"` 26 | Field3 uint32 `protobuf:"varint,3,opt"` // random 27 | Field4 proto.Option[string] `protobuf:"bytes,4,opt"` 28 | Field5 bool `protobuf:"varint,5,opt"` 29 | _ [0]func() 30 | } 31 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x6D9_4.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Group Send File 6 | message OidbSvcTrpcTcp0x6D9_4 { 7 | OidbSvcTrpcTcp0x6D9_4Body Body = 5; 8 | } 9 | 10 | message OidbSvcTrpcTcp0x6D9_4Body { 11 | uint32 GroupUin = 1; 12 | uint32 Type = 2; // 2 13 | OidbSvcTrpcTcp0x6D9_4Info Info = 3; 14 | } 15 | 16 | message OidbSvcTrpcTcp0x6D9_4Info { 17 | uint32 BusiType = 1; // 102 18 | string FileId = 2; 19 | uint32 Field3 = 3; // random 20 | optional string Field4 = 4; 21 | bool Field5 = 5; 22 | } 23 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x7E5_104.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x7E5_104.proto 3 | 4 | package oidb 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | // Friend Likes 11 | type OidbSvcTrpcTcp0X7E5_104 struct { 12 | TargetUid proto.Option[string] `protobuf:"bytes,11,opt"` 13 | Source uint32 `protobuf:"varint,12,opt"` // 71 14 | Count uint32 `protobuf:"varint,13,opt"` // 1 15 | _ [0]func() 16 | } 17 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x7E5_104.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Friend Likes 6 | message OidbSvcTrpcTcp0x7E5_104 { 7 | optional string TargetUid = 11; 8 | uint32 Source = 12; // 71 9 | uint32 Count = 13; // 1 10 | } 11 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x89A_0.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x89A_0.proto 3 | 4 | package oidb 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | // Group Global Mute 11 | type OidbSvcTrpcTcp0X89A_0 struct { 12 | GroupUin uint32 `protobuf:"varint,1,opt"` 13 | State *OidbSvcTrpcTcp0X89A_0State `protobuf:"bytes,2,opt"` 14 | _ [0]func() 15 | } 16 | 17 | type OidbSvcTrpcTcp0X89A_0State struct { 18 | S uint32 `protobuf:"varint,17,opt"` 19 | _ [0]func() 20 | } 21 | 22 | type OidbSvcTrpcTcp0X89A_0Response struct { 23 | GroupUin uint32 `protobuf:"varint,1,opt"` 24 | ErorMsg proto.Option[string] `protobuf:"bytes,2,opt"` 25 | _ [0]func() 26 | } 27 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x89A_0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Group Global Mute 6 | message OidbSvcTrpcTcp0x89A_0 { 7 | uint32 GroupUin = 1; 8 | OidbSvcTrpcTcp0x89A_0State State = 2; 9 | } 10 | 11 | message OidbSvcTrpcTcp0x89A_0State { 12 | uint32 S = 17; 13 | } 14 | 15 | message OidbSvcTrpcTcp0x89A_0Response { 16 | uint32 GroupUin = 1; 17 | optional string ErorMsg = 2; 18 | } 19 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x89A_15.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x89A_15.proto 3 | 4 | package oidb 5 | 6 | // Rename Group Title 7 | type OidbSvcTrpcTcp0X89A_15 struct { 8 | GroupUin uint32 `protobuf:"varint,1,opt"` 9 | Body *OidbSvcTrpcTcp0X89A_15Body `protobuf:"bytes,2,opt"` 10 | _ [0]func() 11 | } 12 | 13 | type OidbSvcTrpcTcp0X89A_15Body struct { 14 | TargetName string `protobuf:"bytes,3,opt"` 15 | _ [0]func() 16 | } 17 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x89A_15.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Rename Group Title 6 | message OidbSvcTrpcTcp0x89A_15 { 7 | uint32 GroupUin = 1; 8 | OidbSvcTrpcTcp0x89A_15Body Body = 2; 9 | } 10 | 11 | message OidbSvcTrpcTcp0x89A_15Body { 12 | string TargetName = 3; 13 | } 14 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x89E_0.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x89E_0.proto 3 | 4 | package oidb 5 | 6 | // GroupTransfer 7 | type OidbSvcTrpcTcp0X89E_0 struct { 8 | GroupUin uint32 `protobuf:"varint,1,opt"` 9 | SourceUid string `protobuf:"bytes,2,opt"` 10 | TargetUid string `protobuf:"bytes,3,opt"` 11 | _ [0]func() 12 | } 13 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x89E_0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // GroupTransfer 6 | message OidbSvcTrpcTcp0x89E_0 { 7 | uint32 GroupUin = 1; 8 | string SourceUid = 2; 9 | string TargetUid = 3; 10 | } 11 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A0_1.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x8A0_1.proto 3 | 4 | package oidb 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | // Group Kick Member 11 | type OidbSvcTrpcTcp0X8A0_1 struct { 12 | GroupUin uint32 `protobuf:"varint,1,opt"` 13 | TargetUid string `protobuf:"bytes,3,opt"` 14 | RejectAddRequest bool `protobuf:"varint,4,opt"` 15 | Field5 string `protobuf:"bytes,5,opt"` 16 | _ [0]func() 17 | } 18 | 19 | type OidbSvcTrpcTcp0X8A0_1Response struct { 20 | GroupUin uint32 `protobuf:"varint,1,opt"` 21 | ErrorMsg proto.Option[string] `protobuf:"bytes,2,opt"` 22 | _ [0]func() 23 | } 24 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A0_1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Group Kick Member 6 | message OidbSvcTrpcTcp0x8A0_1 { 7 | uint32 GroupUin = 1; 8 | string TargetUid = 3; 9 | bool RejectAddRequest = 4; 10 | string Field5 = 5; 11 | } 12 | 13 | message OidbSvcTrpcTcp0x8A0_1Response { 14 | uint32 GroupUin = 1; 15 | optional string ErrorMsg = 2; 16 | } 17 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.proto 3 | 4 | package oidb 5 | 6 | type OidbSvcTrpcTcp0X8A7_0_ReqBody struct { 7 | SubCmd uint32 `protobuf:"varint,1,opt"` 8 | LimitIntervalTypeForUin uint32 `protobuf:"varint,2,opt"` 9 | LimitIntervalTypeForGroup uint32 `protobuf:"varint,3,opt"` 10 | Uin uint64 `protobuf:"varint,4,opt"` 11 | GroupUin uint64 `protobuf:"varint,5,opt"` 12 | _ [0]func() 13 | } 14 | 15 | type OidbSvcTrpcTcp0X8A7_0_RspBody struct { 16 | CanAtAll bool `protobuf:"varint,1,opt"` 17 | CountForUin uint32 `protobuf:"varint,2,opt"` 18 | CountForGroup uint32 `protobuf:"varint,3,opt"` 19 | _ [0]func() 20 | } 21 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8A7_0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | // ref https://github.com/Mrs4s/MiraiGo/blob/master/client/pb/oidb/oidb0x8a7.proto 4 | 5 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 6 | 7 | message OidbSvcTrpcTcp0x8A7_0_ReqBody { 8 | uint32 subCmd = 1; 9 | uint32 limitIntervalTypeForUin = 2; 10 | uint32 limitIntervalTypeForGroup = 3; 11 | uint64 uin = 4; 12 | uint64 groupUin = 5; 13 | } 14 | 15 | message OidbSvcTrpcTcp0x8A7_0_RspBody { 16 | bool canAtAll = 1; 17 | uint32 countForUin = 2; 18 | uint32 countForGroup = 3; 19 | //optional bytes promptMsg1 = 4; 20 | //optional bytes promptMsg2 = 5; 21 | } 22 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8FC.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x8FC.proto 3 | 4 | package oidb 5 | 6 | // Rename Group Member 7 | type OidbSvcTrpcTcp0X8FC struct { 8 | GroupUin uint32 `protobuf:"varint,1,opt"` 9 | Body *OidbSvcTrpcTcp0X8FCBody `protobuf:"bytes,3,opt"` 10 | _ [0]func() 11 | } 12 | 13 | type OidbSvcTrpcTcp0X8FCBody struct { 14 | TargetUid string `protobuf:"bytes,1,opt"` 15 | SpecialTitle string `protobuf:"bytes,5,opt"` 16 | SpecialTitleExpireTime int32 `protobuf:"varint,6,opt"` 17 | UinName string `protobuf:"bytes,7,opt"` 18 | TargetName string `protobuf:"bytes,8,opt"` 19 | _ [0]func() 20 | } 21 | 22 | type OidbSvcTrpcTcp0X8FC_3Response struct { 23 | GroupUin uint32 `protobuf:"varint,1,opt"` 24 | _ [0]func() 25 | } 26 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x8FC.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Rename Group Member 6 | message OidbSvcTrpcTcp0x8FC { 7 | uint32 GroupUin = 1; 8 | OidbSvcTrpcTcp0x8FCBody Body = 3; 9 | } 10 | 11 | message OidbSvcTrpcTcp0x8FCBody { 12 | string TargetUid = 1; 13 | string SpecialTitle = 5; 14 | int32 SpecialTitleExpireTime = 6; 15 | string UinName = 7; 16 | string TargetName = 8; 17 | } 18 | 19 | message OidbSvcTrpcTcp0x8FC_3Response { 20 | uint32 GroupUin = 1; 21 | } 22 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x9082.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x9082.proto 3 | 4 | package oidb 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | // Group Set Reaction 11 | type OidbSvcTrpcTcp0X9082 struct { 12 | GroupUin uint32 `protobuf:"varint,2,opt"` 13 | Sequence uint32 `protobuf:"varint,3,opt"` 14 | Code proto.Option[string] `protobuf:"bytes,4,opt"` 15 | Type uint32 `protobuf:"varint,5,opt"` // 1 face 2 emoji 16 | Field6 bool `protobuf:"varint,6,opt"` 17 | Field7 bool `protobuf:"varint,7,opt"` 18 | _ [0]func() 19 | } 20 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x9082.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Group Set Reaction 6 | message OidbSvcTrpcTcp0x9082 { 7 | uint32 GroupUin = 2; 8 | uint32 Sequence = 3; 9 | optional string Code = 4; 10 | uint32 Type = 5; // 1 face 2 emoji 11 | bool Field6 = 6; 12 | bool Field7 = 7; 13 | } 14 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929B_0.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x929B_0.proto 3 | 4 | package oidb 5 | 6 | type OidbSvcTrpcTcp0X929B_0_Req struct { 7 | GroupUin uint32 `protobuf:"varint,1,opt"` 8 | VoiceId string `protobuf:"bytes,2,opt"` 9 | Text string `protobuf:"bytes,3,opt"` 10 | ChatType uint32 `protobuf:"varint,4,opt"` // 1 voice,2 song 11 | ClientMsgInfo *OidbSvcTrpcTcp0X929B_0_Req_ClientMsgInfo `protobuf:"bytes,5,opt"` 12 | _ [0]func() 13 | } 14 | 15 | type OidbSvcTrpcTcp0X929B_0_Rsp struct { 16 | Field1 uint32 `protobuf:"varint,1,opt"` // 1 complete, 2 wait 17 | Field2 uint32 `protobuf:"varint,2,opt"` // 319 18 | Field3 uint32 `protobuf:"varint,3,opt"` // 20 19 | MsgInfo *MsgInfo `protobuf:"bytes,4,opt"` 20 | _ [0]func() 21 | } 22 | 23 | type OidbSvcTrpcTcp0X929B_0_Req_ClientMsgInfo struct { 24 | MsgRandom uint32 `protobuf:"varint,1,opt"` 25 | _ [0]func() 26 | } 27 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929B_0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | import "pb/service/oidb/NTV2RichMediaReq.proto"; 6 | 7 | message OidbSvcTrpcTcp0x929B_0_Req { 8 | uint32 groupUin = 1; 9 | string voiceId = 2; 10 | string text = 3; 11 | uint32 chatType = 4; // 1 voice,2 song 12 | ClientMsgInfo clientMsgInfo = 5; 13 | message ClientMsgInfo { 14 | uint32 msgRandom = 1; 15 | } 16 | } 17 | 18 | message OidbSvcTrpcTcp0x929B_0_Rsp { 19 | uint32 field1 = 1; // 1 complete, 2 wait 20 | uint32 field2 = 2; // 319 21 | uint32 field3 = 3; // 20 22 | MsgInfo msgInfo = 4; 23 | } 24 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929D_0.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x929D_0.proto 3 | 4 | package oidb 5 | 6 | type OidbSvcTrpcTcp0X929D_0_Req struct { 7 | GroupUin uint32 `protobuf:"varint,1,opt"` 8 | ChatType uint32 `protobuf:"varint,2,opt"` // 1 voice, 2 song 9 | _ [0]func() 10 | } 11 | 12 | type OidbSvcTrpcTcp0X929D_0_Rsp struct { 13 | Property []*OidbSvcTrpcTcp0X929D_0_Rsp_Key `protobuf:"bytes,1,rep"` 14 | } 15 | 16 | type OidbSvcTrpcTcp0X929D_0_Rsp_Key struct { 17 | Type string `protobuf:"bytes,1,opt"` 18 | Value []*OidbSvcTrpcTcp0X929D_0_Rsp_Property `protobuf:"bytes,2,rep"` 19 | } 20 | 21 | type OidbSvcTrpcTcp0X929D_0_Rsp_Property struct { 22 | CharacterId string `protobuf:"bytes,1,opt"` 23 | CharacterName string `protobuf:"bytes,2,opt"` 24 | CharacterVoiceUrl string `protobuf:"bytes,3,opt"` 25 | _ [0]func() 26 | } 27 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929D_0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | message OidbSvcTrpcTcp0x929D_0_Req { 6 | uint32 groupUin = 1; 7 | uint32 chatType = 2; // 1 voice, 2 song 8 | } 9 | 10 | message OidbSvcTrpcTcp0x929D_0_Rsp { 11 | repeated Key property = 1; 12 | message Key { 13 | string type = 1; 14 | repeated Property value = 2; 15 | } 16 | message Property { 17 | string characterId = 1; 18 | string characterName = 2; 19 | string characterVoiceUrl = 3; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x972_6.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0x972_6.proto 3 | 4 | package oidb 5 | 6 | // RequestFriendSearch 7 | type OidbSvcTrpcTcp0X972_6 struct { 8 | TargetUin string `protobuf:"bytes,1,opt"` 9 | Settings *OidbSvcTrpcTcp0X972_6Settings `protobuf:"bytes,3,opt"` 10 | _ [0]func() 11 | } 12 | 13 | type OidbSvcTrpcTcp0X972_6Settings struct { 14 | Field4 uint32 `protobuf:"varint,4,opt"` // 25 15 | Field11 string `protobuf:"bytes,11,opt"` // "" 16 | Setting string `protobuf:"bytes,55,opt"` // {"search_by_uid":true, "scenario":"related_people_and_groups_panel"} 17 | _ [0]func() 18 | } 19 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0x972_6.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // RequestFriendSearch 6 | message OidbSvcTrpcTcp0x972_6 { 7 | string TargetUin = 1; 8 | OidbSvcTrpcTcp0x972_6Settings Settings = 3; 9 | } 10 | 11 | message OidbSvcTrpcTcp0x972_6Settings { 12 | uint32 Field4 = 4; // 25 13 | string Field11 = 11; // "" 14 | string Setting = 55; // {"search_by_uid":true, "scenario":"related_people_and_groups_panel"} 15 | } 16 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xB5D_44.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0xB5D_44.proto 3 | 4 | package oidb 5 | 6 | // Set Friend Request 7 | type OidbSvcTrpcTcp0XB5D_44 struct { 8 | Accept uint32 `protobuf:"varint,1,opt"` // 3 for accept, 5 for reject 9 | TargetUid string `protobuf:"bytes,2,opt"` 10 | _ [0]func() 11 | } 12 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xB5D_44.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Set Friend Request 6 | message OidbSvcTrpcTcp0xB5D_44 { 7 | uint32 Accept = 1; // 3 for accept, 5 for reject 8 | string TargetUid = 2; 9 | } 10 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xBCB_0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | // ref https://github.com/Mrs4s/MiraiGo/blob/master/client/pb/oidb/oidb0xbcb.proto 4 | 5 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 6 | 7 | message OidbSvcTrpcTcp0xBCB_0_ReqBody { 8 | optional int32 notUseCache = 9; 9 | optional CheckUrlReq checkUrlReq = 10; 10 | } 11 | 12 | message CheckUrlReq { 13 | repeated string url = 1; 14 | optional string refer = 2; 15 | optional string plateform = 3; 16 | optional string qqPfTo = 4; 17 | optional uint32 type = 5; 18 | optional uint32 from = 6; 19 | optional uint64 chatId = 7; 20 | optional uint64 serviceType = 8; 21 | optional uint64 sendUin = 9; 22 | optional string reqType = 10; 23 | optional string originalUrl = 11; 24 | optional bool isArk = 12; 25 | optional string arkName = 13; 26 | optional bool isFinish = 14; 27 | repeated string srcUrls = 15; 28 | optional uint32 srcPlatform = 16; 29 | optional string qua = 17; 30 | } 31 | 32 | message OidbSvcTrpcTcp0xBCB_0_RspBody { 33 | optional string wording = 1; 34 | optional CheckUrlRsp checkUrlRsp = 10; 35 | } 36 | 37 | message CheckUrlRsp { 38 | repeated UrlCheckResult results = 1; 39 | optional uint32 nextReqDuration = 2; 40 | } 41 | 42 | message UrlCheckResult { 43 | optional string url = 1; 44 | optional uint32 result = 2; 45 | optional uint32 jumpResult = 3; 46 | optional string jumpUrl = 4; 47 | optional uint32 level = 5; 48 | optional uint32 subLevel = 6; 49 | optional uint32 umrType = 7; 50 | optional uint32 retFrom = 8; 51 | optional uint64 operationBit = 9; 52 | } 53 | 54 | /* 55 | message CheckUrlReqItem { 56 | optional string url = 1; 57 | optional string refer = 2; 58 | optional string plateform = 3; 59 | optional string qqPfTo = 4; 60 | optional uint32 type = 5; 61 | optional uint32 from = 6; 62 | optional uint64 chatId = 7; 63 | optional uint64 serviceType = 8; 64 | optional uint64 sendUin = 9; 65 | optional string reqType = 10; 66 | } 67 | */ 68 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE07_0.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | message OidbSvcTrpcTcp0xE07_0 { 6 | uint32 Version = 1; 7 | uint32 Client = 2; 8 | uint32 Entrance = 3; 9 | OcrReqBody OcrReqBody = 10; 10 | } 11 | 12 | message OcrReqBody { 13 | string ImageUrl = 1; 14 | uint32 LanguageType = 2; 15 | uint32 Scene = 3; 16 | string OriginMd5 = 10; 17 | string AfterCompressMd5 = 11; 18 | string AfterCompressFileSize = 12; 19 | string AfterCompressWeight = 13; 20 | string AfterCompressHeight = 14; 21 | bool IsCut = 15; 22 | } 23 | 24 | message OidbSvcTrpcTcp0xE07_0_Response { 25 | int32 RetCode = 1; 26 | string ErrMsg = 2; 27 | string Wording = 3; 28 | OcrRspBody OcrRspBody = 10; 29 | } 30 | 31 | message OcrRspBody { 32 | repeated TextDetection TextDetections = 1; 33 | string Language = 2; 34 | string RequestId = 3; 35 | repeated string OcrLanguageList = 101; 36 | repeated string DstTranslateLanguageList = 102; 37 | repeated Language LanguageList = 103; 38 | uint32 AfterCompressWeight = 111; 39 | uint32 AfterCompressHeight = 112; 40 | } 41 | 42 | message TextDetection { 43 | string DetectedText = 1; 44 | int32 Confidence = 2; 45 | Polygon Polygon = 3; 46 | string AdvancedInfo = 4; 47 | } 48 | 49 | message Polygon { 50 | repeated Coordinate Coordinates = 1; 51 | } 52 | 53 | message Coordinate { 54 | int32 X = 1; 55 | int32 Y = 2; 56 | } 57 | 58 | message Language { 59 | string LanguageCode = 1; 60 | string LanguageDesc = 2; 61 | } -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE37_1200.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // FileDownload 6 | message OidbSvcTrpcTcp0xE37_1200 { 7 | uint32 SubCommand = 1; // 1200 8 | int32 Field2 = 2; // 1 9 | OidbSvcTrpcTcp0xE37_1200Body Body = 14; 10 | int32 Field101 = 101; // 3 11 | int32 Field102 = 102; // 103 12 | int32 Field200 = 200; // 1 13 | bytes Field99999 = 99999; // 0xc0, 0x85, 0x2c, 0x01 14 | // Actually it is a sub-proto 90200: 1, but we it would be more easy to just hardcode it 15 | } 16 | 17 | message OidbSvcTrpcTcp0xE37_1200Body { 18 | string ReceiverUid = 10; 19 | string FileUuid = 20; 20 | int32 Type = 30; // 2 21 | string FileHash = 60; 22 | int32 T2 = 601; // 0 23 | } 24 | 25 | message OidbSvcTrpcTcp0xE37_1200Response { 26 | uint32 Command = 1; 27 | uint32 SubCommand = 2; 28 | OidbSvcTrpcTcp0xE37_1200ResponseBody Body = 14; 29 | uint32 Field50 = 50; 30 | } 31 | 32 | message OidbSvcTrpcTcp0xE37_1200ResponseBody { 33 | uint32 Field10 = 10; 34 | string State = 20; 35 | OidbSvcTrpcTcp0xE37_1200Result Result = 30; 36 | OidbSvcTrpcTcp0xE37_1200Metadata Metadata = 40; 37 | } 38 | 39 | message OidbSvcTrpcTcp0xE37_1200Result { 40 | string Server = 20; 41 | uint32 Port = 40; 42 | string Url = 50; 43 | repeated string AdditionalServer = 60; 44 | uint32 SsoPort = 80; 45 | string SsoUrl = 90; 46 | bytes Extra = 120; 47 | } 48 | 49 | message OidbSvcTrpcTcp0xE37_1200Metadata { 50 | uint32 Uin = 1; 51 | uint32 Field2 = 2; 52 | uint32 Field3 = 3; 53 | uint32 Size = 4; 54 | uint32 Timestamp = 5; 55 | string FileUuid = 6; 56 | string FileName = 7; 57 | bytes Field100 = 100; 58 | bytes Field101 = 101; 59 | uint32 Field110 = 110; 60 | uint32 Timestamp1 = 130; 61 | string FileHash = 140; 62 | bytes Field141 = 141; 63 | bytes Field142 = 142; 64 | } 65 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE37_1700.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0xE37_1700.proto 3 | 4 | package oidb 5 | 6 | // Upload Offline File 7 | type OidbSvcTrpcTcp0XE37_1700 struct { 8 | Command uint32 `protobuf:"varint,1,opt"` // 1700 9 | Seq int32 `protobuf:"varint,2,opt"` // 0 10 | Upload *ApplyUploadReqV3 `protobuf:"bytes,19,opt"` 11 | BusinessId int32 `protobuf:"varint,101,opt"` // 3 12 | ClientType int32 `protobuf:"varint,102,opt"` // 1 13 | FlagSupportMediaPlatform int32 `protobuf:"varint,200,opt"` // 1 14 | _ [0]func() 15 | } 16 | 17 | type ApplyUploadReqV3 struct { 18 | SenderUid string `protobuf:"bytes,10,opt"` 19 | ReceiverUid string `protobuf:"bytes,20,opt"` 20 | FileSize uint32 `protobuf:"varint,30,opt"` 21 | FileName string `protobuf:"bytes,40,opt"` 22 | Md510MCheckSum []byte `protobuf:"bytes,50,opt"` 23 | Sha1CheckSum []byte `protobuf:"bytes,60,opt"` 24 | LocalPath string `protobuf:"bytes,70,opt"` 25 | Md5CheckSum []byte `protobuf:"bytes,110,opt"` 26 | Sha3CheckSum []byte `protobuf:"bytes,120,opt"` 27 | } 28 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE37_1700.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Upload Offline File 6 | message OidbSvcTrpcTcp0xE37_1700 { 7 | uint32 Command = 1; // 1700 8 | int32 Seq = 2; // 0 9 | ApplyUploadReqV3 Upload = 19; 10 | int32 BusinessId = 101; // 3 11 | int32 ClientType = 102; // 1 12 | int32 FlagSupportMediaPlatform = 200; // 1 13 | } 14 | 15 | message ApplyUploadReqV3 { 16 | string SenderUid = 10; 17 | string ReceiverUid = 20; 18 | uint32 FileSize = 30; 19 | string FileName = 40; 20 | bytes Md510MCheckSum = 50; 21 | bytes Sha1CheckSum = 60; 22 | string LocalPath = 70; 23 | bytes Md5CheckSum = 110; 24 | bytes Sha3CheckSum = 120; 25 | } 26 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xE37_800.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Get Offline File Download 6 | message OidbSvcTrpcTcp0xE37_800 { 7 | uint32 SubCommand = 1; 8 | int32 Field2 = 2; 9 | OidbSvcTrpcTcp0xE37_800Body Body = 10; 10 | int32 Field101 = 101; 11 | int32 Field102 = 102; 12 | int32 Field200 = 200; 13 | } 14 | 15 | message OidbSvcTrpcTcp0xE37_800Body { 16 | string SenderUid = 10; 17 | string ReceiverUid = 20; 18 | string FileUuid = 30; 19 | string FileHash = 40; 20 | } 21 | 22 | message OidbSvcTrpcTcp0xE37Response { 23 | uint32 Command = 1; 24 | int32 Seq = 2; 25 | ApplyUploadRespV3 Upload = 19; 26 | int32 BusinessId = 101; 27 | int32 ClientType = 102; 28 | int32 FlagSupportMediaPlatform = 200; 29 | } 30 | 31 | message ApplyUploadRespV3 { 32 | int32 RetCode = 10; 33 | string RetMsg = 20; 34 | int64 TotalSpace = 30; 35 | int64 UsedSpace = 40; 36 | int64 UploadedSize = 50; 37 | string UploadIp = 60; 38 | string UploadDomain = 70; 39 | uint32 UploadPort = 80; 40 | string Uuid = 90; 41 | bytes UploadKey = 100; 42 | bool BoolFileExist = 110; 43 | int32 PackSize = 120; 44 | repeated string UploadIpList = 130; 45 | int32 UploadHttpsPort = 140; 46 | string UploadHttpsDomain = 150; 47 | string UploadDns = 160; 48 | string UploadLanip = 170; 49 | string FileAddon = 200; 50 | bytes MediaPlatformUploadKey = 220; 51 | } 52 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xEAC.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0xEAC.proto 3 | 4 | package oidb 5 | 6 | // RemoveEssenceMessage 7 | type OidbSvcTrpcTcp0XEAC struct { 8 | GroupUin uint32 `protobuf:"varint,1,opt"` 9 | Sequence uint32 `protobuf:"varint,2,opt"` 10 | Random uint32 `protobuf:"varint,3,opt"` 11 | _ [0]func() 12 | } 13 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xEAC.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // RemoveEssenceMessage 6 | message OidbSvcTrpcTcp0xEAC { 7 | uint32 GroupUin = 1; 8 | uint32 Sequence = 2; 9 | uint32 Random = 3; 10 | } 11 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xEB7_1.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0xEB7_1.proto 3 | 4 | package oidb 5 | 6 | type OidbSvcTrpcTcp0XEB7_1_ReqBody struct { 7 | SignInWriteReq *StSignInWriteReq `protobuf:"bytes,2,opt"` 8 | _ [0]func() 9 | } 10 | 11 | type StSignInWriteReq struct { 12 | Uin string `protobuf:"bytes,1,opt"` 13 | GroupUin string `protobuf:"bytes,2,opt"` 14 | AppVersion string `protobuf:"bytes,3,opt"` // 不确定要不要加,测试过没有这个参数也是可以的 15 | _ [0]func() 16 | } 17 | 18 | type OidbSvcTrpcTcp0XEB7_1_RspBody struct { 19 | SignInWriteRsp *StSignInWriteRsp `protobuf:"bytes,2,opt"` 20 | _ [0]func() 21 | } 22 | 23 | type StSignInWriteRsp struct { 24 | DoneInfo *SignInStatusDoneInfo `protobuf:"bytes,2,opt"` 25 | _ [0]func() 26 | } 27 | 28 | type SignInStatusDoneInfo struct { 29 | Title string `protobuf:"bytes,1,opt"` // 今日已成功打卡 30 | KeepDayText string `protobuf:"bytes,2,opt"` // 已打卡N天 31 | ClockInInfo []string `protobuf:"bytes,3,rep"` // ["群内排名第N位", "[clock in timestamp (second)]"] 32 | DetailUrl string `protobuf:"bytes,4,opt"` // https://qun.qq.com/v2/signin/detail?... 33 | } 34 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xEB7_1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // see https://github.com/LagrangeDev/Lagrange.Core/blob/47b819d43ad101a1a066a3f8afa094d000fe19f5/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xEB7_1.cs 6 | 7 | message OidbSvcTrpcTcp0xEB7_1_ReqBody { 8 | optional StSignInWriteReq signInWriteReq = 2; 9 | } 10 | 11 | message StSignInWriteReq { 12 | string Uin = 1; 13 | string GroupUin = 2; 14 | string AppVersion = 3; // 不确定要不要加,测试过没有这个参数也是可以的 15 | } 16 | 17 | message OidbSvcTrpcTcp0xEB7_1_RspBody { 18 | optional StSignInWriteRsp signInWriteRsp = 2; 19 | } 20 | 21 | message StSignInWriteRsp { 22 | optional SignInStatusDoneInfo doneInfo = 2; 23 | } 24 | 25 | message SignInStatusDoneInfo { 26 | string Title = 1; // 今日已成功打卡 27 | string KeepDayText = 2; // 已打卡N天 28 | repeated string ClockInInfo = 3; // ["群内排名第N位", "[clock in timestamp (second)]"] 29 | string DetailUrl = 4; // https://qun.qq.com/v2/signin/detail?... 30 | } 31 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xED3_1.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0xED3_1.proto 3 | 4 | package oidb 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | // Poke 11 | type OidbSvcTrpcTcp0XED3_1 struct { 12 | Uin uint32 `protobuf:"varint,1,opt"` 13 | GroupUin uint32 `protobuf:"varint,2,opt"` // same when poke type is friend 14 | FriendUin uint32 `protobuf:"varint,5,opt"` 15 | Ext proto.Option[uint32] `protobuf:"varint,6,opt"` 16 | _ [0]func() 17 | } 18 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xED3_1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Poke 6 | message OidbSvcTrpcTcp0xED3_1 { 7 | uint32 Uin = 1; 8 | uint32 GroupUin = 2; // same when poke type is friend 9 | uint32 FriendUin = 5; 10 | optional uint32 Ext = 6; 11 | } 12 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xF16_1.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0xF16_1.proto 3 | 4 | package oidb 5 | 6 | // Group Remark 7 | type OidbSvcTrpcTcp0XF16_1 struct { 8 | Body *OidbSvcTrpcTcp0XF16_1Body `protobuf:"bytes,1,opt"` 9 | _ [0]func() 10 | } 11 | 12 | type OidbSvcTrpcTcp0XF16_1Body struct { 13 | GroupUin uint32 `protobuf:"varint,1,opt"` 14 | TargetRemark string `protobuf:"bytes,3,opt"` 15 | _ [0]func() 16 | } 17 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xF16_1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Group Remark 6 | message OidbSvcTrpcTcp0xF16_1 { 7 | OidbSvcTrpcTcp0xF16_1Body Body = 1; 8 | } 9 | 10 | message OidbSvcTrpcTcp0xF16_1Body { 11 | uint32 GroupUin = 1; 12 | string TargetRemark = 3; 13 | } 14 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xFD4_1.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/OidbSvcTrpcTcp0xFD4_1.proto 3 | 4 | package oidb 5 | 6 | // Fetch Friends List 7 | type OidbSvcTrpcTcp0XFD4_1 struct { 8 | Field2 uint32 `protobuf:"varint,2,opt"` // page count, 300 9 | Field4 uint32 `protobuf:"varint,4,opt"` // 0 10 | NextUin *OidbSvcTrpcTcp0XFD4_1Uin `protobuf:"bytes,5,opt"` 11 | Field6 uint32 `protobuf:"varint,6,opt"` // 1 12 | Body []*OidbSvcTrpcTcp0XFD4_1Body `protobuf:"bytes,10001,rep"` 13 | Field10002 []uint32 `protobuf:"varint,10002,rep"` // [13578, 13579, 13573, 13572, 13568] 14 | Field10003 uint32 `protobuf:"varint,10003,opt"` 15 | } 16 | 17 | type OidbSvcTrpcTcp0XFD4_1Uin struct { 18 | Uin uint32 `protobuf:"varint,1,opt"` 19 | _ [0]func() 20 | } 21 | 22 | type OidbSvcTrpcTcp0XFD4_1Body struct { 23 | Type uint32 `protobuf:"varint,1,opt"` 24 | Number *OidbNumber `protobuf:"bytes,2,opt"` 25 | _ [0]func() 26 | } 27 | 28 | type OidbSvcTrpcTcp0XFD4_1Response struct { 29 | Next *OidbSvcTrpcTcp0XFD4_1Uin `protobuf:"bytes,2,opt"` 30 | DisplayFriendCount uint32 `protobuf:"varint,3,opt"` 31 | Timestamp uint32 `protobuf:"varint,6,opt"` 32 | SelfUin uint32 `protobuf:"varint,7,opt"` 33 | Friends []*OidbFriend `protobuf:"bytes,101,rep"` 34 | } 35 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xFD4_1.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | import "pb/service/oidb/generics.proto"; 6 | 7 | // Fetch Friends List 8 | message OidbSvcTrpcTcp0xFD4_1 { 9 | uint32 Field2 = 2; // page count, 300 10 | uint32 Field4 = 4; // 0 11 | OidbSvcTrpcTcp0xFD4_1Uin NextUin = 5; 12 | uint32 Field6 = 6; // 1 13 | repeated OidbSvcTrpcTcp0xFD4_1Body Body = 10001; 14 | repeated uint32 Field10002 = 10002; // [13578, 13579, 13573, 13572, 13568] 15 | uint32 Field10003 = 10003; 16 | } 17 | 18 | message OidbSvcTrpcTcp0xFD4_1Uin { 19 | uint32 Uin = 1; 20 | } 21 | 22 | message OidbSvcTrpcTcp0xFD4_1Body { 23 | uint32 Type = 1; 24 | OidbNumber Number = 2; 25 | } 26 | 27 | message OidbSvcTrpcTcp0xFD4_1Response { 28 | OidbSvcTrpcTcp0xFD4_1Uin Next = 2; 29 | uint32 DisplayFriendCount = 3; 30 | uint32 Timestamp = 6; 31 | uint32 SelfUin = 7; 32 | repeated OidbFriend Friends = 101; 33 | } 34 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xFE1_2.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | import "pb/service/oidb/generics.proto"; 6 | 7 | // Fetch Avatar 8 | message OidbSvcTrpcTcp0xFE1_2 { 9 | optional string Uid = 1; 10 | uint32 Field2 = 2; 11 | repeated OidbSvcTrpcTcp0xFE1_2Key Keys = 3; 12 | } 13 | 14 | message OidbSvcTrpcTcp0xFE1_2Uin { 15 | uint32 Uin = 1; 16 | uint32 Field2 = 2; 17 | repeated OidbSvcTrpcTcp0xFE1_2Key Keys = 3; 18 | } 19 | 20 | message OidbSvcTrpcTcp0xFE1_2Key { 21 | uint32 Key = 1; 22 | } 23 | 24 | message OidbSvcTrpcTcp0xFE1_2Response { 25 | OidbSvcTrpcTcp0xFE1_2ResponseBody Body = 1; 26 | } 27 | 28 | message OidbSvcTrpcTcp0xFE1_2ResponseBody { 29 | // string Uid = 1; 30 | OidbSvcTrpcTcp0xFE1_2ResponseProperty Properties = 2; 31 | uint32 Uin = 3; 32 | } 33 | 34 | message OidbSvcTrpcTcp0xFE1_2ResponseProperty { 35 | repeated OidbTwoNumber NumberProperties = 1; 36 | repeated OidbFriendProperty StringProperties = 2; 37 | } 38 | 39 | message CustomStatus { 40 | uint32 FaceId = 1; 41 | optional string Msg = 2; 42 | } 43 | 44 | message Avatar { 45 | optional string URL = 5; 46 | } 47 | 48 | message Business { 49 | optional BusinessBody Body = 3; 50 | } 51 | 52 | message BusinessBody { 53 | optional string Msg = 1; 54 | repeated BusinessList Lists = 3; 55 | } 56 | 57 | message BusinessList { 58 | uint32 Type = 1; 59 | uint32 Field2 = 2; 60 | bool IsYear = 3; // 是否年费 61 | uint32 Level = 4; 62 | bool IsPro = 5; // 是否超级 63 | oneof Icon { 64 | string Icon1 = 6; 65 | string Icon2 = 7; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xFE5_2.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Fetch Groups 6 | message OidbSvcTrpcTcp0xFE5_2 { 7 | OidbSvcTrpcTcp0xFE5_2Config Config = 1; 8 | } 9 | 10 | message OidbSvcTrpcTcp0xFE5_2Config { 11 | OidbSvcTrpcTcp0xFE5_2Config1 Config1 = 1; 12 | OidbSvcTrpcTcp0xFE5_2Config2 Config2 = 2; 13 | OidbSvcTrpcTcp0xFE5_2Config3 Config3 = 3; 14 | } 15 | 16 | message OidbSvcTrpcTcp0xFE5_2Config1 { 17 | // all true 18 | bool GroupOwner = 1; 19 | bool Field2 = 2; 20 | bool MemberMax = 3; 21 | bool MemberCount = 4; 22 | bool GroupName = 5; 23 | bool Field8 = 8; 24 | bool Field9 = 9; 25 | bool Field10 = 10; 26 | bool Field11 = 11; 27 | bool Field12 = 12; 28 | bool Field13 = 13; 29 | bool Field14 = 14; 30 | bool Field15 = 15; 31 | bool Field16 = 16; 32 | bool Field17 = 17; 33 | bool Field18 = 18; 34 | bool Question = 19; 35 | bool Field20 = 20; 36 | bool Field22 = 22; 37 | bool Field23 = 23; 38 | bool Field24 = 24; 39 | bool Field25 = 25; 40 | bool Field26 = 26; 41 | bool Field27 = 27; 42 | bool Field28 = 28; 43 | bool Field29 = 29; 44 | bool Field30 = 30; 45 | bool Field31 = 31; 46 | bool Field32 = 32; 47 | bool Field5001 = 5001; 48 | bool Field5002 = 5002; 49 | bool Field5003 = 5003; 50 | } 51 | 52 | message OidbSvcTrpcTcp0xFE5_2Config2 { 53 | // all ture 54 | bool Field1 = 1; 55 | bool Field2 = 2; 56 | bool Field3 = 3; 57 | bool Field4 = 4; 58 | bool Field5 = 5; 59 | bool Field6 = 6; 60 | bool Field7 = 7; 61 | bool Field8 = 8; 62 | } 63 | 64 | message OidbSvcTrpcTcp0xFE5_2Config3 { 65 | bool Field5 = 5; 66 | bool Field6 = 6; 67 | } 68 | 69 | message OidbSvcTrpcTcp0xFE5_2Response { 70 | repeated OidbSvcTrpcTcp0xFE5_2Group Groups = 2; 71 | } 72 | 73 | message OidbSvcTrpcTcp0xFE5_2Group { 74 | uint32 GroupUin = 3; 75 | OidbSvcTrpcTcp0xFE5_2GroupInfo Info = 4; 76 | ExtGroupInfo ExtInfo = 5; 77 | } 78 | 79 | message OidbSvcTrpcTcp0xFE5_2GroupInfo { 80 | OidbSvcTrpcTcp0xFE5_2Member GroupOwner = 1; 81 | uint32 CreateTimeStamp = 2; 82 | uint32 MemberMax = 3; 83 | uint32 MemberCount = 4; 84 | string GroupName = 5; 85 | } 86 | 87 | message OidbSvcTrpcTcp0xFE5_2Member { 88 | string Uid = 2; 89 | } 90 | 91 | message ExtGroupInfo { 92 | uint32 LastMsgTimeStamp = 1; 93 | string GroupMemo = 3; 94 | uint32 ShutupTimestampMe = 4; 95 | } 96 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/OidbSvcTrpcTcp0xFE7_3.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | // Fetch Group Member List 6 | message OidbSvcTrpcTcp0xFE7_3 { 7 | uint32 GroupUin = 1; 8 | uint32 Field2 = 2; 9 | uint32 Field3 = 3; 10 | OidbSvcTrpcScp0xFE7_3Body Body = 4; 11 | optional string Token = 15; 12 | } 13 | 14 | message OidbSvcTrpcScp0xFE7_3Body { 15 | // all ture 16 | bool MemberName = 10; 17 | bool MemberCard = 11; 18 | bool Level = 12; 19 | bool SpecialTitle = 17; 20 | bool Field4 = 20; 21 | bool Field5 = 21; 22 | bool JoinTimestamp = 100; 23 | bool LastMsgTimestamp = 101; 24 | bool ShutUpTimestamp = 102; 25 | bool Field9 = 103; 26 | bool Field10 = 104; 27 | bool Field11 = 105; 28 | bool Field12 = 106; 29 | bool Permission = 107; 30 | } 31 | 32 | message OidbSvcTrpcTcp0xFE7_2Response { 33 | uint32 GroupUin = 1; 34 | repeated OidbSvcTrpcTcp0xFE7_2Member Members = 2; 35 | uint32 Field3 = 3; 36 | uint32 MemberChangeSeq = 5; 37 | uint32 MemberCardChangeSeq = 6; 38 | optional string Token = 15; // for the next page 39 | } 40 | 41 | message OidbSvcTrpcTcp0xFE7_2Member { 42 | OidbSvcTrpcTcp0xFE7_2Uin Uin = 1; 43 | string MemberName = 10; 44 | OidbSvcTrpcTcp0xFE7_2Card MemberCard = 11; 45 | optional OidbSvcTrpcTcp0xFE7_2Level Level = 12; 46 | optional string SpecialTitle = 17; 47 | uint32 JoinTimestamp = 100; 48 | uint32 LastMsgTimestamp = 101; 49 | optional uint32 ShutUpTimestamp = 102; 50 | uint32 Permission = 107; 51 | } 52 | 53 | message OidbSvcTrpcTcp0xFE7_2Uin { 54 | string Uid = 2; 55 | uint32 Uin = 4; 56 | } 57 | 58 | message OidbSvcTrpcTcp0xFE7_2Card { 59 | optional string MemberCard = 2; 60 | } 61 | 62 | message OidbSvcTrpcTcp0xFE7_2Level { 63 | repeated uint32 Infos = 1; 64 | uint32 Level = 2; 65 | } 66 | 67 | message OidbSvcTrpcTcp0xFE7_4 { 68 | uint32 GroupUin = 1; 69 | uint32 Field2 = 2; 70 | uint32 Field3 = 3; 71 | OidbSvcTrpcScp0xFE7_3Body Body = 4; 72 | OidbSvcTrpcScp0xFE7_4Params Params = 5; 73 | } 74 | 75 | message OidbSvcTrpcScp0xFE7_4Params { 76 | string Uid = 2; 77 | } 78 | 79 | message OidbSvcTrpcTcp0xFE7_4Response { 80 | uint32 GroupUin = 1; 81 | OidbSvcTrpcTcp0xFE7_2Member Member = 2; 82 | uint32 Field3 = 3; 83 | } 84 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/base.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/base.proto 3 | 4 | package oidb 5 | 6 | type OidbSvcTrpcTcpBase struct { 7 | Command uint32 `protobuf:"varint,1,opt"` 8 | SubCommand uint32 `protobuf:"varint,2,opt"` 9 | ErrorCode uint32 `protobuf:"varint,3,opt"` 10 | Body []byte `protobuf:"bytes,4,opt"` 11 | ErrorMsg string `protobuf:"bytes,5,opt"` 12 | Lafter *OidbLafter `protobuf:"bytes,7,opt"` 13 | Properties []*OidbProperty `protobuf:"bytes,11,rep"` 14 | Reserved int32 `protobuf:"varint,12,opt"` 15 | } 16 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/base.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | import "pb/service/oidb/generics.proto"; 6 | 7 | // Protobuf版Tlv sbtx 8 | 9 | message OidbSvcTrpcTcpBase { 10 | uint32 Command = 1; 11 | uint32 SubCommand = 2; 12 | uint32 ErrorCode = 3; 13 | bytes Body = 4; 14 | string ErrorMsg = 5; 15 | optional OidbLafter Lafter = 7; 16 | repeated OidbProperty Properties = 11; 17 | int32 Reserved = 12; 18 | } 19 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/generics.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/oidb/generics.proto 3 | 4 | package oidb 5 | 6 | type OidbFriend struct { 7 | Uid string `protobuf:"bytes,1,opt"` 8 | Uin uint32 `protobuf:"varint,3,opt"` 9 | Additional []*OidbFriendAdditional `protobuf:"bytes,10001,rep"` 10 | } 11 | 12 | type OidbFriendAdditional struct { 13 | Type uint32 `protobuf:"varint,1,opt"` 14 | Layer1 *OidbFriendLayer1 `protobuf:"bytes,2,opt"` 15 | _ [0]func() 16 | } 17 | 18 | type OidbFriendLayer1 struct { 19 | Properties []*OidbFriendProperty `protobuf:"bytes,2,rep"` 20 | } 21 | 22 | type OidbFriendProperty struct { 23 | Code uint32 `protobuf:"varint,1,opt"` 24 | Value string `protobuf:"bytes,2,opt"` 25 | _ [0]func() 26 | } 27 | 28 | type OidbLafter struct { 29 | Type int32 `protobuf:"varint,1,opt"` 30 | D2 []byte `protobuf:"bytes,2,opt"` 31 | SubAppid uint32 `protobuf:"varint,3,opt"` 32 | } 33 | 34 | type OidbNumber struct { 35 | Numbers []uint32 `protobuf:"varint,1,rep"` 36 | } 37 | 38 | type OidbProperty struct { 39 | Key string `protobuf:"bytes,1,opt"` 40 | Value []byte `protobuf:"bytes,2,opt"` 41 | } 42 | 43 | type OidbTwoNumber struct { 44 | Number1 uint32 `protobuf:"varint,1,opt"` 45 | Number2 uint32 `protobuf:"varint,2,opt"` 46 | _ [0]func() 47 | } 48 | -------------------------------------------------------------------------------- /client/packets/pb/service/oidb/generics.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; 4 | 5 | message OidbFriend { 6 | string Uid = 1; 7 | uint32 Uin = 3; 8 | repeated OidbFriendAdditional Additional = 10001; 9 | } 10 | 11 | message OidbFriendAdditional { 12 | uint32 Type = 1; 13 | OidbFriendLayer1 Layer1 = 2; 14 | } 15 | 16 | message OidbFriendLayer1 { 17 | repeated OidbFriendProperty Properties = 2; 18 | } 19 | 20 | message OidbFriendProperty { 21 | uint32 Code = 1; 22 | string Value = 2; 23 | } 24 | 25 | message OidbLafter { 26 | int32 Type = 1; 27 | bytes D2 = 2; 28 | uint32 SubAppid = 3; 29 | } 30 | 31 | message OidbNumber { 32 | repeated uint32 Numbers = 1; 33 | } 34 | 35 | message OidbProperty { 36 | string Key = 1; 37 | bytes Value = 2; 38 | } 39 | 40 | message OidbTwoNumber { 41 | uint32 Number1 = 1; 42 | uint32 Number2 = 2; 43 | } 44 | -------------------------------------------------------------------------------- /client/packets/pb/service/service.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/service/service.proto 3 | 4 | package service 5 | 6 | import ( 7 | proto "github.com/RomiChan/protobuf/proto" 8 | ) 9 | 10 | type InfoPushGroup struct { 11 | GroupUin uint32 `protobuf:"varint,1,opt"` 12 | Sequence1 uint32 `protobuf:"varint,2,opt"` 13 | Sequence2 uint32 `protobuf:"varint,3,opt"` 14 | Field4 uint32 `protobuf:"varint,4,opt"` 15 | LastMsgTime uint32 `protobuf:"varint,8,opt"` 16 | GroupName string `protobuf:"bytes,9,opt"` 17 | Sequence3 uint32 `protobuf:"varint,10,opt"` 18 | Random uint64 `protobuf:"varint,11,opt"` 19 | Field13 uint32 `protobuf:"varint,13,opt"` 20 | _ [0]func() 21 | } 22 | 23 | // ref https://github.com/Mrs4s/MiraiGo/blob/54bdd873e3fed9fe1c944918924674dacec5ac76/client/pb/web/WebSsoBody.proto#L1 24 | type STServiceMonitItem struct { 25 | Cmd proto.Option[string] `protobuf:"bytes,1,opt"` 26 | Url proto.Option[string] `protobuf:"bytes,2,opt"` 27 | Errcode proto.Option[int32] `protobuf:"varint,3,opt"` 28 | Cost proto.Option[uint32] `protobuf:"varint,4,opt"` 29 | Src proto.Option[uint32] `protobuf:"varint,5,opt"` 30 | _ [0]func() 31 | } 32 | 33 | type STServiceMonitReq struct { 34 | List []*STServiceMonitItem `protobuf:"bytes,1,rep"` 35 | } 36 | 37 | type WebSsoControlData struct { 38 | Frequency proto.Option[uint32] `protobuf:"varint,1,opt"` 39 | PackageSize proto.Option[uint32] `protobuf:"varint,2,opt"` 40 | _ [0]func() 41 | } 42 | 43 | type WebSsoRequestBody struct { 44 | Version proto.Option[uint32] `protobuf:"varint,1,opt"` 45 | Type proto.Option[uint32] `protobuf:"varint,2,opt"` 46 | Data proto.Option[string] `protobuf:"bytes,3,opt"` 47 | WebData proto.Option[string] `protobuf:"bytes,4,opt"` 48 | _ [0]func() 49 | } 50 | 51 | type WebSsoResponseBody struct { 52 | Version proto.Option[uint32] `protobuf:"varint,1,opt"` 53 | Type proto.Option[uint32] `protobuf:"varint,2,opt"` 54 | Ret proto.Option[uint32] `protobuf:"varint,3,opt"` 55 | Data proto.Option[string] `protobuf:"bytes,4,opt"` 56 | ControlData *WebSsoControlData `protobuf:"bytes,5,opt"` 57 | _ [0]func() 58 | } 59 | -------------------------------------------------------------------------------- /client/packets/pb/service/service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service"; 4 | 5 | message InfoPushGroup { 6 | uint32 GroupUin = 1; 7 | uint32 Sequence1 = 2; 8 | uint32 Sequence2 = 3; 9 | uint32 Field4 = 4; 10 | uint32 LastMsgTime = 8; 11 | string GroupName = 9; 12 | uint32 Sequence3 = 10; 13 | uint64 Random = 11; 14 | uint32 Field13 = 13; 15 | } 16 | 17 | 18 | // ref https://github.com/Mrs4s/MiraiGo/blob/54bdd873e3fed9fe1c944918924674dacec5ac76/client/pb/web/WebSsoBody.proto#L1 19 | message STServiceMonitItem { 20 | optional string cmd = 1; 21 | optional string url = 2; 22 | optional int32 errcode = 3; 23 | optional uint32 cost = 4; 24 | optional uint32 src = 5; 25 | } 26 | 27 | message STServiceMonitReq { 28 | repeated STServiceMonitItem list = 1; 29 | } 30 | 31 | message WebSsoControlData { 32 | optional uint32 frequency = 1; 33 | optional uint32 packageSize = 2; 34 | } 35 | 36 | message WebSsoRequestBody { 37 | optional uint32 version = 1; 38 | optional uint32 type = 2; 39 | optional string data = 3; 40 | optional string webData = 4; 41 | } 42 | 43 | message WebSsoResponseBody { 44 | optional uint32 version = 1; 45 | optional uint32 type = 2; 46 | optional uint32 ret = 3; 47 | optional string data = 4; 48 | optional WebSsoControlData controlData = 5; 49 | } 50 | 51 | 52 | -------------------------------------------------------------------------------- /client/packets/pb/system/system.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/system"; 4 | 5 | message NTDeviceSign { 6 | string Trace = 15; 7 | optional string Uid = 16; 8 | optional Sign Sign = 24; 9 | } 10 | 11 | message Sign { 12 | optional bytes Signature = 1; 13 | optional string Token = 2; 14 | optional Software S = 3; 15 | } 16 | 17 | message Software { 18 | string Ver = 2; 19 | optional string Token = 3; 20 | } 21 | 22 | message NTOS { 23 | string OS = 1; 24 | string Name = 2; 25 | } 26 | 27 | message NTPacketUid { 28 | optional string Uid = 16; 29 | } 30 | 31 | message NTSsoHeartBeat { 32 | int32 Type = 1; 33 | } 34 | 35 | message NTSysEvent { 36 | string IP = 1; 37 | int64 Sid = 2; 38 | NTSysEventSub Sub = 3; 39 | } 40 | 41 | message NTSysEventSub { 42 | int64 State = 2; 43 | int32 Field3 = 3; 44 | int64 Field4 = 4; 45 | int64 Uin = 5; 46 | int32 Flag = 6; 47 | int32 On = 7; 48 | uint32 GroupUin = 8; 49 | } 50 | 51 | message OnlineOsInfo { 52 | string User = 1; 53 | string OS = 2; 54 | string OSVer = 3; 55 | optional string VendorName = 4; 56 | string OSLower = 5; 57 | } 58 | 59 | message ServiceKickNTResponse { 60 | uint32 Uin = 1; 61 | string Tips = 3; 62 | string Title = 4; 63 | int32 Field5 = 5; 64 | int32 Field6 = 6; 65 | int32 Field8 = 8; 66 | } 67 | 68 | message ServiceRegister { 69 | optional string Guid = 1; 70 | optional int32 Type = 2; 71 | optional string CurrentVersion = 3; 72 | optional int32 Field4 = 4; 73 | optional int32 LocaleId = 5; // 2052 74 | optional OnlineOsInfo Online = 6; 75 | optional int32 SetMute = 7; 76 | optional int32 RegisterVendorType = 8; 77 | optional int32 RegType = 9; 78 | } 79 | 80 | message ServiceRegisterResponse { 81 | optional string Message = 2; 82 | uint32 Timestamp = 3; 83 | int32 Field4 = 4; 84 | int32 Field5 = 5; 85 | } 86 | -------------------------------------------------------------------------------- /client/packets/pb/tlv543.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-golite. DO NOT EDIT. 2 | // source: pb/tlv543.proto 3 | 4 | package pb 5 | 6 | type Tlv543 struct { 7 | Layer1 *Tlv543Layer1 `protobuf:"bytes,9,opt"` 8 | _ [0]func() 9 | } 10 | 11 | type Tlv543Layer1 struct { 12 | Layer2 *Tlv543Layer2 `protobuf:"bytes,11,opt"` 13 | _ [0]func() 14 | } 15 | 16 | type Tlv543Layer2 struct { 17 | Uid string `protobuf:"bytes,1,opt"` 18 | _ [0]func() 19 | } 20 | -------------------------------------------------------------------------------- /client/packets/pb/tlv543.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb"; 4 | 5 | message Tlv543 { 6 | Tlv543Layer1 Layer1 = 9; 7 | } 8 | 9 | message Tlv543Layer1 { 10 | Tlv543Layer2 Layer2 = 11; 11 | } 12 | 13 | message Tlv543Layer2 { 14 | string Uid = 1; 15 | } 16 | -------------------------------------------------------------------------------- /client/packets/tlv/qrcode.go: -------------------------------------------------------------------------------- 1 | package tlv 2 | 3 | import ( 4 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 5 | "github.com/LagrangeDev/LagrangeGo/utils/binary" 6 | ) 7 | 8 | func T11(unusualSign []byte) []byte { 9 | return binary.NewBuilder(). 10 | WriteBytes(unusualSign). 11 | Pack(0x11) 12 | } 13 | 14 | func T16(appid, appidQrcode int, guid []byte, ptVersion, packageName string) []byte { 15 | return binary.NewBuilder(). 16 | WriteU32(0). 17 | WriteU32(uint32(appid)). 18 | WriteU32(uint32(appidQrcode)). 19 | WriteBytes(guid). 20 | WritePacketString(packageName, "u16", false). 21 | WritePacketString(ptVersion, "u16", false). 22 | WritePacketString(packageName, "u16", false). 23 | Pack(0x16) 24 | } 25 | 26 | func T1b(micro, version, size, margin, dpi, ecLevel, hint uint32) []byte { 27 | return binary.NewBuilder(). 28 | WriteStruct(micro, version, size, margin, dpi, ecLevel, hint, uint16(0)). 29 | Pack(0x1B) 30 | } 31 | 32 | func T1d(miscBitmap int) []byte { 33 | return binary.NewBuilder(). 34 | WriteU8(1). 35 | WriteU32(uint32(miscBitmap)). 36 | WriteU32(0). 37 | WriteU8(0). 38 | Pack(0x1d) 39 | } 40 | 41 | func T33(guid []byte) []byte { 42 | return binary.NewBuilder().WriteBytes(guid).Pack(0x33) 43 | } 44 | 45 | func T35(ptOSVersion int) []byte { 46 | return binary.NewBuilder().WriteU32(uint32(ptOSVersion)).Pack(0x35) 47 | } 48 | 49 | func T66(ptOSVersion int) []byte { 50 | return binary.NewBuilder().WriteU32(uint32(ptOSVersion)).Pack(0x66) 51 | } 52 | 53 | func Td1(appOS, deviceName string) []byte { 54 | return binary.NewBuilder(). 55 | WriteBytes(proto.DynamicMessage{ 56 | 1: proto.DynamicMessage{ 57 | 1: appOS, 58 | 2: deviceName, 59 | }, 60 | 4: proto.DynamicMessage{ 61 | 6: 1, 62 | }, 63 | }.Encode()). 64 | Pack(0xd1) 65 | } 66 | -------------------------------------------------------------------------------- /client/packets/wtlogin/exchange.go: -------------------------------------------------------------------------------- 1 | package wtlogin 2 | 3 | import ( 4 | "encoding/hex" 5 | "strconv" 6 | "time" 7 | 8 | "github.com/LagrangeDev/LagrangeGo/client/auth" 9 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/login" 10 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 11 | "github.com/LagrangeDev/LagrangeGo/utils" 12 | "github.com/LagrangeDev/LagrangeGo/utils/binary" 13 | "github.com/LagrangeDev/LagrangeGo/utils/crypto" 14 | "github.com/LagrangeDev/LagrangeGo/utils/crypto/ecdh" 15 | ) 16 | 17 | var encKey, _ = hex.DecodeString("e2733bf403149913cbf80c7a95168bd4ca6935ee53cd39764beebe2e007e3aee") 18 | 19 | func BuildKexExchangeRequest(uin uint32, guid string) ([]byte, error) { 20 | plain1, err := proto.Marshal(&login.SsoKeyExchangePlain{ 21 | Uin: proto.Some(strconv.Itoa(int(uin))), 22 | Guid: utils.MustParseHexStr(guid), 23 | }) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | encl, err := crypto.AESGCMEncrypt(plain1, ecdh.P256().SharedKey()) 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | p2Hash := crypto.SHA256Digest( 34 | binary.NewBuilder(). 35 | WriteBytes(ecdh.P256().PublicKey()). 36 | WriteU32(1). 37 | WriteBytes(encl). 38 | WriteU32(0). 39 | WriteU32(uint32(utils.TimeStamp())). 40 | ToBytes(), 41 | ) 42 | encP2Hash, err := crypto.AESGCMEncrypt(p2Hash, encKey) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | return proto.Marshal(&login.SsoKeyExchange{ 48 | PubKey: ecdh.P256().PublicKey(), 49 | Type: 1, 50 | GcmCalc1: encl, 51 | Timestamp: uint32(time.Now().Unix()), 52 | GcmCalc2: encP2Hash, 53 | }) 54 | } 55 | 56 | func ParseKeyExchangeResponse(response []byte, sig *auth.SigInfo) error { 57 | var p login.SsoKeyExchangeResponse 58 | err := proto.Unmarshal(response, &p) 59 | if err != nil { 60 | return err 61 | } 62 | 63 | shareKey, err := ecdh.P256().Exange(p.PublicKey) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | var decPb login.SsoKeyExchangeDecrypted 69 | data, err := crypto.AESGCMDecrypt(p.GcmEncrypted, shareKey) 70 | if err != nil { 71 | return err 72 | } 73 | err = proto.Unmarshal(data, &decPb) 74 | if err != nil { 75 | return err 76 | } 77 | sig.ExchangeKey = decPb.GcmKey 78 | sig.KeySig = decPb.Sign 79 | 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /client/packets/wtlogin/loginstate/enum.go: -------------------------------------------------------------------------------- 1 | package loginstate 2 | 3 | type State int 4 | 5 | const ( 6 | TokenExpired State = 140022015 7 | UnusualVerify State = 140022011 8 | LoginFailure State = 140022013 9 | UserTokenExpired State = 140022016 10 | ServerFailure State = 140022002 //unknown reason 11 | WrongCaptcha State = 140022007 12 | WrongArgument State = 140022001 13 | NewDeviceVerify State = 140022010 14 | CaptchaVerify State = 140022008 15 | UnknownError State = -1 16 | Success State = 0 17 | ) 18 | 19 | var statenames = map[State]string{ 20 | TokenExpired: "TokenExpired", 21 | UnusualVerify: "UnusualVerify", 22 | LoginFailure: "LoginFailure", 23 | UserTokenExpired: "UserTokenExpired", 24 | ServerFailure: "ServerFailure", 25 | WrongCaptcha: "WrongCaptcha", 26 | WrongArgument: "WrongArgument", 27 | NewDeviceVerify: "NewDeviceVerify", 28 | CaptchaVerify: "CaptchaVerify", 29 | UnknownError: "UnknownError", 30 | Success: "Success", 31 | } 32 | 33 | func (r State) Name() string { 34 | name, ok := statenames[r] 35 | if ok { 36 | return name 37 | } 38 | return "Unknown" 39 | } 40 | 41 | func (r State) Missing() bool { 42 | return r == UnknownError 43 | } 44 | 45 | func (r State) Successful() bool { 46 | return r == Success 47 | } 48 | 49 | func (r State) NeedVerify() bool { 50 | return r == NewDeviceVerify || r == CaptchaVerify || r == UnusualVerify 51 | } 52 | -------------------------------------------------------------------------------- /client/packets/wtlogin/qrcodestate/enum.go: -------------------------------------------------------------------------------- 1 | package qrcodestate 2 | 3 | type State int 4 | 5 | const ( 6 | Confirmed State = 0 7 | Expired State = 17 8 | WaitingForScan State = 48 9 | WaitingForConfirm State = 53 10 | Canceled State = 54 11 | ) 12 | 13 | var statenames = map[State]string{ 14 | Confirmed: "Confirmed", 15 | Expired: "Expired", 16 | WaitingForScan: "WaitingForScan", 17 | WaitingForConfirm: "WaitingForConfirm", 18 | Canceled: "Canceled", 19 | } 20 | 21 | func (r State) Name() string { 22 | name, ok := statenames[r] 23 | if ok { 24 | return name 25 | } 26 | return "Unknown" 27 | } 28 | 29 | func (r State) Waitable() bool { 30 | return r == WaitingForScan || r == WaitingForConfirm 31 | } 32 | 33 | func (r State) Success() bool { 34 | return r == Confirmed 35 | } 36 | -------------------------------------------------------------------------------- /client/packets/wtlogin/statusService.go: -------------------------------------------------------------------------------- 1 | package wtlogin 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | 7 | "github.com/LagrangeDev/LagrangeGo/client/auth" 8 | "github.com/LagrangeDev/LagrangeGo/client/packets/pb/system" 9 | "github.com/LagrangeDev/LagrangeGo/internal/proto" 10 | ) 11 | 12 | // BuildRegisterRequest trpc.qq_new_tech.status_svc.StatusService.Register 13 | func BuildRegisterRequest(app *auth.AppInfo, device *auth.DeviceInfo) []byte { 14 | return proto.DynamicMessage{ 15 | 1: strings.ToUpper(device.GUID), 16 | 2: 0, 17 | 3: app.CurrentVersion, 18 | 4: 0, 19 | 5: 2052, 20 | 6: proto.DynamicMessage{ 21 | 1: device.DeviceName, 22 | 2: app.Kernel, 23 | 3: device.SystemKernel, 24 | 4: "", 25 | 5: app.VendorOS, 26 | }, 27 | 7: false, // set_mute 28 | 8: false, // register_vendor_type 29 | 9: true, // regtype 30 | }.Encode() 31 | } 32 | 33 | // BuildSSOHeartbeatRequest trpc.qq_new_tech.status_svc.StatusService.SsoHeartBeat 34 | func BuildSSOHeartbeatRequest() []byte { 35 | //return proto.DynamicMessage{ 36 | // 1: 1, 37 | //}.Encode() 38 | // 直接硬编码罢 39 | return []byte{0x08, 0x01} 40 | } 41 | 42 | func ParseRegisterResponse(response []byte) error { 43 | var resp system.ServiceRegisterResponse 44 | err := proto.Unmarshal(response, &resp) 45 | if err != nil { 46 | return err 47 | } 48 | msg := resp.Message.Unwrap() 49 | if msg == "register success" { 50 | return nil 51 | } 52 | return errors.New(msg) 53 | } 54 | -------------------------------------------------------------------------------- /client/sign/provider.go: -------------------------------------------------------------------------------- 1 | package sign 2 | 3 | import ( 4 | "encoding/hex" 5 | "encoding/json" 6 | 7 | "github.com/LagrangeDev/LagrangeGo/client/auth" 8 | ) 9 | 10 | type ( 11 | HexData []byte 12 | 13 | Request struct { 14 | Cmd string `json:"cmd"` 15 | Seq int `json:"seq"` 16 | Src HexData `json:"src"` 17 | } 18 | 19 | Response struct { 20 | Platform string `json:"platform"` 21 | Version string `json:"version"` 22 | Value struct { 23 | Sign HexData `json:"sign"` 24 | Extra HexData `json:"extra"` 25 | Token HexData `json:"token"` 26 | } `json:"value"` 27 | } 28 | ) 29 | 30 | func (h HexData) MarshalJSON() ([]byte, error) { 31 | return json.Marshal(hex.EncodeToString(h)) 32 | } 33 | 34 | func (h *HexData) UnmarshalJSON(data []byte) error { 35 | var hexStr string 36 | if err := json.Unmarshal(data, &hexStr); err != nil { 37 | return err 38 | } 39 | decoded, err := hex.DecodeString(hexStr) 40 | if err != nil { 41 | return err 42 | } 43 | *h = decoded 44 | return nil 45 | } 46 | 47 | type Provider interface { 48 | Sign(cmd string, seq uint32, data []byte) (*Response, error) 49 | AddRequestHeader(header map[string]string) 50 | AddSignServer(signServers ...string) 51 | GetSignServer() []string 52 | SetAppInfo(app *auth.AppInfo) 53 | Release() 54 | } 55 | -------------------------------------------------------------------------------- /client/statistics.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/client/statistics.go 4 | 5 | import ( 6 | "bytes" 7 | "strconv" 8 | "sync/atomic" 9 | ) 10 | 11 | type Statistics struct { 12 | PacketReceived atomic.Uint64 13 | PacketSent atomic.Uint64 14 | PacketLost atomic.Uint64 15 | MessageReceived atomic.Uint64 16 | MessageSent atomic.Uint64 17 | LastMessageTime atomic.Int64 18 | DisconnectTimes atomic.Uint32 19 | LostTimes atomic.Uint32 20 | } 21 | 22 | func (c *QQClient) GetStatistics() *Statistics { 23 | return &c.stat 24 | } 25 | 26 | // MarshalJSON encodes the wrapped statistics into JSON. 27 | func (m *Statistics) MarshalJSON() ([]byte, error) { 28 | var w bytes.Buffer 29 | w.Grow(256) 30 | w.WriteString(`{"packet_received":`) 31 | w.WriteString(strconv.FormatUint(m.PacketReceived.Load(), 10)) 32 | w.WriteString(`,"packet_sent":`) 33 | w.WriteString(strconv.FormatUint(m.PacketSent.Load(), 10)) 34 | w.WriteString(`,"packet_lost":`) 35 | w.WriteString(strconv.FormatUint(m.PacketLost.Load(), 10)) 36 | w.WriteString(`,"message_received":`) 37 | w.WriteString(strconv.FormatUint(m.MessageReceived.Load(), 10)) 38 | w.WriteString(`,"message_sent":`) 39 | w.WriteString(strconv.FormatUint(m.MessageSent.Load(), 10)) 40 | w.WriteString(`,"disconnect_times":`) 41 | w.WriteString(strconv.FormatUint(uint64(m.DisconnectTimes.Load()), 10)) 42 | w.WriteString(`,"lost_times":`) 43 | w.WriteString(strconv.FormatUint(uint64(m.LostTimes.Load()), 10)) 44 | w.WriteString(`,"last_message_time":`) 45 | w.WriteString(strconv.FormatInt(m.LastMessageTime.Load(), 10)) 46 | w.WriteByte('}') 47 | return w.Bytes(), nil 48 | } 49 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/LagrangeDev/LagrangeGo 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/RomiChan/protobuf v0.1.1-0.20230204044148-2ed269a2e54d 7 | github.com/RomiChan/syncx v0.0.0-20240418144900-b7402ffdebc7 8 | github.com/fumiama/gofastTEA v0.1.3 9 | github.com/fumiama/imgsz v0.0.4 10 | github.com/fumiama/orbyte v0.0.0-20250512155242-23a2b7120589 11 | github.com/mattn/go-colorable v0.1.13 12 | github.com/pkg/errors v0.9.1 13 | github.com/sirupsen/logrus v1.9.3 14 | github.com/tidwall/gjson v1.18.0 15 | golang.org/x/net v0.33.0 16 | golang.org/x/sync v0.9.0 17 | ) 18 | 19 | require ( 20 | github.com/mattn/go-isatty v0.0.16 // indirect 21 | github.com/tidwall/match v1.1.1 // indirect 22 | github.com/tidwall/pretty v1.2.0 // indirect 23 | golang.org/x/image v0.18.0 // indirect 24 | golang.org/x/sys v0.28.0 // indirect 25 | ) 26 | -------------------------------------------------------------------------------- /internal/proto/dynamic_test.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/internal/proto/dynamic_test.go 4 | 5 | import ( 6 | "bytes" 7 | "math" 8 | "testing" 9 | ) 10 | 11 | func benchEncoderUvarint(b *testing.B, v uint64) { 12 | e := encoder{} 13 | for i := 0; i < b.N; i++ { 14 | e.buf = e.buf[:0] 15 | e.uvarint(v) 16 | } 17 | } 18 | 19 | func benchEncoderSvarint(b *testing.B, v int64) { 20 | e := encoder{} 21 | for i := 0; i < b.N; i++ { 22 | e.buf = e.buf[:0] 23 | e.svarint(v) 24 | } 25 | } 26 | 27 | func Benchmark_encoder_uvarint(b *testing.B) { 28 | b.Run("short", func(b *testing.B) { 29 | benchEncoderUvarint(b, uint64(1)) 30 | }) 31 | b.Run("medium", func(b *testing.B) { 32 | benchEncoderUvarint(b, uint64(114514)) 33 | }) 34 | b.Run("large", func(b *testing.B) { 35 | benchEncoderUvarint(b, math.MaxUint64) 36 | }) 37 | } 38 | 39 | func Benchmark_encoder_svarint(b *testing.B) { 40 | b.Run("short", func(b *testing.B) { 41 | benchEncoderSvarint(b, int64(1)) 42 | }) 43 | b.Run("medium", func(b *testing.B) { 44 | benchEncoderSvarint(b, int64(114514)) 45 | }) 46 | b.Run("large", func(b *testing.B) { 47 | benchEncoderSvarint(b, math.MaxInt64) 48 | }) 49 | } 50 | 51 | func TestDynamicMessage_Encode(t *testing.T) { 52 | input := DynamicMessage{ 53 | 1: 2, 54 | 3: 4, 55 | } 56 | got := input.Encode() 57 | expected := []byte{1 << 3, 2, 3 << 3, 4} 58 | if !bytes.Equal(got, expected) { 59 | t.Fatalf("expected %v but got %v", expected, got) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /internal/proto/wrapper.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/internal/proto/wrapper.go 4 | 5 | import ( 6 | "reflect" 7 | 8 | "github.com/RomiChan/protobuf/proto" 9 | ) 10 | 11 | // TODO: move to a new package 12 | const debug = false 13 | 14 | type Message = any 15 | 16 | func Marshal(m Message) ([]byte, error) { 17 | b, err := proto.Marshal(m) 18 | if err != nil { 19 | return b, err 20 | } 21 | if debug { 22 | t := reflect.TypeOf(m).Elem() 23 | n := reflect.New(t) 24 | err = Unmarshal(b, n.Interface()) 25 | if err != nil { 26 | panic(err) 27 | } 28 | if reflect.DeepEqual(m, n) { 29 | panic("not equal") 30 | } 31 | } 32 | return b, err 33 | } 34 | 35 | func Unmarshal(b []byte, m Message) error { 36 | return proto.Unmarshal(b, m) 37 | } 38 | 39 | func Some[T any](val T) proto.Option[T] { 40 | return proto.Some(val) 41 | } 42 | 43 | func None[T any]() proto.Option[T] { 44 | return proto.None[T]() 45 | } 46 | 47 | // Bool stores v in a new bool value and returns a pointer to it. 48 | func Bool(v bool) proto.Option[bool] { return proto.Some(v) } 49 | 50 | // Int32 stores v in a new int32 value and returns a pointer to it. 51 | func Int32(v int32) proto.Option[int32] { return proto.Some(v) } 52 | 53 | // Int64 stores v in a new int64 value and returns a pointer to it. 54 | func Int64(v int64) proto.Option[int64] { return proto.Some(v) } 55 | 56 | // Float32 stores v in a new float32 value and returns a pointer to it. 57 | func Float32(v float32) proto.Option[float32] { return proto.Some(v) } 58 | 59 | // Float64 stores v in a new float64 value and returns a pointer to it. 60 | func Float64(v float64) proto.Option[float64] { return proto.Some(v) } 61 | 62 | // Uint32 stores v in a new uint32 value and returns a pointer to it. 63 | func Uint32(v uint32) proto.Option[uint32] { return proto.Some(v) } 64 | 65 | // Uint64 stores v in a new uint64 value and returns a pointer to it. 66 | func Uint64(v uint64) proto.Option[uint64] { return proto.Some(v) } 67 | 68 | // String stores v in a new string value and returns a pointer to it. 69 | func String(v string) proto.Option[string] { return proto.Some(v) } 70 | -------------------------------------------------------------------------------- /message/default_thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LagrangeDev/LagrangeGo/92282d2ecf3f3e8cca8a69b2dfb2c8405eac1e59/message/default_thumb.jpg -------------------------------------------------------------------------------- /message/essence.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | type GroupEssenceMessage struct { 4 | OperatorUin uint32 5 | OperatorUID string 6 | OperatorTime uint64 7 | CanRemove bool 8 | Message *GroupMessage 9 | } 10 | -------------------------------------------------------------------------------- /message/multi.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "encoding/xml" 5 | ) 6 | 7 | type ForwardNode struct { 8 | GroupID uint32 9 | SenderID uint32 10 | SenderName string 11 | Time uint32 12 | Message []IMessageElement 13 | } 14 | 15 | type ( 16 | MultiMsgLightApp struct { 17 | App string `json:"app"` 18 | Config Config `json:"config"` 19 | Desc string `json:"desc"` 20 | Extra string `json:"extra"` 21 | Meta Meta `json:"meta"` 22 | Prompt string `json:"prompt"` 23 | Ver string `json:"ver"` 24 | View string `json:"view"` 25 | } 26 | 27 | MultiMsgLightAppExtra struct { 28 | FileName string `json:"filename"` 29 | Sum int `json:"tsum"` 30 | } 31 | 32 | Config struct { 33 | Autosize int64 `json:"autosize"` 34 | Forward int64 `json:"forward"` 35 | Round int64 `json:"round"` 36 | Type string `json:"type"` 37 | Width int64 `json:"width"` 38 | } 39 | 40 | Meta struct { 41 | Detail Detail `json:"detail"` 42 | } 43 | 44 | Detail struct { 45 | News []News `json:"news"` 46 | Resid string `json:"resid"` 47 | Source string `json:"source"` 48 | Summary string `json:"summary"` 49 | UniSeq string `json:"uniseq"` 50 | } 51 | 52 | News struct { 53 | Text string `json:"text"` 54 | } 55 | ) 56 | 57 | type ( 58 | MultiMessage struct { 59 | XMLName xml.Name `xml:"msg"` 60 | ServiceID uint `xml:"serviceID,attr"` 61 | TemplateID int `xml:"templateID,attr"` 62 | Action string `xml:"action,attr"` 63 | Brief string `xml:"brief,attr"` 64 | FileName string `xml:"m_fileName,attr"` 65 | ResID string `xml:"m_resid,attr"` 66 | Total int `xml:"tSum,attr"` 67 | Flag int `xml:"flag,attr"` 68 | Item MultiItem `xml:"item"` 69 | Source MultiSource `xml:"source"` 70 | } 71 | 72 | MultiItem struct { 73 | Layout int `xml:"layout,attr"` 74 | Title []MultiTitle `xml:"title"` 75 | Summary MultiSummary `xml:"summary"` 76 | } 77 | 78 | MultiTitle struct { 79 | Color string `xml:"color,attr"` 80 | Size int `xml:"size,attr"` 81 | Text string `xml:",chardata"` 82 | } 83 | 84 | MultiSummary struct { 85 | Color string `xml:"color,attr"` 86 | Text string `xml:",chardata"` 87 | } 88 | 89 | MultiSource struct { 90 | Name string `xml:"name,attr"` 91 | } 92 | ) 93 | -------------------------------------------------------------------------------- /message/source.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/message/source.go 4 | 5 | type SourceType byte 6 | 7 | // MessageSourceType 常量 8 | const ( 9 | SourcePrivate SourceType = 1 << iota 10 | SourceGroup SourceType = 1 << iota 11 | ) 12 | 13 | func (t SourceType) String() string { 14 | switch t { 15 | case SourcePrivate: 16 | return "私聊" 17 | case SourceGroup: 18 | return "群聊" 19 | default: 20 | return "unknown" 21 | } 22 | } 23 | 24 | // Source 消息来源 25 | type Source struct { 26 | SourceType SourceType 27 | PrimaryID int64 // 群号/QQ号/guild_id 28 | } 29 | -------------------------------------------------------------------------------- /utils/audio/info.go: -------------------------------------------------------------------------------- 1 | package audio 2 | 3 | // https://github.com/LagrangeDev/lagrange-python/tree/broken/lagrange/utils/audio 4 | 5 | import ( 6 | binary2 "encoding/binary" 7 | "errors" 8 | "fmt" 9 | "io" 10 | "strings" 11 | 12 | "github.com/LagrangeDev/LagrangeGo/utils" 13 | "github.com/LagrangeDev/LagrangeGo/utils/binary" 14 | ) 15 | 16 | type Info struct { 17 | Type Type 18 | Time float32 19 | } 20 | 21 | func decode(r io.ReadSeeker, _f bool) (*Info, error) { 22 | reader := binary.ParseReader(r) 23 | buf := reader.ReadBytes(1) 24 | if utils.B2S(buf) != utils.B2S([]byte{0x23}) { 25 | if !_f { 26 | return decode(r, true) 27 | } 28 | return nil, errors.New("unknown audio type") 29 | } 30 | buf = append(buf, reader.ReadBytes(5)...) 31 | 32 | switch { 33 | case strings.HasPrefix(string(buf), "#!AMR\n"): 34 | return &Info{ 35 | Type: amr, 36 | Time: float32(len(reader.ReadAll())) / 1607.0, 37 | }, nil 38 | case string(buf) == "#!SILK": 39 | ver := reader.ReadBytes(3) 40 | if string(ver) != "_V3" { 41 | return nil, fmt.Errorf("unsupported silk version: %s", utils.B2S(ver)) 42 | } 43 | data := reader.ReadAll() 44 | size := len(data) 45 | 46 | var typ Type 47 | if _f { // txsilk 48 | typ = txSilk 49 | } else { 50 | typ = silkV3 51 | } 52 | 53 | blks := 0 54 | pos := 0 55 | 56 | for pos+2 < size { 57 | length := binary2.LittleEndian.Uint16(data[pos : pos+2]) 58 | if length == 0xFFFF { 59 | break 60 | } 61 | blks++ 62 | pos += int(length) + 2 63 | } 64 | return &Info{ 65 | Type: typ, 66 | Time: float32(blks) * 0.02, 67 | }, nil 68 | default: 69 | return nil, errors.New("unknown audio type") 70 | } 71 | } 72 | 73 | func Decode(r io.ReadSeeker) (*Info, error) { 74 | defer func() { 75 | _, _ = r.Seek(0, io.SeekStart) 76 | }() 77 | _, _ = r.Seek(0, io.SeekStart) 78 | return decode(r, false) 79 | } 80 | -------------------------------------------------------------------------------- /utils/audio/type.go: -------------------------------------------------------------------------------- 1 | package audio 2 | 3 | type Type int 4 | 5 | const ( 6 | amr Type = iota 7 | txSilk 8 | silkV3 9 | ) 10 | -------------------------------------------------------------------------------- /utils/binary/network.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/binary/reader.go 4 | 5 | import ( 6 | "encoding/binary" 7 | "io" 8 | "net" 9 | ) 10 | 11 | type NetworkReader struct { 12 | conn net.Conn 13 | } 14 | 15 | func NewNetworkReader(conn net.Conn) *NetworkReader { 16 | return &NetworkReader{conn: conn} 17 | } 18 | 19 | func (r *NetworkReader) ReadByte() (byte, error) { 20 | buf := make([]byte, 1) 21 | n, err := r.conn.Read(buf) 22 | if err != nil { 23 | return 0, err 24 | } 25 | if n != 1 { 26 | return r.ReadByte() 27 | } 28 | return buf[0], nil 29 | } 30 | 31 | func (r *NetworkReader) ReadBytes(l int) ([]byte, error) { 32 | buf := make([]byte, l) 33 | _, err := io.ReadFull(r.conn, buf) 34 | return buf, err 35 | } 36 | 37 | func (r *NetworkReader) ReadInt32() (int32, error) { 38 | b := make([]byte, 4) 39 | _, err := r.conn.Read(b) 40 | if err != nil { 41 | return 0, err 42 | } 43 | return int32(binary.BigEndian.Uint32(b)), nil 44 | } 45 | -------------------------------------------------------------------------------- /utils/binary/pool.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/binary/pool.go 4 | 5 | import ( 6 | "bytes" 7 | "compress/gzip" 8 | "compress/zlib" 9 | "sync" 10 | 11 | "github.com/fumiama/orbyte" 12 | "github.com/fumiama/orbyte/pbuf" 13 | ) 14 | 15 | var bufferPool = pbuf.NewBufferPool[teacfg]() 16 | 17 | type Builder orbyte.Item[pbuf.UserBuffer[teacfg]] 18 | 19 | // NewBuilder 从池中取出一个 Builder 20 | func NewBuilder(key ...byte) *Builder { 21 | b := bufferPool.NewBuffer(nil) 22 | b.P(func(ub *pbuf.UserBuffer[teacfg]) { 23 | ub.DAT.init(key) 24 | }) 25 | return (*Builder)(b) 26 | } 27 | 28 | var gzipPool = sync.Pool{ 29 | New: func() any { 30 | buf := new(bytes.Buffer) 31 | w := gzip.NewWriter(buf) 32 | return &GzipWriter{ 33 | w: w, 34 | buf: buf, 35 | } 36 | }, 37 | } 38 | 39 | func acquireGzipWriter() *GzipWriter { 40 | ret := gzipPool.Get().(*GzipWriter) 41 | ret.buf.Reset() 42 | ret.w.Reset(ret.buf) 43 | return ret 44 | } 45 | 46 | func releaseGzipWriter(w *GzipWriter) { 47 | // See https://golang.org/issue/23199 48 | const maxSize = 1 << 16 49 | if w.buf.Cap() < maxSize { 50 | w.buf.Reset() 51 | gzipPool.Put(w) 52 | } 53 | } 54 | 55 | type zlibWriter struct { 56 | w *zlib.Writer 57 | buf *bytes.Buffer 58 | } 59 | 60 | var zlibPool = sync.Pool{ 61 | New: func() any { 62 | buf := new(bytes.Buffer) 63 | w := zlib.NewWriter(buf) 64 | return &zlibWriter{ 65 | w: w, 66 | buf: buf, 67 | } 68 | }, 69 | } 70 | 71 | func acquireZlibWriter() *zlibWriter { 72 | ret := zlibPool.Get().(*zlibWriter) 73 | ret.buf.Reset() 74 | ret.w.Reset(ret.buf) 75 | return ret 76 | } 77 | 78 | func releaseZlibWriter(w *zlibWriter) { 79 | // See https://golang.org/issue/23199 80 | const maxSize = 1 << 16 81 | if w.buf.Cap() < maxSize { 82 | w.buf.Reset() 83 | zlibPool.Put(w) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /utils/binary/utils.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/binary/utils.go 4 | 5 | import ( 6 | "bytes" 7 | "compress/gzip" 8 | "compress/zlib" 9 | "encoding/binary" 10 | "net" 11 | ) 12 | 13 | type GzipWriter struct { 14 | w *gzip.Writer 15 | buf *bytes.Buffer 16 | } 17 | 18 | func (w *GzipWriter) Write(p []byte) (int, error) { 19 | return w.w.Write(p) 20 | } 21 | 22 | func (w *GzipWriter) Close() error { 23 | return w.w.Close() 24 | } 25 | 26 | func (w *GzipWriter) Bytes() []byte { 27 | return w.buf.Bytes() 28 | } 29 | 30 | func ZlibUncompress(src []byte) []byte { 31 | b := bytes.NewReader(src) 32 | var out bytes.Buffer 33 | r, _ := zlib.NewReader(b) 34 | defer r.Close() 35 | _, _ = out.ReadFrom(r) 36 | return out.Bytes() 37 | } 38 | 39 | func ZlibCompress(data []byte) []byte { 40 | zw := acquireZlibWriter() 41 | _, _ = zw.w.Write(data) 42 | _ = zw.w.Close() 43 | ret := make([]byte, len(zw.buf.Bytes())) 44 | copy(ret, zw.buf.Bytes()) 45 | releaseZlibWriter(zw) 46 | return ret 47 | } 48 | 49 | func GZipCompress(data []byte) []byte { 50 | gw := acquireGzipWriter() 51 | _, _ = gw.Write(data) 52 | _ = gw.Close() 53 | ret := make([]byte, len(gw.buf.Bytes())) 54 | copy(ret, gw.buf.Bytes()) 55 | releaseGzipWriter(gw) 56 | return ret 57 | } 58 | 59 | func GZipUncompress(src []byte) []byte { 60 | b := bytes.NewReader(src) 61 | var out bytes.Buffer 62 | r, _ := gzip.NewReader(b) 63 | defer r.Close() 64 | _, _ = out.ReadFrom(r) 65 | return out.Bytes() 66 | } 67 | 68 | func UInt32ToIPV4Address(i uint32) string { 69 | ip := net.IP{0, 0, 0, 0} 70 | binary.LittleEndian.PutUint32(ip, i) 71 | return ip.String() 72 | } 73 | -------------------------------------------------------------------------------- /utils/crypto/aes.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | ) 8 | 9 | func AESGCMEncrypt(data []byte, key []byte) ([]byte, error) { 10 | nonce := make([]byte, 12) 11 | if _, err := rand.Read(nonce); err != nil { 12 | return nil, err 13 | } 14 | 15 | block, err := aes.NewCipher(key) 16 | if err != nil { 17 | return nil, err 18 | } 19 | aead, err := cipher.NewGCM(block) 20 | if err != nil { 21 | return nil, err 22 | } 23 | ciphertext := aead.Seal(nil, nonce, data, nil) 24 | 25 | result := make([]byte, len(nonce)+len(ciphertext)) 26 | copy(result[:len(nonce)], nonce) 27 | copy(result[len(nonce):], ciphertext) 28 | 29 | return result, nil 30 | } 31 | 32 | func AESGCMDecrypt(data []byte, key []byte) ([]byte, error) { 33 | nonce := data[:12] 34 | ciphertext := data[12:] 35 | 36 | block, err := aes.NewCipher(key) 37 | if err != nil { 38 | return nil, err 39 | } 40 | aead, err := cipher.NewGCM(block) 41 | if err != nil { 42 | return nil, err 43 | } 44 | plaintext, err := aead.Open(nil, nonce, ciphertext, nil) 45 | if err != nil { 46 | return nil, err 47 | } 48 | 49 | return plaintext, nil 50 | } 51 | -------------------------------------------------------------------------------- /utils/crypto/ecdh/define.go: -------------------------------------------------------------------------------- 1 | package ecdh 2 | 3 | import ( 4 | "encoding/hex" 5 | ) 6 | 7 | var ( 8 | ecdhP256PublicBytes, _ = hex.DecodeString("049D1423332735980EDABE7E9EA451B3395B6F35250DB8FC56F25889F628CBAE3E8E73077914071EEEBC108F4E0170057792BB17AA303AF652313D17C1AC815E79") 9 | // ecdhS192PublicBytes, _ = hex.DecodeString("04928D8850673088B343264E0C6BACB8496D697799F37211DEB25BB73906CB089FEA9639B4E0260498B51A992D50813DA8") 10 | ) 11 | 12 | var ( 13 | p256 = newp256exchanger() 14 | // s192 = news192exchanger() 15 | ) 16 | 17 | /* 18 | 19 | func S192() Exchanger { 20 | return s192 21 | } 22 | 23 | */ 24 | 25 | func P256() Exchanger { 26 | return p256 27 | } 28 | -------------------------------------------------------------------------------- /utils/crypto/ecdh/impl.go: -------------------------------------------------------------------------------- 1 | package ecdh 2 | 3 | import ( 4 | "crypto/ecdh" 5 | "crypto/rand" 6 | ) 7 | 8 | type Exchanger interface { 9 | PublicKey() []byte 10 | SharedKey() []byte 11 | Exange(remote []byte) ([]byte, error) 12 | } 13 | 14 | /* 15 | 16 | type s192exchanger struct { 17 | provider *provider 18 | publicKey []byte 19 | sharedKey []byte 20 | compressKey bool 21 | } 22 | 23 | func (e *s192exchanger) PublicKey() []byte { 24 | return e.publicKey 25 | } 26 | 27 | func (e *s192exchanger) SharedKey() []byte { 28 | return e.sharedKey 29 | } 30 | 31 | func (e *s192exchanger) Exange(newKey []byte) ([]byte, error) { 32 | return e.provider.keyExchange(newKey, e.compressKey) 33 | } 34 | 35 | func news192exchanger() *s192exchanger { 36 | p, err := newProvider(newS192Curve()) 37 | if err != nil { 38 | panic(err) 39 | } 40 | shk, err := p.keyExchange(ecdhS192PublicBytes, true) 41 | if err != nil { 42 | panic(err) 43 | } 44 | return &s192exchanger{ 45 | provider: p, 46 | publicKey: p.packPublic(true), 47 | sharedKey: shk, 48 | compressKey: true, 49 | } 50 | } 51 | 52 | */ 53 | 54 | type p256exchanger struct { 55 | privateKey *ecdh.PrivateKey 56 | shareKey []byte 57 | } 58 | 59 | func (e *p256exchanger) PublicKey() []byte { 60 | return e.privateKey.PublicKey().Bytes() 61 | } 62 | 63 | func (e *p256exchanger) SharedKey() []byte { 64 | return e.shareKey 65 | } 66 | 67 | func (e *p256exchanger) Exange(remote []byte) ([]byte, error) { 68 | rk, err := e.privateKey.Curve().NewPublicKey(remote) 69 | if err != nil { 70 | return nil, err 71 | } 72 | return e.privateKey.ECDH(rk) 73 | } 74 | 75 | func newp256exchanger() *p256exchanger { 76 | p256 := ecdh.P256() 77 | privateKey, err := p256.GenerateKey(rand.Reader) 78 | if err != nil { 79 | panic(err) 80 | } 81 | pk, err := p256.NewPublicKey(ecdhP256PublicBytes) 82 | if err != nil { 83 | panic(err) 84 | } 85 | shk, err := privateKey.ECDH(pk) 86 | if err != nil { 87 | panic(err) 88 | } 89 | return &p256exchanger{ 90 | privateKey: privateKey, 91 | shareKey: shk, 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /utils/crypto/ecdh/point.go: -------------------------------------------------------------------------------- 1 | package ecdh 2 | 3 | /* 4 | 5 | import "math/big" 6 | 7 | type ep struct { 8 | x, y *big.Int 9 | } 10 | 11 | func newEllipticPoint(x, y *big.Int) *ep { 12 | return &ep{x: x, y: y} 13 | } 14 | 15 | func (p *ep) Equals(other *ep) bool { 16 | // return p.x == other.x && p.y == other.y 17 | return (p.x.Cmp(other.x) == 0) && (p.y.Cmp(other.y) == 0) 18 | } 19 | 20 | func (p *ep) Negate() *ep { 21 | // return &EllipticPoint{-p.x, -p.y} 22 | return &ep{ 23 | x: new(big.Int).Neg(p.x), 24 | y: new(big.Int).Neg(p.y), 25 | } 26 | } 27 | 28 | func (p *ep) IsDefault() bool { 29 | // return p.x == 0 && p.y == 0 30 | return (p.x.Cmp(big.NewInt(0)) == 0) && (p.y.Cmp(big.NewInt(0)) == 0) 31 | } 32 | 33 | */ 34 | -------------------------------------------------------------------------------- /utils/crypto/rand.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import "crypto/rand" 4 | 5 | func RandomBytes(size int) []byte { 6 | b := make([]byte, size) 7 | _, _ = rand.Read(b) 8 | return b 9 | } 10 | -------------------------------------------------------------------------------- /utils/crypto/rand_1.21.go: -------------------------------------------------------------------------------- 1 | //go:build !go1.22 2 | 3 | package crypto 4 | 5 | import ( 6 | _ "unsafe" // required by go:linkname 7 | ) 8 | 9 | // randuint32 returns a lock free uint32 value. 10 | // 11 | // Too much legacy code has go:linkname references 12 | // to runtime.fastrand and friends, so keep these around for now. 13 | // Code should migrate to math/rand/v2.Uint64, 14 | // which is just as fast, but that's only available in Go 1.22+. 15 | // It would be reasonable to remove these in Go 1.24. 16 | // Do not call these from package runtime. 17 | // 18 | //go:linkname randuint32 runtime.fastrand 19 | func randuint32() uint32 20 | 21 | func RandU32() uint32 { 22 | return randuint32() 23 | } 24 | -------------------------------------------------------------------------------- /utils/crypto/rand_1.22.go: -------------------------------------------------------------------------------- 1 | //go:build go1.22 2 | 3 | package crypto 4 | 5 | import ( 6 | "math/rand/v2" 7 | ) 8 | 9 | func RandU32() uint32 { 10 | return rand.Uint32() 11 | } 12 | -------------------------------------------------------------------------------- /utils/img.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | 7 | "github.com/fumiama/imgsz" 8 | ) 9 | 10 | var ( 11 | ErrImageDataTooShort = errors.New("image data is too short") 12 | ) 13 | 14 | type ImageFormat uint32 15 | 16 | const ( 17 | Unknown ImageFormat = 0000 18 | Jpeg ImageFormat = 1000 19 | Png ImageFormat = 1001 20 | Gif ImageFormat = 2000 21 | Webp ImageFormat = 1002 22 | Bmp ImageFormat = 1005 23 | Tiff ImageFormat = 1006 24 | ) 25 | 26 | var formatmap = map[string]ImageFormat{ 27 | "jpeg": Jpeg, 28 | "png": Png, 29 | "gif": Gif, 30 | "webp": Webp, 31 | "bmp": Bmp, 32 | "tiff": Tiff, 33 | } 34 | 35 | func (format ImageFormat) String() string { 36 | //nolint 37 | switch format { 38 | case Jpeg: 39 | return "jpg" 40 | case Png: 41 | return "png" 42 | case Gif: 43 | return "gif" 44 | case Webp: 45 | return "webp" 46 | case Bmp: 47 | return "bmp" 48 | case Tiff: 49 | return "tiff" 50 | default: 51 | return "unknown" 52 | } 53 | } 54 | 55 | func ImageResolve(image io.ReadSeeker) (format ImageFormat, size imgsz.Size, err error) { 56 | defer func(image io.ReadSeeker, offset int64, whence int) { 57 | _, _ = image.Seek(offset, whence) 58 | }(image, 0, io.SeekStart) 59 | if _, err = image.Seek(10, io.SeekStart); err != nil { // 最小长度检查 60 | err = ErrImageDataTooShort 61 | return 62 | } 63 | _, _ = image.Seek(0, io.SeekStart) 64 | sz, fmts, err := imgsz.DecodeSize(image) 65 | if err != nil { 66 | return 67 | } 68 | 69 | return formatmap[fmts], sz, nil 70 | } 71 | -------------------------------------------------------------------------------- /utils/log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "runtime" 5 | "strings" 6 | ) 7 | 8 | type Logger interface { 9 | Info(format string, args ...any) 10 | Warning(format string, args ...any) 11 | Error(format string, args ...any) 12 | Debug(format string, args ...any) 13 | Dump(dumped []byte, format string, args ...any) 14 | } 15 | 16 | func Getcaller(msg string) string { 17 | pc, _, _, ok := runtime.Caller(2) 18 | if !ok { 19 | return "[unkcal] " + msg 20 | } 21 | fp := runtime.FuncForPC(pc) 22 | sb := strings.Builder{} 23 | sb.WriteByte('[') 24 | if fp == nil { 25 | sb.WriteString(" unkfun]") 26 | sb.WriteString(msg) 27 | return sb.String() 28 | } 29 | n := fp.Name() 30 | i := strings.LastIndex(n, "/") 31 | if i > 0 && i < len(n) { 32 | n = n[i+1:] 33 | } 34 | sb.WriteString(n) 35 | sb.WriteString("] ") 36 | sb.WriteString(msg) 37 | return sb.String() 38 | } 39 | -------------------------------------------------------------------------------- /utils/operator.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "bufio" 5 | "crypto/rand" 6 | "fmt" 7 | "io" 8 | "os" 9 | "strings" 10 | ) 11 | 12 | func ReadLine() string { 13 | inputReader := bufio.NewReader(os.Stdin) 14 | rs, err := inputReader.ReadString('\n') 15 | if err != nil { 16 | return "" 17 | } 18 | return strings.TrimSpace(rs) 19 | } 20 | 21 | func Bool2Int(v bool) int { 22 | if v { 23 | return 1 24 | } 25 | return 0 26 | } 27 | 28 | func CloseIO(reader io.Reader) { 29 | if closer, ok := reader.(io.Closer); ok { 30 | _ = closer.Close() 31 | } 32 | } 33 | 34 | func NewUUID() string { 35 | u := make([]byte, 16) 36 | _, err := io.ReadFull(rand.Reader, u) 37 | if err != nil { 38 | return "" 39 | } 40 | 41 | // Set the version to 4 (randomly generated UUID) 42 | u[6] = (u[6] & 0x0f) | 0x40 43 | // Set the variant to RFC 4122 44 | u[8] = (u[8] & 0x3f) | 0x80 45 | 46 | return fmt.Sprintf("%08x-%04x-%04x-%04x-%12x", u[0:4], u[4:6], u[6:8], u[8:10], u[10:]) 47 | } 48 | 49 | func Ternary[T any](condition bool, trueValue, falseValue T) T { 50 | if condition { 51 | return trueValue 52 | } 53 | return falseValue 54 | } 55 | 56 | func LazyTernary[T any](condition bool, trueFunc, falseFunc func() T) T { 57 | if condition { 58 | return trueFunc() 59 | } 60 | return falseFunc() 61 | } 62 | 63 | func Map[T any, U any](list []T, mapper func(T) U) []U { 64 | result := make([]U, len(list)) 65 | for i, v := range list { 66 | result[i] = mapper(v) 67 | } 68 | return result 69 | } 70 | -------------------------------------------------------------------------------- /utils/platform/platform.go: -------------------------------------------------------------------------------- 1 | package platform 2 | 3 | import "runtime" 4 | 5 | func System() string { 6 | return runtime.GOOS 7 | } 8 | 9 | func Version() string { 10 | return runtime.GOARCH 11 | } 12 | -------------------------------------------------------------------------------- /utils/string.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | // from https://github.com/Mrs4s/MiraiGo/blob/master/utils/string.go 4 | 5 | import ( 6 | "crypto/rand" 7 | "encoding/hex" 8 | "fmt" 9 | "sync" 10 | "unsafe" 11 | ) 12 | 13 | // B2S converts byte slice to a string without memory allocation. 14 | func B2S(b []byte) string { 15 | size := len(b) 16 | if size == 0 { 17 | return "" 18 | } 19 | return unsafe.String(&b[0], size) 20 | } 21 | 22 | // S2B converts string to a byte slice without memory allocation. 23 | // 24 | // Note it may break if string and/or slice header will change 25 | // in the future go versions. 26 | func S2B(s string) (b []byte) { 27 | return unsafe.Slice(unsafe.StringData(s), len(s)) 28 | } 29 | 30 | func MustParseHexStr(s string) []byte { 31 | result, err := hex.DecodeString(s) 32 | if err != nil { 33 | panic(err) 34 | } 35 | return result 36 | } 37 | 38 | func NewTrace() string { 39 | randomBytes := make([]byte, 16+8) 40 | 41 | if _, err := rand.Read(randomBytes); err != nil { 42 | return "" 43 | } 44 | 45 | trace := fmt.Sprintf("00-%x-%x-01", randomBytes[:16], randomBytes[16:]) 46 | return trace 47 | } 48 | 49 | // String Interning is a technique for reducing the memory footprint of large 50 | // strings. It can re-use strings that are already in memory. 51 | 52 | type StringInterner struct { 53 | mu sync.RWMutex 54 | strings map[string]string 55 | } 56 | 57 | func NewStringInterner() *StringInterner { 58 | return &StringInterner{ 59 | strings: make(map[string]string), 60 | } 61 | } 62 | 63 | func (i *StringInterner) Intern(s string) string { 64 | i.mu.RLock() 65 | if v, ok := i.strings[s]; ok { 66 | i.mu.RUnlock() 67 | return v 68 | } 69 | i.mu.RUnlock() 70 | i.mu.Lock() 71 | i.strings[s] = s 72 | i.mu.Unlock() 73 | return s 74 | } 75 | -------------------------------------------------------------------------------- /utils/tcping.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "net" 5 | "time" 6 | ) 7 | 8 | // ref https://github.com/Mrs4s/MiraiGo/blob/54bdd873e3fed9fe1c944918924674dacec5ac76/utils/tcping.go 9 | 10 | type ICMPPingResult struct { 11 | PacketsSent int 12 | PacketsLoss int 13 | AvgTimeMill int64 14 | } 15 | 16 | // RunTCPPingLoop 使用 tcp 进行 ping 17 | func RunTCPPingLoop(ipport string, count int) (r ICMPPingResult) { 18 | r = ICMPPingResult{ 19 | PacketsSent: count, 20 | PacketsLoss: count, 21 | AvgTimeMill: 9999, 22 | } 23 | if count <= 0 { 24 | return 25 | } 26 | durs := make([]int64, 0, count) 27 | for i := 0; i < count; i++ { 28 | d, err := tcping(ipport) 29 | if err == nil { 30 | r.PacketsLoss-- 31 | durs = append(durs, d) 32 | } 33 | time.Sleep(time.Millisecond * 100) 34 | } 35 | 36 | if len(durs) > 0 { 37 | r.AvgTimeMill = 0 38 | for _, d := range durs { 39 | r.AvgTimeMill += d 40 | } 41 | if len(durs) > 1 { 42 | r.AvgTimeMill /= int64(len(durs)) 43 | } 44 | } 45 | 46 | return 47 | } 48 | 49 | func tcping(ipport string) (int64, error) { 50 | t := time.Now().UnixMilli() 51 | conn, err := net.DialTimeout("tcp", ipport, time.Second*10) 52 | if err != nil { 53 | return 9999, err 54 | } 55 | _ = conn.Close() 56 | return time.Now().UnixMilli() - t, nil 57 | } 58 | -------------------------------------------------------------------------------- /utils/time.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func TimeStamp() int64 { 9 | return time.Now().Unix() 10 | } 11 | 12 | func UinTimestamp(uin uint32) string { 13 | currentTime := time.Now() 14 | formattedTime := currentTime.Format("0102150405") 15 | milliseconds := currentTime.Nanosecond() / 1000000 16 | return fmt.Sprintf("%d_%s%02d_%d", uin, formattedTime, currentTime.Year()%100, milliseconds) 17 | } 18 | --------------------------------------------------------------------------------