├── docs ├── request │ ├── web.md │ ├── development.md │ ├── common.md │ ├── core.md │ ├── req_active.md │ ├── authentication.md │ ├── request.md │ ├── group_file.md │ ├── req_passive.md │ ├── friend.md │ ├── message.md │ ├── group.md │ └── guild.md ├── event │ ├── core.md │ ├── request.md │ ├── notice.md │ ├── event.md │ └── msg.md └── README.md ├── protos ├── reverse │ └── reverse.proto ├── developer │ ├── customization.proto │ ├── qsign.proto │ └── developer.proto ├── event │ ├── event_request.proto │ ├── request_data.proto │ ├── event.proto │ ├── event_notice.proto │ └── notice_data.proto ├── common │ ├── request.proto │ ├── contact.proto │ ├── message_data.proto │ └── message_element.proto ├── file │ ├── file_data.proto │ └── group_file.proto ├── process │ └── process.proto ├── web │ └── web.proto ├── friend │ ├── firend_data.proto │ └── friend.proto ├── core │ └── core.proto ├── group │ ├── group_data.proto │ └── group.proto ├── auth │ └── authentication.proto ├── guild │ ├── guild_data.proto │ └── guild.proto └── message │ └── message.proto └── README.md /docs/request/web.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /docs/event/core.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Kritor核心事件 -------------------------------------------------------------------------------- /docs/event/request.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 请求事件 6 | 7 | 用于上报QQ的好友申请,加群申请,诸如此类。 8 | 9 | ## 事件类型 10 | 11 | ```protobuf 12 | enum RequestType { 13 | UNKNOWN = 0; // 保留字段, UNSPECIFIED 14 | 15 | FRIEND_APPLY = 10; 16 | GROUP_APPLY = 11; 17 | INVITED_GROUP = 12; 18 | } 19 | ``` 20 | 21 | 详细的事件内容请参考[通知事件内容](/protos/src/main/proto/kritor/event/comm_request.proto)。 22 | -------------------------------------------------------------------------------- /protos/reverse/reverse.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.reverse; 10 | 11 | option csharp_namespace = "Kritor.Reverse"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.reverse"; 14 | option go_package = "grpc/kritor/reverse"; 15 | 16 | import "common/request.proto"; 17 | 18 | service ReverseService { 19 | rpc ReverseStream(stream kritor.common.Response) returns (stream kritor.common.Request); 20 | } -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Kritor文档 6 | 7 | Kritor使用Grpc强力驱动,提供了多种语言的客户端示例。 8 | 9 | ## 连接方式 10 | 11 | - [主动RPC](/docs/request/req_active.md): Kritor作为Server,客户端(Bot)作为Client连接。**(推荐)** 12 | - [被动RPC](/docs/request/req_passive.md): Kritor作为Client,客户端(Bot)作为Server连接。 13 | 14 | ## 请求 15 | 16 | Kritor可使用(支持)请求的列表及格式分析。 17 | 18 | ----> [点我前往](/docs/request/request.md) 19 | 20 | ## 事件 21 | 22 | Kritor可使用(支持)事件的列表及格式分析。 23 | 24 | ----> [点我前往](/docs/event/event.md) 25 | -------------------------------------------------------------------------------- /protos/developer/customization.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.customization; 10 | 11 | option csharp_namespace = "Kritor.Customization"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.customization"; 14 | option go_package = "grpc/kritor/customization"; 15 | 16 | import "common/request.proto"; 17 | 18 | /* 自定义功能接口 */ 19 | 20 | service CustomizationService { 21 | rpc CallFunction(kritor.common.Request) returns (kritor.common.Response); 22 | } -------------------------------------------------------------------------------- /protos/event/event_request.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.event; 10 | 11 | option csharp_namespace = "Kritor.Event"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.event"; 14 | option go_package = "grpc/kritor/event"; 15 | 16 | import "event/request_data.proto"; 17 | 18 | message RequestEvent { 19 | enum RequestType { 20 | UNKNOWN = 0; // 保留字段, UNSPECIFIED 21 | 22 | FRIEND_APPLY = 10; 23 | GROUP_APPLY = 11; 24 | INVITED_GROUP = 12; 25 | } 26 | 27 | RequestType type = 1; 28 | uint64 time = 2; 29 | string request_id = 3; 30 | 31 | oneof request { 32 | FriendApplyRequest friend_apply = 10; 33 | GroupApplyRequest group_apply = 11; 34 | InvitedJoinGroupRequest invited_group = 12; 35 | } 36 | } -------------------------------------------------------------------------------- /protos/event/request_data.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.event; 10 | 11 | option csharp_namespace = "Kritor.Event"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.event"; 14 | option go_package = "grpc/kritor/event"; 15 | 16 | message FriendApplyRequest { 17 | optional string applier_uid = 1; 18 | uint64 applier_uin = 2; 19 | string message = 3; 20 | } 21 | 22 | message GroupApplyRequest { 23 | uint64 group_id = 1; 24 | optional string applier_uid = 2; 25 | uint64 applier_uin = 3; 26 | optional string inviter_uid = 4; 27 | optional uint64 inviter_uin = 5; 28 | string reason = 6; 29 | } 30 | 31 | message InvitedJoinGroupRequest { 32 | uint64 group_id = 1; 33 | optional string inviter_uid = 2; 34 | uint64 inviter_uin = 3; 35 | } -------------------------------------------------------------------------------- /protos/common/request.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.common; 10 | 11 | option csharp_namespace = "Kritor.Common"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.common"; 14 | option go_package = "grpc/kritor/common"; 15 | 16 | message Request { 17 | string cmd = 1; // command, such as "android.get_external_storage_path" 18 | uint32 seq = 2; 19 | bytes buf = 3; 20 | bool no_response = 4; // no response 21 | } 22 | 23 | message Response { 24 | enum ResponseCode { 25 | UNSPECIFIED = 0; 26 | SUCCESS = 1; 27 | INVALID_ARGUMENT = 2; 28 | INTERNAL = 3; 29 | UNAUTHENTICATED = 4; 30 | PERMISSION_DENIED = 5; 31 | } 32 | 33 | string cmd = 1; 34 | uint32 seq = 2; 35 | ResponseCode code = 3; 36 | optional string msg = 4; 37 | bytes buf = 5; 38 | } -------------------------------------------------------------------------------- /protos/file/file_data.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.file; 10 | 11 | option csharp_namespace = "Kritor.File"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.file"; 14 | option go_package = "grpc/kritor/file"; 15 | 16 | message File { 17 | string file_id = 1; 18 | string file_name = 2; 19 | uint64 file_size = 3; 20 | int32 bus_id = 4; 21 | uint64 upload_time = 5; 22 | uint64 expire_time = 6; 23 | uint64 modify_time = 7; 24 | uint32 download_times = 8; 25 | uint64 uploader = 9; 26 | string uploader_name = 10; 27 | string sha = 11; 28 | string sha3 = 12; 29 | string md5 = 13; 30 | } 31 | 32 | message Folder { 33 | string folder_id = 1; 34 | string folder_name = 2; 35 | uint32 total_file_count = 3; 36 | uint64 create_time = 4; 37 | uint64 creator = 5; 38 | string creator_name = 6; 39 | } 40 | -------------------------------------------------------------------------------- /docs/request/development.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Kritor扩展服务 6 | 7 | 由Kritor端提供的几个扩展功能。 8 | 9 | ## 基础信息 10 | 11 | - **服务名**: `DeveloperService` 12 | - **Java包名**: `io.kritor.core` 13 | - **C#命名空间**: `Kritor.Core` 14 | - **[source proto file](/protos/src/main/proto/kritor/core/core.proto)** 15 | 16 | ## 清理缓存 17 | 18 | 清理Kritor的缓存。 19 | 20 | ### 参数 21 | 22 | - **方法名**: `ClearCache` 23 | - **请求类型**: `ClearCacheRequest` 24 | - **响应类型**: `ClearCacheResponse` 25 | 26 | ### 请求与响应 27 | 28 | ```protobuf 29 | message ClearCacheRequest {} 30 | 31 | message ClearCacheResponse {} 32 | ``` 33 | 34 | ## 获取设备电池状态 35 | 36 | 获取设备电池状态。 37 | 38 | ### 参数 39 | 40 | - **方法名**: `GetDeviceBattery` 41 | - **请求类型**: `GetDeviceBatteryRequest` 42 | - **响应类型**: `GetDeviceBatteryResponse` 43 | 44 | ### 请求与响应 45 | 46 | ```protobuf 47 | message GetDeviceBatteryRequest {} 48 | 49 | message GetDeviceBatteryResponse { 50 | uint32 battery = 1; // 设备电量 51 | uint32 scale = 2; 52 | uint32 status = 3; 53 | } 54 | ``` -------------------------------------------------------------------------------- /docs/event/notice.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 通知事件 6 | 7 | 用于上报QQ的撤回事件,禁言事件,诸如此类。 8 | 9 | ## 事件类型 10 | 11 | ```protobuf 12 | enum NoticeType { 13 | UNKNOWN = 0; // 保留字段, UNSPECIFIED 14 | 15 | PRIVATE_POKE = 10; // 私聊头像戳一戳 16 | PRIVATE_RECALL = 11; // 私聊消息撤回 17 | PRIVATE_FILE_UPLOADED = 12; // 私聊文件上传 18 | 19 | GROUP_POKE = 20; // 群头像戳一戳 20 | GROUP_RECALL = 21; // 群消息撤回 21 | GROUP_FILE_UPLOADED = 22; // 群文件上传 22 | GROUP_CARD_CHANGED = 23; // 群名片改变 23 | GROUP_MEMBER_UNIQUE_TITLE_CHANGED = 24; // 群成员专属头衔改变 24 | GROUP_ESSENCE_CHANGED = 25; // 群精华消息改变 25 | GROUP_MEMBER_INCREASE = 26; // 群成员增加 26 | GROUP_MEMBER_DECREASE = 27; // 群成员减少 27 | GROUP_ADMIN_CHANGED = 28; // 群管理员变动 28 | GROUP_SIGN_IN = 29; // 群签到 29 | GROUP_MEMBER_BAN = 30; // 群成员被禁言 30 | GROUP_WHOLE_BAN = 31; // 群全员禁言 31 | GROUP_REACT_MESSAGE_WITH_EMOJI = 32; // 群消息被表情回应 32 | GROUP_TRANSFER = 33; // 群转让 33 | 34 | FRIEND_INCREASE = 40; // 好友增加 35 | FRIEND_DECREASE = 41; // 好友减少 36 | } 37 | ``` 38 | 39 | 详细的事件内容请参考[通知事件内容](/protos/src/main/proto/kritor/event/comm_notice.proto)。 -------------------------------------------------------------------------------- /docs/event/event.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 事件推送 6 | 7 | Kritor的事件推送由于基于grpc,所以说主动RPC和被动RPC,有不同的消息监听写法。 8 | 9 | ## 事件监听示例 10 | 11 | ### 主动RPC 12 | 13 | 接下来将举例一段代码,来说明如何使用主动RPC去实现事件监听。 14 | 15 | ```kotlin 16 | val channel = ManagedChannelBuilder 17 | .forAddress("localhost", 8080) 18 | .usePlaintext() 19 | .enableRetry() // 允许尝试 20 | .executor(Dispatchers.IO.asExecutor()) // 使用协程的调度器 21 | .build() 22 | 23 | EventServiceGrpcKt.EventServiceCoroutineStub(channel).registerActiveListener(requestPushEvent { 24 | type = EventType.EVENT_TYPE_MESSAGE // 声明需要监听的是消息事件 25 | }).collect { 26 | // 这里处理消息事件 27 | } 28 | ``` 29 | 30 | 需要注意的是,这里的`EventServiceGrpcKt.EventServiceCoroutineStub`是一个自动生成的类,它是由`proto`文件生成的。 31 | 32 | **如果您开启了鉴权,请在监听的时候提供正确的鉴权`ticket`**! 33 | 34 | ### 被动RPC 35 | 36 | 被动Grpc比较复杂,其实更需要一个框架去封装它,[点我查看示例](/src/test/kotlin/passive/Server.kt)。 37 | 38 | ## 事件大全 39 | 40 | > - ### [核心事件](/docs/event/core.md) 41 | > 42 | > - ### [消息事件](/docs/event/msg.md) 43 | > 44 | > - ### [通知事件](/docs/event/notice.md) 45 | > 46 | > - ### [请求事件](/docs/event/request.md) -------------------------------------------------------------------------------- /protos/event/event.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.event; 10 | 11 | option csharp_namespace = "Kritor.Event"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.event"; 14 | option go_package = "grpc/kritor/event"; 15 | 16 | import "common/message_data.proto"; 17 | import "event/event_notice.proto"; 18 | import "event/event_request.proto"; 19 | 20 | service EventService { 21 | rpc RegisterActiveListener(RequestPushEvent) returns (stream EventStructure); // 主动RPC推送器 22 | rpc RegisterPassiveListener(stream EventStructure) returns (RequestPushEvent); // 被动RPC监听器 23 | } 24 | 25 | enum EventType { 26 | UNSPECIFIED = 0; 27 | EVENT_TYPE_CORE_EVENT = 1; 28 | EVENT_TYPE_MESSAGE = 2; 29 | EVENT_TYPE_NOTICE = 3; 30 | EVENT_TYPE_REQUEST = 4; 31 | } 32 | 33 | message RequestPushEvent { 34 | EventType type = 1; 35 | } 36 | 37 | message EventStructure { 38 | EventType type = 1; 39 | oneof event { 40 | kritor.common.PushMessageBody message = 2; 41 | RequestEvent request = 3; 42 | NoticeEvent notice = 4; 43 | } 44 | } -------------------------------------------------------------------------------- /protos/developer/qsign.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.developer; 10 | 11 | option csharp_namespace = "Kritor.Developer"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.developer"; 14 | option go_package = "grpc/kritor/developer"; 15 | 16 | service QsignService { 17 | rpc Sign(SignRequest) returns (SignResponse); 18 | rpc Energy(EnergyRequest) returns (EnergyResponse); 19 | rpc GetCmdWhitelist(GetCmdWhitelistRequest) returns (GetCmdWhitelistResponse); 20 | } 21 | 22 | message SignRequest { 23 | string uin = 1; 24 | string command = 2; 25 | uint32 seq = 3; 26 | bytes buffer = 4; 27 | optional string qua = 6; 28 | } 29 | 30 | message SignResponse { 31 | bytes sec_sig = 1; 32 | bytes sec_device_token = 2; 33 | bytes sec_extra = 3; 34 | } 35 | 36 | message EnergyRequest { 37 | string data = 2; 38 | bytes salt = 3; 39 | } 40 | 41 | message EnergyResponse { 42 | bytes result = 1; 43 | } 44 | 45 | message GetCmdWhitelistRequest { 46 | } 47 | 48 | message GetCmdWhitelistResponse { 49 | repeated string commands = 1; 50 | } -------------------------------------------------------------------------------- /docs/request/common.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 消息接口服务 6 | 7 | 提供发消息,获取消息相关的服务。 8 | 9 | ## 基础信息 10 | 11 | - **Java包名**: `io.kritor.common` 12 | - **C#命名空间**: `Kritor.Common` 13 | - **[source proto file](/protos/src/main/proto/kritor/message/message.proto)** 14 | 15 | ## 基础定义 16 | 17 | ```protobuf 18 | enum Scene { 19 | GROUP = 0; // 群聊 20 | FRIEND = 1; // 好友 21 | GUILD = 2; // 频道 22 | STRANGER_FROM_GROUP = 10; // 群临时会话 23 | 24 | // 以下类型为可选实现 25 | NEARBY = 5; // 附近的人 26 | STRANGER = 9; // 陌生人 27 | } 28 | 29 | message Contact { 30 | Scene scene = 1; 31 | string peer = 2; // GROUP: group_id, FRIEND|STRANGER_FROM_GROUP|NEARBY|STRANGER: uid, GUILD: guild_id 32 | optional string sub_peer = 3; // GUILD: channel_id, STRANGER_FROM_GROUP: group_id 33 | } 34 | 35 | message Sender { 36 | optional string uid = 1; 37 | uint64 uin = 2; 38 | optional string nick = 3; 39 | } 40 | ``` 41 | 42 | 其中的`scene`表示来自何方的类型,而`peer`则为来自何方,他有以下几种情况: 43 | 44 | - **GROUP**:`peer`为群号。 45 | - **FRIEND**:`peer`为QQ号或者用户`uid`。 46 | - **GUILD**:`peer`为频道号,`sub_peer`为子频道号。 47 | - **NEARBY**:`peer`为QQ号或者用户`tiny_id`。 48 | - **STRANGER**:`peer`为QQ号或者用户`uid`。 49 | - **STRANGER_FROM_GROUP**:`peer`为QQ,`sub_peer`为群号。 50 | -------------------------------------------------------------------------------- /protos/process/process.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.process; 10 | 11 | option csharp_namespace = "Kritor.Process"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.process"; 14 | option go_package = "grpc/kritor/process"; 15 | 16 | service ProcessService { 17 | rpc SetFriendApplyResult(SetFriendApplyResultRequest) returns (SetFriendApplyResultResponse); 18 | rpc SetGroupApplyResult(SetGroupApplyResultRequest) returns (SetGroupApplyResultResponse); 19 | rpc SetInvitedJoinGroupResult(SetInvitedJoinGroupResultRequest) returns (SetInvitedJoinGroupResultResponse); 20 | } 21 | 22 | message SetFriendApplyResultRequest { 23 | string request_id = 1; 24 | bool is_approve = 2; 25 | optional string remark = 3; // 同意时可选 26 | } 27 | 28 | message SetFriendApplyResultResponse { 29 | } 30 | 31 | message SetGroupApplyResultRequest { 32 | string request_id = 1; 33 | bool is_approve = 2; 34 | optional string deny_reason = 3; // 拒绝时可选 35 | } 36 | 37 | message SetGroupApplyResultResponse { 38 | } 39 | 40 | message SetInvitedJoinGroupResultRequest { 41 | string request_id = 1; 42 | bool is_approve = 2; 43 | } 44 | 45 | message SetInvitedJoinGroupResultResponse { 46 | } -------------------------------------------------------------------------------- /protos/common/contact.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.common; 10 | 11 | option csharp_namespace = "Kritor.Common"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.common"; 14 | option go_package = "grpc/kritor/common"; 15 | 16 | enum Scene { 17 | UNSPECIFIED = 0; // 保留字段, UNSPECIFIED 18 | GROUP = 1; // 群聊 19 | FRIEND = 2; // 好友 20 | GUILD = 3; // 频道 21 | STRANGER_FROM_GROUP = 11; // 群临时会话 22 | 23 | // 以下类型为可选实现 24 | NEARBY = 6; // 附近的人 25 | STRANGER = 10; // 陌生人 26 | } 27 | 28 | enum Role { 29 | UNKNOWN = 0; // 未知 30 | MEMBER = 1; // 普通成员 31 | ADMIN = 2; // 管理员 32 | OWNER = 3; // 群主 33 | } 34 | 35 | message Contact { 36 | Scene scene = 1; 37 | string peer = 2; // GROUP: group_id, FRIEND|STRANGER_FROM_GROUP|NEARBY|STRANGER: uix, GUILD: guild_id 38 | optional string sub_peer = 3; // GUILD: channel_id, STRANGER_FROM_GROUP: group_id 39 | } 40 | 41 | message PrivateSender { 42 | optional string uid = 1; 43 | uint64 uin = 2; 44 | string nick = 3; 45 | } 46 | 47 | message GroupSender { 48 | string group_id = 1; 49 | optional string uid = 2; 50 | uint64 uin = 3; 51 | string nick = 4; 52 | } 53 | 54 | message GuildSender { 55 | string guild_id = 1; 56 | string channel_id = 2; 57 | string tiny_id = 3; 58 | string nick = 4; 59 | Role role = 5; 60 | } -------------------------------------------------------------------------------- /protos/common/message_data.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.common; 10 | 11 | option csharp_namespace = "Kritor.Common"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.common"; 14 | option go_package = "grpc/kritor/common"; 15 | 16 | import "common/contact.proto"; 17 | import "common/message_element.proto"; 18 | 19 | message PushMessageBody { 20 | uint64 time = 1; 21 | // 消息 id 22 | // 长度 | 1 | 20 | 20 | 23 | // 内容 | 群聊为 'g' 私聊为 'p' | 群 uin 或好友 uin | 消息 Seq | 24 | string message_id = 2; 25 | uint64 message_seq = 3; 26 | Scene scene = 4; 27 | oneof sender { 28 | PrivateSender private = 5; 29 | GroupSender group = 6; 30 | GuildSender guild = 7; 31 | } 32 | repeated Element elements = 9; // 发的什么东西 33 | } 34 | 35 | message ForwardMessageBody { 36 | oneof forward_message { 37 | string message_id = 1; 38 | PushMessageBody message = 2; 39 | } 40 | } 41 | 42 | message EssenceMessageBody { 43 | uint32 group_id = 1; 44 | optional string sender_uid = 2; 45 | uint64 sender_uin = 3; 46 | string sender_nick = 4; 47 | optional uint64 operator_uid = 5; 48 | uint64 operator_uin = 6; 49 | string operator_nick = 7; 50 | uint64 operation_time = 8; 51 | uint64 message_time = 9; 52 | string message_id = 10; 53 | uint64 message_seq = 11; 54 | string json_elements = 12; 55 | } -------------------------------------------------------------------------------- /protos/web/web.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.web; 10 | 11 | option csharp_namespace = "Kritor.Web"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.web"; 14 | option go_package = "grpc/kritor/web"; 15 | 16 | service WebService { 17 | rpc GetCookies(GetCookiesRequest) returns (GetCookiesResponse); // 获取通用cookie 18 | rpc GetCredentials(GetCredentialsRequest) returns (GetCredentialsResponse); // 获取bkn参数与cookie 19 | rpc GetCSRFToken(GetCSRFTokenRequest) returns (GetCSRFTokenResponse); // 获取bkn 20 | rpc GetHttpCookies(GetHttpCookiesRequest) returns (GetHttpCookiesResponse); // 获取http请求的cookie 21 | } 22 | 23 | message GetCookiesRequest { 24 | optional string domain = 1; // The domain to get cookies from 25 | } 26 | 27 | message GetCookiesResponse { 28 | string cookie = 1; 29 | } 30 | 31 | message GetCredentialsRequest { 32 | optional string domain = 1; // The domain to get credentials from 33 | } 34 | 35 | message GetCredentialsResponse { 36 | string bkn = 1; 37 | string cookie = 2; 38 | } 39 | 40 | message GetCSRFTokenRequest { 41 | optional string domain = 1; // The domain to get the CSRF token from 42 | } 43 | 44 | message GetCSRFTokenResponse { 45 | string bkn = 1; 46 | } 47 | 48 | message GetHttpCookiesRequest { 49 | string appid = 1; 50 | string daid = 2; 51 | string jump_url = 3; 52 | } 53 | 54 | message GetHttpCookiesResponse { 55 | string cookie = 1; 56 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Kritor 6 | 7 | **本项目目前处于开发阶段, 所定义 api 可能会有较大变动** 8 | 9 | 10 | *Kritor*是一个聊天机器人应用接口标准. 11 | 旨在统一腾讯QQ IM平台上的机器人应用开发接口. 12 | 使开发者只需编写一次业务逻辑代码即可应用到多种机器人平台. 13 | 在QQNT中, 协议出现大范围变动, OneBot 的原有定义已经不再适用或过于复杂, 因此我们制定了一套新的定义来满足现在的需要. 14 | 15 | *Kritor*使用[*grpc*](https://grpc.io/)作为通信协议, 16 | 并提供了一套标准的接口定义, 开发者可以使用任何支持grpc的语言进行开发. 17 | 18 | ## 特性 19 | 20 | - **多语言**:支持多种编程语言, 包括Nodejs、Kotlin、C#等 21 | - **标准化**:提供一套标准的接口定义(提供全套`proto`文件), 使开发者只需编写一次业务逻辑代码即可应用到多种机器人平台 22 | - **稳定性**:使用高质量, 低延迟的通信协议, 保证稳定性和性能 23 | 24 | ## 项目结构 25 | 26 | - [docs](./docs): 文档 27 | - [protos](./protos): 接口定义 28 | 29 | ### 注解字段解释 30 | 31 | ```protobuf 32 | extend google.protobuf.MethodOptions { 33 | bool require = 1; // 需要强制实现的服务 34 | string desc = 2; // 服务描述 35 | } 36 | ``` 37 | 38 | ## 使用说明 39 | 40 | ### 主动RPC 41 | 42 | 协议端作为 Server, 插件端作为 Client. 43 | 插件端可以通过构造 Stub 对象来直接对协议端进行请求操作. 44 | 45 | ### 被动RPC 46 | 47 | 协议端作为 Client, 插件端作为 Server. 48 | 因为 Grpc 并没有服务端直接调用客户端的方法, 所以*Kritor*通过双向流来实现插件端对协议端的调用. 49 | 50 | ### 各语言插件示例 51 | 52 | - [Kotlin](https://github.com/KarinJS/kritor-kotlin) 53 | - [TypeScript](https://github.com/KarinJS/kritor-ts) 54 | - [Go](https://github.com/KarinJS/kritor-go) 55 | - [C#](https://github.com/KarinJS/kritor-csharp) 56 | 57 | ## 接入状态 58 | 59 | - [Shamrock](https://github.com/whitechi73/OpenShamrock): **v1.1.0+** 60 | - [Lagrange.Core](https://github.com/LagrangeDev/Lagrange.Core): **0.0.3+** 61 | - [Lagrange.Kritor](https://github.com/LagrangeDev/Lagrange.Kritor): 一个**Kritor**在 C# 的实现. -------------------------------------------------------------------------------- /protos/friend/firend_data.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.friend; 10 | 11 | option csharp_namespace = "Kritor.Friend"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.friend"; 14 | option go_package = "grpc/kritor/friend"; 15 | 16 | message FriendInfo { 17 | optional string uid = 1; // uid 'u_*********' 18 | uint64 uin = 2; // qq 如果没有可不提供 19 | string qid = 3; // qid 用户自定义的qid 如若没有则为空 20 | 21 | string nick = 4; // 名称 22 | string remark = 5; // 备注 23 | optional uint32 level = 6; // 等级 24 | optional uint32 age = 7; // 年龄 25 | optional uint32 vote_cnt = 8; // 赞数量 26 | optional int32 gender = 9; // 性别 27 | int32 friend_group_id = 10; // 好友分组id 28 | 29 | 30 | optional ExtInfo ext = 99; // 扩展信息,根据协议平台提供的扩展信息 31 | } 32 | 33 | message ProfileCard { 34 | optional string uid = 1; 35 | uint64 uin = 2; 36 | string qid = 3; 37 | 38 | string nick = 4; 39 | optional string remark = 5; 40 | uint32 level = 6; 41 | optional uint64 birthday = 7; 42 | uint32 login_day = 8; // 登录天数 43 | uint32 vote_cnt = 9; // 点赞数 44 | 45 | /* 以下字段可以不实现 */ 46 | optional bool is_school_verified = 51; 47 | optional ExtInfo ext = 99; // 扩展信息,根据协议平台提供的扩展信息 48 | } 49 | 50 | // 通用好友信息扩展字段 51 | // 所有第三方协议分发扩展字段, 52 | // 必须基于本字段修改, 53 | // 并保存定制的副本到本仓库特定路径!! 54 | message ExtInfo { 55 | optional bool big_vip = 1; // 大会员 56 | optional bool hollywood_vip = 2; // 好莱坞/腾讯视频会员 57 | optional bool qq_vip = 3; // QQ会员 58 | optional bool super_vip = 4; // QQ超级会员 59 | optional bool voted = 5; // 是否已经赞过 60 | } -------------------------------------------------------------------------------- /protos/core/core.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.core; 10 | 11 | option csharp_namespace = "Kritor.Core"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.core"; 14 | option go_package = "grpc/kritor/core"; 15 | 16 | service CoreService { 17 | rpc GetVersion(GetVersionRequest) returns (GetVersionResponse); // 获取Kritor版本 18 | rpc DownloadFile(DownloadFileRequest) returns (DownloadFileResponse); // 让Kritor下载文件到Kritor本地 19 | 20 | rpc GetCurrentAccount(GetCurrentAccountRequest) returns (GetCurrentAccountResponse); // 获取当前账户信息 21 | rpc SwitchAccount(SwitchAccountRequest) returns (SwitchAccountResponse); // 切换账户 22 | } 23 | 24 | message GetVersionRequest { 25 | } 26 | 27 | message GetVersionResponse { 28 | string version = 1; // Kritor版本 29 | string app_name = 2; 30 | } 31 | 32 | message DownloadFileRequest { 33 | optional string url = 1; // 下载文件的URL 二选一 34 | optional string base64 = 2; // 下载文件的base64 二选一 35 | optional string root_path = 3; // 下载文件的根目录 需要保证Kritor有该目录访问权限 可选 36 | optional string file_name = 4; // 保存的文件名称 默认为文件MD5 可选 37 | optional uint32 thread_cnt = 5; // 下载文件的线程数 默认为3 可选 38 | map headers = 6; // 下载文件的请求头 39 | } 40 | 41 | message DownloadFileResponse { 42 | string file_absolute_path = 1; // 下载文件的绝对路径 43 | string file_md5 = 2; // 下载文件的MD5 44 | } 45 | 46 | message GetCurrentAccountRequest { 47 | } 48 | 49 | message GetCurrentAccountResponse { 50 | optional string account_uid = 1; // 当前账户 51 | uint64 account_uin = 2; 52 | string account_name = 3; // 当前账户名称 53 | } 54 | 55 | message SwitchAccountRequest { 56 | oneof account { 57 | string account_uid = 1; // 切换账户uid 58 | uint64 account_uin = 2; // 切换账户uin 59 | } 60 | string super_ticket = 3; // 凭证 61 | } 62 | 63 | message SwitchAccountResponse { 64 | } -------------------------------------------------------------------------------- /protos/group/group_data.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.group; 10 | 11 | option csharp_namespace = "Kritor.Group"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.group"; 14 | option go_package = "grpc/kritor/group"; 15 | 16 | message GroupInfo { 17 | uint64 group_id = 1; 18 | string group_name = 2; 19 | string group_remark = 3; 20 | uint64 owner = 4; 21 | repeated uint64 admins = 5; 22 | uint32 max_member_count = 6; 23 | uint32 member_count = 7; 24 | uint64 group_uin = 10; 25 | } 26 | 27 | message NotJoinedGroupInfo { 28 | uint64 group_id = 1; 29 | uint32 max_member_count = 2; 30 | uint32 member_count = 3; 31 | string group_name = 4; 32 | string group_desc = 5; 33 | uint64 owner = 6; 34 | uint64 create_time = 7; 35 | 36 | uint32 group_flag = 8; // 群聊类型什么的都在这里,如果获取不到可以不实现 37 | uint32 group_flag_ext = 9; // 扩展群聊类型 38 | } 39 | 40 | message ProhibitedUserInfo { 41 | optional string uid = 1; 42 | uint64 uin = 2; 43 | uint64 prohibited_time = 3; 44 | } 45 | 46 | message GroupHonorInfo { 47 | optional string uid = 1; // 荣誉成员uid 48 | uint64 uin = 2; // 荣誉成员uin 49 | string nick = 3; // 荣誉成员昵称 50 | string honor_name = 4; // 荣誉名称 51 | string avatar = 5; // 荣誉图标url 52 | uint32 id = 6; // 荣誉id 53 | string description = 7; // 荣誉描述 54 | } 55 | 56 | enum MemberRole { 57 | UNSPECIFIED = 0; 58 | ADMIN = 1; 59 | MEMBER = 2; 60 | OWNER = 3; 61 | STRANGER = 4; 62 | } 63 | 64 | message GroupMemberInfo { 65 | optional string uid = 1; 66 | uint64 uin = 2; 67 | string nick = 3; 68 | uint32 age = 4; 69 | string unique_title = 5; 70 | uint64 unique_title_expire_time = 6; 71 | string card = 7; 72 | uint64 join_time = 8; 73 | uint64 last_active_time = 9; 74 | uint32 level = 10; 75 | uint64 shut_up_time = 11; 76 | 77 | optional uint32 distance = 100; 78 | repeated uint32 honors = 101; 79 | optional bool unfriendly = 102; 80 | optional bool card_changeable = 103; 81 | } 82 | 83 | -------------------------------------------------------------------------------- /protos/developer/developer.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.developer; 10 | 11 | option csharp_namespace = "Kritor.Developer"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.developer"; 14 | option go_package = "grpc/kritor/developer"; 15 | 16 | service DeveloperService { 17 | rpc Shell(ShellRequest) returns (ShellResponse); 18 | rpc GetLog(GetLogRequest) returns (GetLogResponse); 19 | rpc ClearCache(ClearCacheRequest) returns (ClearCacheResponse); 20 | rpc GetDeviceBattery(GetDeviceBatteryRequest) returns (GetDeviceBatteryResponse); // 获取设备电量 21 | 22 | rpc UploadImage(UploadImageRequest) returns (UploadImageResponse); 23 | rpc SendPacket(SendPacketRequest) returns (SendPacketResponse); 24 | } 25 | 26 | message ShellRequest { 27 | repeated string command = 1; 28 | string directory = 2; 29 | } 30 | 31 | message ShellResponse { 32 | bool is_success = 1; 33 | string data = 2; 34 | } 35 | 36 | message GetLogRequest { 37 | uint64 start = 1; 38 | bool recent = 2; 39 | } 40 | 41 | message GetLogResponse { 42 | bool is_success = 1; 43 | string log = 2; 44 | } 45 | 46 | message ClearCacheRequest { 47 | } 48 | 49 | message ClearCacheResponse { 50 | } 51 | 52 | message GetDeviceBatteryRequest { 53 | } 54 | 55 | message GetDeviceBatteryResponse { 56 | uint32 battery = 1; // 设备电量 57 | uint32 scale = 2; 58 | uint32 status = 3; 59 | } 60 | 61 | message UploadImageRequest { 62 | oneof data { 63 | bytes file = 1; // 文件内容 64 | string file_name = 2; // 文件文件名 65 | string file_path = 3; // 文件绝对路径 66 | string file_url = 4; // 文件下载地址 67 | } 68 | uint64 group_id = 5; 69 | } 70 | 71 | message UploadImageResponse { 72 | bool is_success = 1; 73 | string image_url = 2; 74 | } 75 | 76 | message SendPacketRequest { 77 | string command = 1; 78 | bytes request_buffer = 2; 79 | bool is_protobuf = 3; 80 | map attrs = 4; 81 | } 82 | 83 | message SendPacketResponse { 84 | bool is_success = 1; 85 | bytes response_buffer = 2; 86 | } -------------------------------------------------------------------------------- /protos/event/event_notice.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.event; 10 | 11 | option csharp_namespace = "Kritor.Event"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.event"; 14 | option go_package = "grpc/kritor/event"; 15 | 16 | import "event/notice_data.proto"; 17 | 18 | message NoticeEvent { 19 | enum NoticeType { 20 | UNKNOWN = 0; // 保留字段, UNSPECIFIED 21 | 22 | PRIVATE_POKE = 10; // 私聊头像戳一戳 23 | PRIVATE_RECALL = 11; // 私聊消息撤回 24 | PRIVATE_FILE_UPLOADED = 12; // 私聊文件上传 25 | 26 | GROUP_POKE = 20; // 群头像戳一戳 27 | GROUP_RECALL = 21; // 群消息撤回 28 | GROUP_FILE_UPLOADED = 22; // 群文件上传 29 | GROUP_CARD_CHANGED = 23; // 群名片改变 30 | GROUP_MEMBER_UNIQUE_TITLE_CHANGED = 24; // 群成员专属头衔改变 31 | GROUP_ESSENCE_CHANGED = 25; // 群精华消息改变 32 | GROUP_MEMBER_INCREASE = 26; // 群成员增加 33 | GROUP_MEMBER_DECREASE = 27; // 群成员减少 34 | GROUP_ADMIN_CHANGED = 28; // 群管理员变动 35 | GROUP_SIGN_IN = 29; // 群签到 36 | GROUP_MEMBER_BAN = 30; // 群成员被禁言 37 | GROUP_WHOLE_BAN = 31; // 群全员禁言 38 | GROUP_REACT_MESSAGE_WITH_EMOJI = 32; // 群消息被表情回应 39 | GROUP_TRANSFER = 33; // 群转让 40 | 41 | FRIEND_INCREASE = 40; // 好友增加 42 | FRIEND_DECREASE = 41; // 好友减少 43 | } 44 | 45 | NoticeType type = 1; 46 | uint64 time = 2; 47 | string notice_id = 3; 48 | 49 | oneof notice { 50 | PrivatePokeNotice private_poke = 10; 51 | PrivateRecallNotice private_recall = 11; 52 | PrivateFileUploadedNotice private_file_uploaded = 12; 53 | 54 | GroupPokeNotice group_poke = 20; 55 | GroupRecallNotice group_recall = 21; 56 | GroupFileUploadedNotice group_file_uploaded = 22; 57 | GroupCardChangedNotice group_card_changed = 23; 58 | GroupUniqueTitleChangedNotice group_member_unique_title_changed = 24; 59 | GroupEssenceMessageNotice group_essence_changed = 25; 60 | GroupMemberIncreasedNotice group_member_increase = 26; 61 | GroupMemberDecreasedNotice group_member_decrease = 27; 62 | GroupAdminChangedNotice group_admin_changed = 28; 63 | GroupSignInNotice group_sign_in = 29; 64 | GroupMemberBanNotice group_member_ban = 30; 65 | GroupWholeBanNotice group_whole_ban = 31; 66 | GroupReactMessageWithEmojiNotice group_react_message_with_emoji = 32; 67 | GroupTransferNotice group_transfer = 33; 68 | 69 | FriendIncreasedNotice friend_increase = 40; 70 | FriendDecreasedNotice friend_decrease = 41; 71 | } 72 | } -------------------------------------------------------------------------------- /protos/auth/authentication.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.authentication; 10 | 11 | option csharp_namespace = "Kritor.Authentication"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.authentication"; 14 | option go_package = "grpc/kritor/authentication"; 15 | 16 | service AuthenticationService { 17 | rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse); 18 | rpc GetAuthenticationState(GetAuthenticationStateRequest) returns (GetAuthenticationStateResponse); 19 | 20 | rpc GetTicket(GetTicketRequest) returns (GetTicketResponse); 21 | rpc AddTicket(AddTicketRequest) returns (AddTicketResponse); 22 | rpc DeleteTicket(DeleteTicketRequest) returns (DeleteTicketResponse); 23 | } 24 | 25 | /* 26 | 在某个账号授权成功之后,接下来所有的请求都必须围绕该账号,且禁止再次发送授权包。 27 | */ 28 | message AuthenticateRequest { 29 | string account = 1; // 客户端连接认证账号 30 | string ticket = 2; // 客户端连接认证ticket 31 | } 32 | 33 | message AuthenticateResponse { 34 | enum AuthenticateResponseCode { 35 | UNSPECIFIED = 0; 36 | OK = 1; 37 | NO_ACCOUNT = 2; 38 | NO_TICKET = 3; 39 | LOGIC_ERROR = 4; 40 | } 41 | 42 | AuthenticateResponseCode code = 1; // 认证结果 43 | string msg = 2; // 错误信息 44 | } 45 | 46 | message GetAuthenticationStateRequest { 47 | string account = 1; // 客户端连接认证账号 48 | } 49 | 50 | message GetAuthenticationStateResponse { 51 | bool is_required = 1; // 是否需要认证 52 | } 53 | 54 | 55 | /* 所有对认证ticket增删查都需要使用super ticket */ 56 | 57 | enum TicketOperationResponseCode { 58 | UNSPECIFIED = 0; 59 | OK = 1; 60 | ERROR = 2; 61 | } 62 | 63 | message GetTicketRequest { 64 | string account = 1; // 客户端连接认证账号 65 | string super_ticket = 2; // 客户端连接认证super ticket 66 | } 67 | 68 | message GetTicketResponse { 69 | TicketOperationResponseCode code = 1; 70 | string msg = 2; 71 | repeated string tickets = 3; // 返回的客户端ticket,非super ticket 72 | } 73 | 74 | message AddTicketRequest { 75 | string account = 1; // 客户端连接认证账号 76 | string super_ticket = 2; // 客户端连接认证super ticket 77 | string ticket = 3; 78 | } 79 | 80 | message AddTicketResponse { 81 | TicketOperationResponseCode code = 1; 82 | string msg = 2; 83 | } 84 | 85 | message DeleteTicketRequest { 86 | string account = 1; // 客户端连接认证账号 87 | string super_ticket = 2; // 客户端连接认证super ticket 88 | string ticket = 3; 89 | } 90 | 91 | message DeleteTicketResponse { 92 | TicketOperationResponseCode code = 1; 93 | string msg = 2; 94 | } -------------------------------------------------------------------------------- /docs/request/core.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # Kritor核心服务 6 | 7 | 由Kritor端提供的几个操作Kritor端的基础功能。 8 | 9 | ## 基础信息 10 | 11 | - **服务名**: `CoreService` 12 | - **Java包名**: `io.kritor.core` 13 | - **C#命名空间**: `Kritor.Core` 14 | - **[source proto file](/protos/src/main/proto/kritor/core/core.proto)** 15 | 16 | ## 获取Kritor版本 17 | 18 | 获取Kritor的版本信息。 19 | 20 | ### 参数 21 | 22 | - **方法名**: `GetVersion` 23 | - **请求类型**: `GetVersionRequest` 24 | - **响应类型**: `GetVersionResponse` 25 | 26 | ### 请求与响应 27 | 28 | ```protobuf 29 | message GetVersionRequest {} 30 | 31 | message GetVersionResponse { 32 | string version = 1; // Kritor版本 33 | string app_name = 2; 34 | } 35 | ``` 36 | 37 | ## 请求Kritor端下载文件 38 | 39 | 请求Kritor端下载文件。 40 | 41 | ### 参数 42 | 43 | - **方法名**: `DownloadFile` 44 | - **请求类型**: `DownloadFileRequest` 45 | - **响应类型**: `DownloadFileResponse` 46 | 47 | ### 请求与响应 48 | 49 | ```protobuf 50 | message DownloadFileRequest { 51 | optional string url = 1; // 下载文件的URL 二选一 52 | optional string base64 = 2; // 下载文件的base64 二选一 53 | optional string root_path = 3; // 下载文件的根目录 需要保证Kritor有该目录访问权限 可选 54 | optional string file_name = 4; // 保存的文件名称 默认为文件MD5 可选 55 | optional uint32 thread_cnt = 5; // 下载文件的线程数 默认为3 可选 56 | map headers = 6; // 下载文件的请求头 57 | } 58 | 59 | message DownloadFileResponse { 60 | string file_absolute_path = 1; // 下载文件的绝对路径 61 | string file_md5 = 2; // 下载文件的MD5 62 | } 63 | ``` 64 | 65 | > `root_path`需要保证Kritor有该目录访问权限,否则会报错。 66 | > 67 | > `file_name`默认为文件MD5,如果你需要指定文件名,请填写。 68 | 69 | ## 获取当前账户 70 | 71 | 获取当前账户的信息。 72 | 73 | ### 参数 74 | 75 | - **方法名**: `GetCurrentAccount` 76 | - **请求类型**: `GetCurrentAccountRequest` 77 | - **响应类型**: `GetCurrentAccountResponse` 78 | 79 | ### 请求与响应 80 | 81 | ```protobuf 82 | message GetCurrentAccountRequest {} 83 | 84 | message GetCurrentAccountResponse { 85 | optional string account_uid = 1; // 当前账户 86 | uint64 account_uin = 2; 87 | string account_name = 3; // 当前账户名称 88 | } 89 | ``` 90 | 91 | ## 切换账户 92 | 93 | 切换账户。 94 | 95 | ### 参数 96 | 97 | - **方法名**: `SwitchAccount` 98 | - **请求类型**: `SwitchAccountRequest` 99 | - **响应类型**: `SwitchAccountResponse` 100 | 101 | ### 请求与响应 102 | 103 | ```protobuf 104 | message SwitchAccountRequest { 105 | oneof account { 106 | string account_uid = 1; // 切换账户uid 107 | uint64 account_uin = 2; // 切换账户uin 108 | } 109 | string super_ticket = 3; // 凭证 110 | } 111 | 112 | message SwitchAccountResponse {} 113 | ``` 114 | -------------------------------------------------------------------------------- /protos/file/group_file.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.file; 10 | 11 | option csharp_namespace = "Kritor.File"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.file"; 14 | option go_package = "grpc/kritor/file"; 15 | 16 | import "file/file_data.proto"; 17 | 18 | service GroupFileService { 19 | rpc CreateFolder(CreateFolderRequest) returns (CreateFolderResponse); // 创建文件夹 20 | rpc RenameFolder(RenameFolderRequest) returns (RenameFolderResponse); // 重命名文件夹 21 | rpc DeleteFolder(DeleteFolderRequest) returns (DeleteFolderResponse); // 删除文件夹 22 | 23 | rpc UploadFile(UploadFileRequest) returns (UploadFileResponse); // 删除文件 24 | rpc DeleteFile(DeleteFileRequest) returns (DeleteFileResponse); // 删除文件 25 | 26 | rpc GetFileSystemInfo(GetFileSystemInfoRequest) returns (GetFileSystemInfoResponse); // 获取文件系统信息 27 | rpc GetFileList(GetFileListRequest) returns (GetFileListResponse); // 获取文件夹下文件 28 | } 29 | 30 | message CreateFolderRequest { 31 | uint64 group_id = 1; // 群号 32 | string name = 2; // 文件夹名 33 | } 34 | 35 | message CreateFolderResponse { 36 | string id = 1; // 文件夹id 37 | uint64 used_space = 2; // 已使用空间 38 | } 39 | 40 | message RenameFolderRequest { 41 | uint64 group_id = 1; // 群号 42 | string folder_id = 2; // 文件夹id 43 | string name = 3; // 文件夹名 44 | } 45 | 46 | message RenameFolderResponse { 47 | } 48 | 49 | message DeleteFolderRequest { 50 | uint64 group_id = 1; // 群号 51 | string folder_id = 2; // 文件夹id 52 | } 53 | 54 | message DeleteFolderResponse { 55 | } 56 | 57 | message UploadFileRequest { 58 | uint64 group_id = 1; // 群号 59 | oneof data { 60 | bytes file = 2; // 文件内容 61 | string file_name = 3; // 文件文件名 62 | string file_path = 4; // 文件绝对路径 63 | string file_url = 5; // 文件下载地址 64 | } 65 | } 66 | 67 | message UploadFileResponse { 68 | 69 | } 70 | 71 | message DeleteFileRequest { 72 | uint64 group_id = 1; // 群号 73 | string file_id = 2; // 文件id 74 | int32 bus_id = 3; // 文件类型ID 75 | } 76 | 77 | message DeleteFileResponse { 78 | } 79 | 80 | message GetFileSystemInfoRequest { 81 | uint64 group_id = 1; // 群号 82 | } 83 | 84 | message GetFileSystemInfoResponse { 85 | uint32 file_count = 1; // 文件数量 86 | uint32 total_count = 2; // 文件数量上限 87 | uint32 used_space = 3; // 已使用空间 88 | uint32 total_space = 4; // 空间上限 89 | } 90 | 91 | message GetFileListRequest { 92 | uint64 group_id = 1; // 群号 93 | optional string folder_id = 2; // 文件夹id 空则为根目录 94 | } 95 | 96 | message GetFileListResponse { 97 | repeated File files = 1; 98 | repeated Folder folders = 2; 99 | } -------------------------------------------------------------------------------- /docs/request/req_active.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 主动Grpc 6 | 7 | 主动Grpc由Grpc框架提供与实现请求的接收等待以及重试,是Kritor最为推荐的请求方式。 8 | 9 | ## 元数据 (Metadata) 10 | 11 | Kritor端的响应和事件推送均包含以下元数据: 12 | 13 | | 名称 | 解释 | 14 | |-------------|--------------| 15 | | kritor-self-uin | kritor端uin | 16 | | kritor-self-uid | kritor端uid | 17 | | kritor-self-version | kritor端实现及其版本 | 18 | 19 | ## 请求与响应 20 | 21 | Grpc提供了`挂起/堵塞`和`异步`的两种请求方式。 22 | 23 | ### 异步 (流式传输) 24 | 25 | ```kotlin 26 | suspend fun main() { 27 | val channel = ManagedChannelBuilder 28 | .forAddress("localhost", 8080) 29 | .usePlaintext() 30 | .enableRetry() // 允许尝试 31 | .executor(Dispatchers.IO.asExecutor()) // 使用协程的调度器 32 | .build() 33 | 34 | val observer: StreamObserver = object: StreamObserver { 35 | override fun onCompleted() { 36 | 37 | } 38 | 39 | override fun onNext(rsp: AuthRsp?) { 40 | // doSomething 41 | } 42 | 43 | override fun onError(e: Throwable?) { 44 | 45 | } 46 | } 47 | 48 | AuthenticationGrpc.newStub(channel).auth(authReq { 49 | account = "1145141919810" 50 | ticket = "A123456" 51 | }, observer) 52 | } 53 | ``` 54 | 55 | ### 挂起 56 | 57 | ```kotlin 58 | suspend fun main() { 59 | val channel = ManagedChannelBuilder 60 | .forAddress("localhost", 8080) 61 | .usePlaintext() 62 | .enableRetry() // 允许尝试 63 | .executor(Dispatchers.IO.asExecutor()) // 使用协程的调度器 64 | .build() 65 | 66 | val stub = AuthenticationGrpcKt.AuthenticationCoroutineStub(channel) 67 | val rsp = stub.auth(authReq { 68 | account = "1145141919810" 69 | ticket = "A123456" 70 | }) 71 | } 72 | ``` 73 | 74 | ### 其它语言的请求示例 75 | 76 | - [Java](https://grpc.io/docs/languages/java/basics/#calling-service-methods)(同步请求) 77 | - [Java](https://grpc.io/docs/languages/java/basics/#client-side-streaming-rpc)(流式异步) 78 | - [C#](https://learn.microsoft.com/zh-cn/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-8.0&tabs=visual-studio#create-the-grpc-client-in-a-net-console-app) (微软文档) 79 | - [C++](https://grpc.io/docs/languages/cpp/basics/#calling-service-methods) 80 | - [Golang](https://grpc.io/docs/languages/go/basics/#calling-service-methods) 81 | - [Node](https://grpc.io/docs/languages/node/basics/#calling-service-methods) 82 | - [Object-C](https://grpc.io/docs/languages/objective-c/basics/#calling-service-methods) 83 | - [PHP](https://grpc.io/docs/languages/php/basics/#calling-service-methods) 84 | - [Python](https://grpc.io/docs/languages/python/basics/#calling-service-methods) 85 | -------------------------------------------------------------------------------- /docs/event/msg.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 消息事件 6 | 7 | 消息事件分为`好友`,`群聊`,`频道`,`群临时会话`。 8 | 9 | 其中对消息事件进行监听前文有所提及。 10 | 11 | ## 消息来源对象解析 12 | 13 | ```protobuf 14 | enum Scene { 15 | UNSPECIFIED = 0; // 保留字段, UNSPECIFIED 16 | GROUP = 1; // 群聊 17 | FRIEND = 2; // 好友 18 | GUILD = 3; // 频道 19 | STRANGER_FROM_GROUP = 11; // 群临时会话 20 | 21 | // 以下类型为可选实现 22 | NEARBY = 6; // 附近的人 23 | STRANGER = 10; // 陌生人 24 | } 25 | 26 | message Contact { 27 | Scene scene = 1; 28 | string peer = 2; // 群聊则为群号 私聊则为 Uix (Uin 或 Uid) 频道消息则为频道号 29 | optional string sub_peer = 3; // 群临时聊天则为群号 频道消息则为子频道号 其它情况可不提供 30 | } 31 | ``` 32 | 33 | 其中的`scene`表示来自何方的类型,而`peer`则为来自何方,他有以下几种情况: 34 | 35 | - **GROUP**:`peer`为群号。 36 | - **FRIEND**:`peer`为QQ号或者用户`uid`。 37 | - **GUILD**:`peer`为频道号,`sub_peer`为子频道号。 38 | - **NEARBY**:`peer`为QQ号或者用户`tiny_id`。 39 | - **STRANGER**:`peer`为QQ号或者用户`uid`。 40 | - **STRANGER_FROM_GROUP**:`peer`为QQ,`sub_peer`为群号。 41 | 42 | ## 消息事件 43 | 44 | 下方是一个完整的消息事件结构体: 45 | 46 | ```protobuf 47 | message PrivateSender { 48 | optional string uid = 1; 49 | uint64 uin = 2; 50 | string nick = 3; 51 | } 52 | 53 | message GroupSender { 54 | string group_id = 1; 55 | optional string uid = 2; 56 | uint64 uin = 3; 57 | string nick = 4; 58 | } 59 | 60 | message GuildSender { 61 | string guild_id = 1; 62 | string channel_id = 2; 63 | string tiny_id = 3; 64 | string nick = 4; 65 | Role role = 5; 66 | } 67 | 68 | message PushMessageBody { 69 | uint64 time = 1; 70 | string message_id = 2; 71 | uint64 message_seq = 3; 72 | Scene scene = 4; 73 | oneof sender { 74 | PrivateSender private = 5; 75 | GroupSender group = 6; 76 | GuildSender guild = 7; 77 | } 78 | repeated Element elements = 9; // 发的什么东西 79 | } 80 | ``` 81 | 其中`message_id`作为接下来各种操作的主要对象,`message_seq`则是由腾讯维护的一个自增的序列号,用于标识消息的顺序,您也可以使用它反查一些它的`message_id`(**GetMessageBySeq**)。 82 | 83 | ## 消息元素 84 | 85 | 消息元素是消息的主要内容,他有很多种类型,下面将列出一个表格: 86 | 87 | | 名称 | 说明 | 接收 | 88 | |-------------|----------|-----| 89 | | TEXT | 文本 | yes | 90 | | AT | @ | yes | 91 | | FACE | 表情 | yes | 92 | | BUBBLE_FACE | 弹射表情 | yes | 93 | | REPLY | 回复 | yes | 94 | | IMAGE | 图片 | yes | 95 | | VOICE | 语音 | yes | 96 | | VIDEO | 视频 | yes | 97 | | BASKETBALL | 篮球 | yes | 98 | | DICE | 骰子 | yes | 99 | | RPS | 石头剪刀布 | yes | 100 | | POKE | 戳一戳 | yes | 101 | | MUSIC | 音乐 | yes | 102 | | WEATHER | 天气 | yes | 103 | | LOCATION | 位置 | yes | 104 | | SHARE | 分享 | yes | 105 | | GIFT | 礼物 | yes | 106 | | MARKET_FACE | 商城表情 | yes | 107 | | FORWARD | 转发 | yes | 108 | | CONTACT | 名片 | yes | 109 | | JSON | JSON | yes | 110 | | XML | XML | yes | 111 | | FILE | 文件 | yes | 112 | | MARKDOWN | Markdown | yes | 113 | | BUTTON | 按钮 | yes | 114 | | NODE | 节点 | no | 115 | 116 | 详细的消息元素定义请参考[消息元素](/protos/src/main/proto/kritor/event/comm_msg.proto)。 117 | 118 | > 注意:接收的消息对象只是和发消息的对象名字相同,但是对应结构不同。 -------------------------------------------------------------------------------- /docs/request/authentication.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 鉴权服务 6 | 7 | Kritor提供的基础鉴权操作,可避免grpc泄露导致的被骇入操作。 8 | 9 | ## 基础信息 10 | 11 | - **服务名**: `AuthenticationService` 12 | - **Java包名**: `io.kritor.authentication` 13 | - **C#命名空间**: `Kritor.Authentication` 14 | - **[source proto file](/protos/src/main/proto/kritor/auth/authenticate.proto)** 15 | 16 | ## 鉴权 17 | 18 | 服务端鉴权操作,用于验证客户端的合法性。 19 | 20 | ### 参数 21 | 22 | - **方法名**: `Authenticate` 23 | - **请求类型**: `AuthenticateRequest` 24 | - **响应类型**: `AuthenticateResponse` 25 | 26 | ### 请求与响应 27 | 28 | ```protobuf 29 | message AuthenticateRequest { 30 | string account = 1; // 客户端连接认证账号 31 | string ticket = 2; // 客户端连接认证ticket 32 | } 33 | 34 | message AuthenticateResponse { 35 | enum AuthenticateResponseCode { 36 | OK = 0; 37 | NO_ACCOUNT = 1; 38 | NO_TICKET = 2; 39 | LOGIC_ERROR = 3; 40 | } 41 | 42 | AuthenticateResponseCode code = 1; // 认证结果 43 | string msg = 2; // 错误信息 44 | } 45 | ``` 46 | 47 | ## 获取是否需要鉴权 48 | 49 | 获取是否需要在元数据携带鉴权信息。 50 | 51 | ### 参数 52 | 53 | - **方法名**: `GetAuthenticationState` 54 | - **请求类型**: `GetAuthenticationStateRequest` 55 | - **响应类型**: `GetAuthenticationStateResponse` 56 | 57 | ### 请求与响应 58 | 59 | ```protobuf 60 | message GetAuthenticationStateRequest { 61 | string account = 1; // 客户端连接认证账号 62 | } 63 | 64 | message GetAuthenticationStateResponse { 65 | bool is_required = 1; // 是否需要认证 66 | } 67 | ``` 68 | 69 | ## 获取鉴权Ticket (WebUI) 70 | 71 | WebUI通过superTicket获取鉴权ticket,用于实现远程控制kritor。 72 | 73 | ### 参数 74 | 75 | - **方法名**: `GetTicket` 76 | - **请求类型**: `GetTicketRequest` 77 | - **响应类型**: `GetTicketResponse` 78 | 79 | ### 请求与响应 80 | 81 | ```protobuf 82 | enum TicketOperationResponseCode { 83 | OK = 0; 84 | ERROR = 1; 85 | } 86 | 87 | message GetTicketRequest { 88 | string account = 1; // 客户端连接认证账号 89 | string ticket = 2; // 客户端连接认证super ticket 90 | } 91 | 92 | message GetTicketResponse { 93 | TicketOperationResponseCode code = 1; 94 | string msg = 2; 95 | repeated string tickets = 3; // 返回的客户端ticket,非super ticket 96 | } 97 | ``` 98 | 99 | ## 删除鉴权Ticket (WebUI) 100 | 101 | WebUI通过superTicket删除鉴权ticket,用于实现远程控制kritor。 102 | 103 | ### 参数 104 | 105 | - **方法名**: `DeleteTicket` 106 | - **请求类型**: `DeleteTicketRequest` 107 | - **响应类型**: `DeleteTicketResponse` 108 | 109 | ### 请求与响应 110 | 111 | ```protobuf 112 | message DeleteTicketRequest { 113 | string account = 1; // 客户端连接认证账号 114 | string ticket = 2; // 客户端连接认证super ticket 115 | string delete_ticket = 3; 116 | } 117 | 118 | message DeleteTicketResponse { 119 | TicketOperationResponseCode code = 1; 120 | string msg = 2; 121 | } 122 | ``` 123 | 124 | ## 添加鉴权Ticket (WebUI) 125 | 126 | WebUI通过superTicket添加鉴权ticket,用于实现远程控制kritor。 127 | 128 | ### 参数 129 | 130 | - **方法名**: `AddTicket` 131 | - **请求类型**: `AddTicketRequest` 132 | - **响应类型**: `AddTicketResponse` 133 | 134 | ### 请求与响应 135 | 136 | ```protobuf 137 | message AddTicketRequest { 138 | string account = 1; // 客户端连接认证账号 139 | string ticket = 2; // 客户端连接认证super ticket 140 | string new_ticket = 3; 141 | } 142 | 143 | message AddTicketResponse { 144 | TicketOperationResponseCode code = 1; 145 | string msg = 2; 146 | } 147 | ``` -------------------------------------------------------------------------------- /protos/guild/guild_data.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.guild; 10 | 11 | option csharp_namespace = "Kritor.Guild"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.guild"; 14 | option go_package = "grpc/kritor/guild"; 15 | 16 | // 频道信息 17 | message GuildInfo { 18 | uint64 guild_id = 1; // 频道ID 19 | string guild_name = 2; // 频道名称 20 | string guild_display_id = 3; // 频道显示ID 21 | string profile = 4; // 频道简介 22 | bool is_enable = 5; // 是否启用 23 | bool is_banned = 6; // 是否被封禁 24 | bool is_frozen = 7; // 是否被冻结 25 | uint64 owner_id = 8; // 频道拥有者ID 26 | uint64 shutup_expire_time = 9; // 禁言过期时间 27 | bool allow_search = 10; // 是否允许搜索 28 | } 29 | 30 | // 子频道信息 31 | message ChannelInfo { 32 | uint64 channel_id = 1; // 子频道ID 33 | uint64 guild_id = 2; // 频道ID 34 | string channel_name = 3; // 子频道名称 35 | uint64 create_time = 4; // 创建时间 36 | uint64 max_member_count = 5; // 最大成员数 37 | uint64 creator_tiny_id = 6; // 创建者tinyid 38 | uint64 talk_permission = 7; // 发言权限 39 | uint64 visible_type = 8; // 可见类型 40 | uint64 current_slow_mode = 9; // 当前发言限制 41 | repeated SlowModes slow_modes = 10; // 发言限制 42 | string icon_url = 11; // 频道图标 43 | uint64 jump_switch = 12; // 跳转开关 44 | uint64 jump_type = 13; // 跳转类型 45 | string jump_url = 14; // 跳转地址 46 | uint64 category_id = 15; // 分类ID 47 | uint64 my_talk_permission = 16; // 我的发言权限 48 | } 49 | 50 | // 发言限制 51 | message SlowModes { 52 | uint64 slow_mode_key = 1; // 0:关闭 1:每分钟1条 2:每分钟2条 3:每分钟5条 4:每分钟10条 5:每5分钟1条 6:每10分钟1条 7:每15分钟1条 8:每30分钟1条 9:每1小时1条 10:每12小时1条 11:每24小时1条 53 | string slow_mode_text = 2; // 发言限制描述 54 | uint64 speak_frequency = 3; // 每分钟发言频率 55 | uint64 slow_mode_circle = 4; // 发言限制周期 56 | } 57 | 58 | // 频道成员信息 59 | message MemberInfo { 60 | uint64 tiny_id = 1; // 用户tinyid 61 | string title = 2; // 用户头衔 62 | string nickname = 3; // 用户昵称 63 | uint64 role_id = 4; // 用户角色ID 64 | string role_name = 5; // 用户角色名称 65 | uint64 role_color = 6; // 用户角色颜色 66 | uint64 join_time = 7; // 加入时间 67 | uint64 robot_type = 8; // 机器人类型 68 | uint64 type = 9; // 用户类型 69 | bool in_black = 10; // 是否在黑名单 70 | uint64 platform = 11; // 平台 71 | } 72 | 73 | // 频道成员资料 74 | message MemberProfile { 75 | uint64 tiny_id = 1; // 用户tinyid 76 | string nickname = 2; // 用户昵称 77 | string avatar_url = 3; // 用户头像 78 | uint64 join_time = 4; // 加入时间 79 | repeated MemberRoleInfo roles_info = 5; // 用户角色 80 | } 81 | 82 | // 身份组权限信息 83 | message PermissionInfo { 84 | uint64 root_id = 1; // 权限根ID 85 | repeated uint64 child_ids = 2; // 权限子ID 86 | } 87 | 88 | // 用户身份组信息 89 | message MemberRoleInfo { 90 | uint64 role_id = 1; // 身份组ID 91 | string role_name = 2; // 身份组名称 92 | uint64 color = 3; // 身份组颜色 93 | repeated PermissionInfo permissions = 4; // 身份组权限 94 | uint64 type = 5; // 用户角色类型 95 | string display_name = 6; // 用户角色显示名称 96 | } 97 | 98 | // 频道身份组详细信息 99 | message RoleInfo { 100 | uint64 role_id = 1; // 身份组ID 101 | string role_name = 2; // 身份组名称 102 | uint64 color = 3; // 身份组颜色 103 | repeated PermissionInfo permissions = 4; // 身份组权限 104 | bool disabled = 5; // 是否禁用 105 | bool independent = 6; // 是否独立 106 | uint64 max_count = 7; // 最大成员数 107 | uint64 member_count = 8; // 成员数 108 | bool owned = 9; // 是否拥有 109 | } -------------------------------------------------------------------------------- /protos/friend/friend.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.friend; 10 | 11 | option csharp_namespace = "Kritor.Friend"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.friend"; 14 | option go_package = "grpc/kritor/friend"; 15 | 16 | import "friend/firend_data.proto"; 17 | 18 | service FriendService { 19 | rpc GetFriendList (GetFriendListRequest) returns (GetFriendListResponse); // 获取好友列表 20 | 21 | rpc GetFriendProfileCard(GetFriendProfileCardRequest) returns (GetFriendProfileCardResponse); // 获取名片(限好友) 22 | rpc GetStrangerProfileCard(GetStrangerProfileCardRequest) returns (GetStrangerProfileCardResponse); // 获取陌生人信息 23 | rpc SetProfileCard(SetProfileCardRequest) returns (SetProfileCardResponse); // 设置自己的名片 24 | 25 | rpc IsBlackListUser(IsBlackListUserRequest) returns (IsBlackListUserResponse); // 是否是黑名单用户 26 | rpc VoteUser(VoteUserRequest) returns (VoteUserResponse); // 点赞好友 27 | 28 | rpc GetUidByUin(GetUidByUinRequest) returns (GetUidByUinResponse); // 获取uid 29 | rpc GetUinByUid(GetUinByUidRequest) returns (GetUinByUidResponse); // 获取uin 30 | 31 | rpc UploadPrivateFile(PrivateChatFileRequest) returns (UploadPrivateChatFileResponse); // 上传私聊文件 32 | } 33 | 34 | message GetFriendListRequest { 35 | optional bool refresh = 1; // 是否刷新好友列表 36 | } 37 | 38 | message GetFriendListResponse { 39 | repeated FriendInfo friends_info = 1; 40 | } 41 | 42 | message GetFriendProfileCardRequest { 43 | repeated string target_uids = 1; 44 | repeated uint64 target_uins = 2; 45 | } 46 | 47 | message GetFriendProfileCardResponse { 48 | repeated ProfileCard friends_profile_card = 1; 49 | } 50 | 51 | message GetStrangerProfileCardRequest { 52 | repeated string target_uids = 1; 53 | repeated uint64 target_uins = 2; 54 | } 55 | 56 | message GetStrangerProfileCardResponse { 57 | repeated ProfileCard strangers_profile_card = 1; 58 | } 59 | 60 | message SetProfileCardRequest { 61 | optional string nick = 1; 62 | optional string company = 2; 63 | optional string email = 3; 64 | optional string college = 4; 65 | optional string personal_note = 5; 66 | optional uint32 birthday = 6; 67 | optional uint32 age = 7; 68 | } 69 | 70 | message SetProfileCardResponse { 71 | } 72 | 73 | message IsBlackListUserRequest { 74 | oneof target { 75 | string target_uid = 1; 76 | uint64 target_uin = 2; 77 | } 78 | } 79 | 80 | message IsBlackListUserResponse { 81 | bool is_black_list_user = 1; 82 | } 83 | 84 | message VoteUserRequest { 85 | oneof target { 86 | string target_uid = 1; 87 | uint64 target_uin = 2; 88 | } 89 | uint32 vote_count = 3; 90 | } 91 | 92 | message VoteUserResponse { 93 | } 94 | 95 | message GetUidByUinRequest { 96 | repeated uint64 target_uins = 1; 97 | } 98 | 99 | message GetUidByUinResponse { 100 | map uid_map = 1; 101 | } 102 | 103 | message GetUinByUidRequest { 104 | repeated string target_uids = 1; 105 | } 106 | 107 | message GetUinByUidResponse { 108 | map uin_map = 1; 109 | } 110 | 111 | message PrivateChatFileRequest { 112 | string target_uid = 1; // 用户id 113 | uint64 target_uin = 2; // 用户id 114 | string file = 3; // 本地文件绝对路径 115 | string name = 4; // 文件名称 116 | } 117 | 118 | message UploadPrivateChatFileResponse { 119 | string file_id = 1; // 文件ID 120 | string file_url = 2; // 文件URL 121 | optional string file_name = 3; // 文件名 122 | optional string file_size = 4; // 文件大小 123 | optional string file_bizid = 5; // 文件bizid 124 | optional string file_sha = 6; // 文件sha 125 | optional string file_md5 = 7; // 文件md5 126 | } -------------------------------------------------------------------------------- /docs/request/request.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 请求响应相关 6 | 7 | ## 请求与响应 8 | 9 | [主动Grpc](/docs/request/req_active.md): 主动与被动Grpc的行为有所差异,主动Grpc是客户端主动发起请求,服务端被动响应。主动Grpc提供了`挂起/堵塞`和`异步`的两种请求方式。 10 | 11 | [被动Grpc](/docs/request/req_passive.md): 被动Grpc则为双向流式实现,客户端与服务端可以同时发送和接收数据。 12 | 但是需要客户端对接收的数据进行`command`与`seq`的配对比较,才能拿到对应请求的数据包。 13 | 14 | ## 请求错误处理(主动Grpc) 15 | 16 | 当Kritor端无法正常处理某个请求,或者请求失败的时候,将会使用Grpc的错误码来返回错误信息。其中大量错误信息的描述通常在`status.description`中。 17 | 18 | 除去Grpc用于保证传输稳定和网络波动的那几个状态码外,Kritor端还会使用以下状态码: 19 | 20 | - `OK (code 0)`: 一切正常。 21 | - `INVALID_ARGUMENT (code 3)`: 参数错误,例如群禁言没提供群号。 22 | - `UNIMPLEMENTED (code 12)`: api不支持,例如协议端不支持使用uid。 23 | - `UNAUTHENTICATED (code 16)`: 未认证,通常是鉴权失败或者越级调用。 24 | - `PERMISSION_DENIED (code 7)`: 权限不足,例如没有权限解除群禁言或者无权使用某个服务。 25 | - `INTERNAL (code 13)`: Kritor内部出现问题,例如数据库连接失败或者其他异常。 26 | 27 | 我们通过几个简单的Kotlin代码示例来演示如何处理请求错误。 28 | 29 | 如果需要查看错误码的详细信息,可以查看[官方文档](https://github.com/grpc/grpc/blob/master/doc/statuscodes.md)。 30 | 31 | ### Kotlin 32 | 33 | ```kotlin 34 | suspend fun main() { 35 | val channel = ManagedChannelBuilder 36 | .forAddress("localhost", 8080) 37 | .usePlaintext() 38 | .enableRetry() // 允许尝试 39 | .executor(Dispatchers.IO.asExecutor()) // 使用协程的调度器 40 | .build() 41 | 42 | val stub = AuthenticationGrpcKt.AuthenticationCoroutineStub(channel) 43 | runCatching { 44 | val rsp = stub.auth(authReq { 45 | account = "1145141919810" 46 | ticket = "A123456" 47 | }) 48 | println(rsp.code) 49 | }.onFailure { 50 | // 如果错误,打印错误信息 51 | val status = Status.fromThrowable(it) 52 | println(status) // 直接打印code + cause + description 53 | println(status.code) // 打印错误码 54 | println(status.description) // 打印错误描述 55 | } 56 | } 57 | ``` 58 | 59 | 更多语言请查看[Grpc官方错误处理示例](https://grpc.io/docs/guides/error/)。 60 | 61 | ## 请求错误处理(被动Grpc) 62 | 63 | 当Kritor端无法正常处理某个请求,或者请求失败的时候,将会在返回包携带错误信息。其中大量错误信息的描述通常在`msg`中。 64 | 65 | Kritor推送的返回包将会提供以下状态码: 66 | 67 | - `OK (code 0)`: 一切正常。 68 | - `INVALID_ARGUMENT (code 3)`: 参数错误,例如群禁言没提供群号。 69 | - `UNIMPLEMENTED (code 12)`: api不支持,例如协议端不支持使用uid。 70 | - `UNAUTHENTICATED (code 16)`: 未认证,通常是鉴权失败或者越级调用。 71 | - `PERMISSION_DENIED (code 7)`: 权限不足,例如没有权限解除群禁言或者无权使用某个服务。 72 | - `INTERNAL (code 13)`: Kritor内部出现问题,例如数据库连接失败或者其他异常。 73 | 74 | 详细信息可以查看,请求包与返回包的[定义](/protos/src/main/proto/kritor/comm_request.proto)。 75 | 76 | ## 鉴权操作 77 | 78 | 如果需要进行鉴权操作的校验,可以查看[鉴权服务](/docs/request/authentication.md)。 79 | 80 | 如果确保`ticket`可用,请在每次请求的元数据中携带鉴权`ticket`,下面是一个简单的示例: 81 | 82 | ### 主动RPC 83 | 84 | ```kotlin 85 | ContactServiceGrpcKt.ContactServiceCoroutineStub(channel).getProfileCard(profileCardRequest { 86 | uin = 114514 87 | }, Metadata().also { 88 | // 114514就是你的ticket 89 | it.put(Metadata.Key.of("ticket", Metadata.ASCII_STRING_MARSHALLER), "114514") 90 | }) 91 | ``` 92 | 93 | ### 被动RPC 94 | 95 | Kritor端将携带`ticket`在元数据,发起双向流请求,Bot端作为Server应该去实现一个拦截器或者其它操作已获取鉴权`ticket`达到鉴权目的! 96 | 97 | - [Go语言拦截器示例](https://golang2.eddycjy.com/posts/ch3/08-grpc-interceptor/) 98 | - [NodeJs拦截器示例](https://juejin.cn/post/6844904016221044750) 99 | 100 | ## 实现接口 101 | 102 | Kritor提供了多种接口供客户端调用,包括但不限于以下服务: 103 | 104 | > - ### [鉴权服务](/docs/request/authentication.md) 105 | > 106 | > - ### [核心服务](/docs/request/core.md) 107 | > 108 | > - ### [扩展服务](/docs/request/development.md) 109 | > 110 | > - ### [好友服务](/docs/request/friend.md) 111 | > 112 | > - ### [群聊服务](/docs/request/group.md) 113 | > 114 | > - ### [文件服务](/docs/request/group_file.md) 115 | > 116 | > - ### [频道服务](/docs/request/guild.md) 117 | > 118 | > - ### [消息服务](/docs/request/message.md) 119 | > 120 | > - ### [Web服务](/docs/request/web.md) 121 | -------------------------------------------------------------------------------- /docs/request/group_file.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 群聊文件服务 6 | 7 | 实现于操作群聊/频道文件。 8 | 9 | ## 基础信息 10 | 11 | - **服务名**: `GroupFileService` 12 | - **Java包名**: `io.kritor.file` 13 | - **C#命名空间**: `Kritor.File` 14 | - **[source proto file](/protos/src/main/proto/kritor/file/group_file.proto)** 15 | 16 | ## 基础定义 17 | 18 | ### 文件信息 19 | 20 | ```protobuf 21 | message File { 22 | string file_id = 1; 23 | string file_name = 2; 24 | uint64 file_size = 3; 25 | int32 bus_id = 4; 26 | uint32 upload_time = 5; 27 | uint32 dead_time = 6; 28 | uint32 modify_time = 7; 29 | uint32 download_times = 8; 30 | uint64 uploader = 9; 31 | string uploader_name = 10; 32 | string sha = 11; 33 | string sha3 = 12; 34 | string md5 = 13; 35 | } 36 | ``` 37 | ### 文件夹信息 38 | 39 | ```protobuf 40 | message Folder { 41 | string folder_id = 1; 42 | string folder_name = 2; 43 | uint32 total_file_count = 3; 44 | uint32 create_time = 4; 45 | uint64 creator = 5; 46 | string creator_name = 6; 47 | } 48 | ``` 49 | 50 | ## 创建文件夹 51 | 52 | 创建一个文件夹。 53 | 54 | ### 参数 55 | 56 | - **方法名**: `CreateFolder` 57 | - **请求类型**: `CreateFolderRequest` 58 | - **响应类型**: `CreateFolderResponse` 59 | 60 | ### 请求与响应 61 | 62 | ```protobuf 63 | message CreateFolderRequest { 64 | uint64 group_id = 1; // 群号 65 | string name = 2; // 文件夹名 66 | } 67 | 68 | message CreateFolderResponse { 69 | string id = 1; // 文件夹id 70 | uint64 used_space = 2; // 已使用空间 71 | } 72 | ``` 73 | 74 | ## 删除文件夹 75 | 76 | 删除一个文件夹。 77 | 78 | ### 参数 79 | 80 | - **方法名**: `DeleteFolder` 81 | - **请求类型**: `DeleteFolderRequest` 82 | - **响应类型**: `DeleteFolderResponse` 83 | 84 | ### 请求与响应 85 | 86 | ```protobuf 87 | message DeleteFolderRequest { 88 | uint64 group_id = 1; // 群号 89 | string folder_id = 2; // 文件夹id 90 | } 91 | 92 | message DeleteFolderResponse { 93 | } 94 | ``` 95 | 96 | ## 删除文件 97 | 98 | 删除一个文件。 99 | 100 | ### 参数 101 | 102 | - **方法名**: `DeleteFile` 103 | - **请求类型**: `DeleteFileRequest` 104 | - **响应类型**: `DeleteFileResponse` 105 | 106 | ### 请求与响应 107 | 108 | ```protobuf 109 | message DeleteFileRequest { 110 | uint64 group_id = 1; // 群号 111 | string file_id = 2; // 文件id 112 | int32 bus_id = 3; // 文件类型ID 113 | } 114 | 115 | message DeleteFileResponse { 116 | } 117 | ``` 118 | 119 | ## 重命名文件夹 120 | 121 | 重命名一个文件夹。 122 | 123 | ### 参数 124 | 125 | - **方法名**: `RenameFolder` 126 | - **请求类型**: `RenameFolderRequest` 127 | - **响应类型**: `RenameFolderResponse` 128 | 129 | ### 请求与响应 130 | 131 | ```protobuf 132 | message RenameFolderRequest { 133 | uint64 group_id = 1; // 群号 134 | string folder_id = 2; // 文件夹id 135 | string name = 3; // 文件夹名 136 | } 137 | 138 | message RenameFolderResponse { 139 | } 140 | ``` 141 | 142 | ## 获取文件系统信息 143 | 144 | 获取文件系统信息,例如文件数量,空间大小限制。 145 | 146 | ### 参数 147 | 148 | - **方法名**: `GetFileSystemInfo` 149 | - **请求类型**: `GetFileSystemInfoRequest` 150 | - **响应类型**: `GetFileSystemInfoResponse` 151 | 152 | ### 请求与响应 153 | 154 | ```protobuf 155 | message GetFileSystemInfoRequest { 156 | uint64 group_id = 1; // 群号 157 | } 158 | 159 | message GetFileSystemInfoResponse { 160 | uint32 file_count = 1; // 文件数量 161 | uint32 total_count = 2; // 文件数量上限 162 | uint32 used_space = 3; // 已使用空间 163 | uint32 total_space = 4; // 空间上限 164 | } 165 | ``` 166 | 167 | ## 获取文件列表 168 | 169 | 获取文件列表。 170 | 171 | ### 参数 172 | 173 | - **方法名**: `GetFileList` 174 | - **请求类型**: `GetFileListRequest` 175 | - **响应类型**: `GetFileListResponse` 176 | 177 | ### 请求与响应 178 | 179 | ```protobuf 180 | message GetFileListRequest { 181 | uint64 group_id = 1; // 群号 182 | optional string folder_id = 2; // 文件夹id 空则为根目录 183 | } 184 | 185 | message GetFileListResponse { 186 | repeated File files = 1; 187 | repeated Folder folders = 2; 188 | } 189 | ``` -------------------------------------------------------------------------------- /docs/request/req_passive.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 被动式Grpc 6 | 7 | 被动Grpc是为了弥补Grpc在Kritor作为client时候,Bot端(server)无法主动发起请求的一个实现,其原理是基于grpc的双向流来传输数据,实现比较繁琐,需要用户自行实现接包的等待以及处理。 8 | 9 | ## 对接流程 10 | 11 | 1. Bot端的Server启动之后,Kritor端建立连接(调用`reverseStream`方法)。 12 | 2. Kritor端会输入一个 `Channel` **(Flow / Stream)**,这个管道流允许你从其中获取`Response`(返回包),我们称其为收包流。 13 | 3. 因为是Bot端启动的server,所以说Bot端需要实现`reverseStream`方法,这个方法需要返回一个`Flow` **(Flow / Stream)**,我们称其为发包流,这个流允许你发送`Request`(请求包)。 14 | 4. Bot端通过发包流向Kritor端发送请求包,注意标明正确的`cmd`和`seq`。 15 | 5. Kritor端会从Bot端的发包流中获取到来自Bot端的请求包,然后处理,处理完成之后,会返回一个`Response`给Bot端。 16 | 6. Bot端通过发包的`seq`和`cmd`来匹配之前发过的包,从而获取到对应的返回包。 17 | 18 | > 这个发包流(Bot端的发包流)在Kritor端,会被用于接收来自Bot端的请求包,所以说也叫做Kritor端的收包流。 19 | > 20 | > Kritor端的发包流会被用于在Bot端接收来自Kritor端的返回包,也叫做Bot端的收包流。 21 | 22 | ## 元数据 (Metadata) 23 | 24 | Kritor端的响应和事件推送均包含以下元数据: 25 | 26 | | 名称 | 解释 | 27 | |-------------|--------------| 28 | | kritor-self-uin | kritor端uin | 29 | | kritor-self-uid | kritor端uid | 30 | | kritor-self-version | kritor端实现及其版本 | 31 | 32 | ## 请求包格式 33 | 34 | ### 请求命令名 35 | 36 | ```js 37 | let command = "Authentication.Auth" 38 | ``` 39 | 40 | 其中`Authentication`是服务名,`Auth`是方法名,这里可以康出[这些东西](/docs/request/authentication.md#%E5%9F%BA%E7%A1%80%E4%BF%A1%E6%81%AF)什么地方来的。 41 | 42 | ### 自增序列 43 | 44 | ```js 45 | let seq = 1 46 | ``` 47 | 48 | 这个序列是一个自增的序列,用于标记这个请求包的唯一性,Kritor端会通过这个序列来匹配返回包。如果超过了最大值,可以从头开始继续自增。当然如果你觉得一定不会重复,写个随机数也可以捏。 49 | 50 | > 来自Kritor端的推送的seq一定是负数!(除Bot端请求包对应的返回包除外) 51 | > 52 | > Kritor端推送的包是负数,一般接收消息推送/事件推送... 53 | > 54 | > 从Bot端发出的请求包,必须是正数! 55 | > 56 | > 从Kritor端返回的包,seq必定和请求包一致,否则无法匹配。 57 | 58 | ## 代码示例 59 | 60 | 这是一个被动Grpc,Bot端作为Server的代码示例,仅限为Kotlin,如有其它语言补充请PR提交。 61 | 62 | ```kotlin 63 | package passive 64 | 65 | import io.grpc.ServerBuilder 66 | import io.kritor.ReverseServiceGrpcKt 67 | import io.kritor.authReq 68 | import io.kritor.reverse.Request 69 | import io.kritor.reverse.Response 70 | import io.kritor.reverse.request 71 | import kotlinx.coroutines.GlobalScope 72 | import kotlinx.coroutines.delay 73 | import kotlinx.coroutines.flow.Flow 74 | import kotlinx.coroutines.flow.channelFlow 75 | import kotlinx.coroutines.launch 76 | import java.util.* 77 | 78 | class PassiveKritorServer( 79 | port: Int, 80 | ) { 81 | private val requestList = Collections.synchronizedList(mutableListOf()) // 用于存储请求包 82 | 83 | private val server = ServerBuilder 84 | .forPort(port) 85 | .addService(object: ReverseServiceGrpcKt.ReverseServiceCoroutineImplBase() { 86 | override fun reverseStream(requests: Flow): Flow { 87 | // requests: Flow 用于接收来自Kritor端的返回包 88 | 89 | // 这里Kritor端建立了一个连接, 并且给予了一个Flow 90 | // 这个flow用于接收来自Kritor端的返回包 91 | requestList.add(request { 92 | cmd = "Authentication.Auth" // 服务名 + "." + 方法名 93 | buf = authReq { 94 | account = "admin" 95 | ticket = "admin" 96 | }.toByteString() 97 | seq = 1 // 理论上是一个自增序列,超了可以从头开始继续自增 98 | }) 99 | 100 | // 这里给一个flow给Kritor端,让Kritor端可以获取到客户端发的请求包 101 | return channelFlow { 102 | GlobalScope.launch { 103 | requests.collect { 104 | println("收到请求返回包:$it") 105 | } 106 | // 开启一个协程去接收来自kritor端的返回包 107 | } 108 | 109 | while (true) { 110 | if (requestList.isNotEmpty()) { 111 | send(requestList.removeFirst()) // 发送请求包 112 | } // 如果有请求包,就发送 113 | delay(10) // 没有就等待 114 | } 115 | } 116 | } 117 | }) 118 | .build()!! 119 | 120 | fun start(block: Boolean = false) { 121 | server.start() 122 | if (block) { 123 | server.awaitTermination() 124 | } 125 | } 126 | } 127 | 128 | fun main() { 129 | PassiveKritorServer(8080) 130 | .start(true) 131 | } 132 | ``` 133 | -------------------------------------------------------------------------------- /protos/event/notice_data.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.event; 10 | 11 | option csharp_namespace = "Kritor.Event"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.event"; 14 | option go_package = "grpc/kritor/event"; 15 | 16 | message PrivatePokeNotice { 17 | optional string operator_uid = 1; 18 | uint64 operator_uin = 2; 19 | string action = 3; 20 | string suffix = 4; 21 | string action_image = 5; 22 | } 23 | 24 | message PrivateRecallNotice { 25 | optional string operator_uid = 1; 26 | uint64 operator_uin = 2; 27 | string message_id = 3; 28 | string tip_text = 4; 29 | } 30 | 31 | message PrivateFileUploadedNotice { 32 | optional string operator_uid = 1; 33 | uint64 operator_uin = 2; 34 | string file_id = 3; 35 | int32 file_sub_id = 4; 36 | string file_name = 5; 37 | uint64 file_size = 6; 38 | uint64 expire_time = 7; 39 | string file_url = 8; 40 | } 41 | 42 | message GroupPokeNotice { 43 | uint64 group_id = 1; 44 | optional string operator_uid = 2; 45 | uint64 operator_uin = 3; 46 | optional string target_uid = 4; 47 | uint64 target_uin = 5; 48 | string action = 6; 49 | string suffix = 7; 50 | string action_image = 8; 51 | } 52 | 53 | message GroupRecallNotice { 54 | uint64 group_id = 1; 55 | optional string operator_uid = 2; 56 | uint64 operator_uin = 3; 57 | optional string target_uid = 4; 58 | uint64 target_uin = 5; 59 | string message_id = 6; 60 | string tip_text = 7; 61 | } 62 | 63 | message GroupFileUploadedNotice { 64 | uint64 group_id = 1; 65 | optional string operator_uid = 2; 66 | uint64 operator_uin = 3; 67 | string file_id = 4; 68 | string file_name = 5; 69 | uint64 file_size = 6; 70 | int32 file_sub_id = 7; 71 | uint64 expire_time = 8; 72 | string file_url = 9; 73 | } 74 | 75 | message GroupCardChangedNotice { 76 | uint64 group_id = 1; 77 | optional string operator_uid = 2; 78 | uint64 operator_uin = 3; 79 | optional string target_uid = 4; 80 | uint64 target_uin = 5; 81 | string new_card = 6; 82 | } 83 | 84 | message GroupUniqueTitleChangedNotice { 85 | uint64 group_id = 1; 86 | optional string target_uid = 2; 87 | uint64 target_uin = 3; 88 | string title = 4; 89 | } 90 | 91 | message GroupEssenceMessageNotice { 92 | uint64 group_id = 1; 93 | optional string operator_uid = 2; 94 | uint64 operator_uin = 3; 95 | optional string target_uid = 4; 96 | uint64 target_uin = 5; 97 | string message_id = 6; 98 | bool is_set = 7; 99 | } 100 | 101 | message GroupMemberIncreasedNotice { 102 | enum GroupMemberIncreasedType { 103 | UNSPECIFIED = 0; 104 | APPROVE = 1; 105 | INVITE = 2; 106 | } 107 | 108 | uint64 group_id = 1; 109 | optional string operator_uid = 2; 110 | uint64 operator_uin = 3; 111 | optional string target_uid = 4; 112 | uint64 target_uin = 5; 113 | GroupMemberIncreasedType type = 6; 114 | } 115 | 116 | message GroupMemberDecreasedNotice { 117 | enum GroupMemberDecreasedType { 118 | UNSPECIFIED = 0; 119 | LEAVE = 1; 120 | KICK = 2; 121 | KICK_ME = 3; 122 | } 123 | 124 | uint64 group_id = 1; 125 | optional string operator_uid = 2; // 当 type 不为 LEAVE 时提供 126 | optional uint64 operator_uin = 3; 127 | optional string target_uid = 4; // 当 type 不为 KICK_ME 时提供 128 | optional uint64 target_uin = 5; 129 | GroupMemberDecreasedType type = 6; 130 | } 131 | 132 | message GroupAdminChangedNotice { 133 | uint64 group_id = 1; 134 | optional string target_uid = 4; 135 | uint64 target_uin = 5; 136 | bool is_admin = 6; 137 | } 138 | 139 | message GroupSignInNotice { 140 | uint64 group_id = 1; 141 | optional string target_uid = 2; 142 | uint64 target_uin = 3; 143 | string action = 4; 144 | string rank_image = 6; 145 | } 146 | 147 | message GroupMemberBanNotice { 148 | enum GroupMemberBanType { 149 | UNSPECIFIED = 0; 150 | LIFT_BAN = 1; 151 | BAN = 2; 152 | } 153 | 154 | uint64 group_id = 1; 155 | optional string operator_uid = 2; 156 | uint64 operator_uin = 3; 157 | optional string target_uid = 4; 158 | uint64 target_uin = 5; 159 | int32 duration = 6; 160 | GroupMemberBanType type = 7; 161 | } 162 | 163 | message GroupWholeBanNotice { 164 | uint64 group_id = 1; 165 | optional string operator_uid = 2; 166 | uint64 operator_uin = 3; 167 | bool is_ban = 4; 168 | } 169 | 170 | message GroupReactMessageWithEmojiNotice { 171 | uint64 group_id = 1; 172 | string message_id = 2; 173 | uint32 face_id = 3; 174 | bool is_set = 4; 175 | } 176 | 177 | message GroupTransferNotice { 178 | uint64 group_id = 1; 179 | optional string operator_uid = 2; 180 | uint64 operator_uin = 3; 181 | optional string target_uid = 4; 182 | uint64 target_uin = 5; 183 | } 184 | 185 | message FriendIncreasedNotice { 186 | optional string friend_uid = 1; 187 | uint64 friend_uin = 2; 188 | optional string friend_nick = 3; 189 | } 190 | 191 | message FriendDecreasedNotice { 192 | optional string friend_uid = 1; 193 | uint64 friend_uin = 2; 194 | optional string friend_nick = 3; 195 | } 196 | -------------------------------------------------------------------------------- /docs/request/friend.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 好友服务 6 | 7 | 实现好友相关的服务,提供简化操作的接口。 8 | 9 | ## 基础信息 10 | 11 | - **服务名**: `FriendService` 12 | - **Java包名**: `io.kritor.friend` 13 | - **C#命名空间**: `Kritor.Friend` 14 | - **[source proto file](/protos/src/main/proto/kritor/friend/friend.proto)** 15 | 16 | ## 基础定义 17 | 18 | ### 好友信息 19 | 20 | ```protobuf 21 | message FriendInfo { 22 | optional string uid = 1; // uid 'u_*********' 23 | uint64 uin = 2; // qq 24 | string qid = 3; // qid 用户自定义的qid 如若没有则为空 25 | 26 | string nick = 4; // 名称 27 | string remark = 5; // 备注 28 | uint32 level = 6; // 等级 29 | uint32 age = 7; // 年龄 30 | uint32 vote_cnt = 8; // 赞数量 31 | int32 gender = 9; // 性别 可不提供 32 | int32 group_id = 10; // 好友分组id 33 | 34 | 35 | optional ExtInfo ext = 99; // 扩展信息,根据协议平台提供的扩展信息 36 | } 37 | 38 | message ProfileCard { 39 | optional string uid = 1; 40 | uint64 uin = 2; 41 | string qid = 3; 42 | 43 | string nick = 4; 44 | optional string remark = 5; 45 | uint32 level = 6; 46 | optional uint64 birthday = 7; 47 | uint32 login_day = 8; // 登录天数 48 | uint32 vote_cnt = 9; // 点赞数 49 | 50 | /* 以下字段可以不实现 */ 51 | optional bool is_school_verified = 51; 52 | optional ExtInfo ext = 99; // 扩展信息,根据协议平台提供的扩展信息 53 | } 54 | 55 | // 通用好友信息扩展字段 56 | // 所有第三方协议分发扩展字段, 57 | // 必须基于本字段修改, 58 | // 并保存定制的副本到本仓库特定路径!! 59 | message ExtInfo { 60 | optional bool big_vip = 1; // 大会员 61 | optional bool hollywood_vip = 2; // 好莱坞/腾讯视频会员 62 | optional bool qq_vip = 3; // QQ会员 63 | optional bool super_vip = 4; // QQ超级会员 64 | optional bool voted = 5; // 是否已经赞过 65 | } 66 | ``` 67 | 68 | ## 获取好友列表 69 | 70 | 获取好友列表。 71 | 72 | ### 参数 73 | 74 | - **方法名**: `GetFriendList` 75 | - **请求类型**: `GetFriendListRequest` 76 | - **响应类型**: `GetFriendListResponse` 77 | 78 | ### 请求与响应 79 | 80 | ```protobuf 81 | message GetFriendListRequest { 82 | optional bool refresh = 1; // 是否刷新好友列表 83 | } 84 | 85 | message GetFriendListResponse { 86 | repeated FriendData friendList = 1; 87 | } 88 | ``` 89 | 90 | ## 获取好友名片 91 | 92 | 获取好友的名片信息,该接口仅仅适用于好友。 93 | 94 | ### 参数 95 | 96 | - **方法名**: `GetFriendProfileCard` 97 | - **请求类型**: `GetFriendProfileCardRequest` 98 | - **响应类型**: `GetFriendProfileCardResponse` 99 | 100 | ### 请求与响应 101 | 102 | ```protobuf 103 | message GetFriendProfileCardRequest { 104 | repeated string target_uids = 1; 105 | repeated uint64 target_uins = 2; 106 | } 107 | 108 | message GetFriendProfileCardResponse { 109 | repeated ProfileCard friends_profile_card = 1; 110 | } 111 | ``` 112 | 113 | ## 获取陌生人信息 114 | 115 | 获取陌生人的信息,该接口适用于陌生人和好友。 116 | 117 | ### 参数 118 | 119 | - **方法名**: `GetStrangerProfileCard` 120 | - **请求类型**: `GetStrangerProfileCardRequest` 121 | - **响应类型**: `GetStrangerProfileCardResponse` 122 | 123 | ### 请求与响应 124 | 125 | ```protobuf 126 | message GetStrangerProfileCardRequest { 127 | repeated string target_uids = 1; 128 | repeated uint64 target_uins = 2; 129 | } 130 | 131 | message GetStrangerProfileCardResponse { 132 | repeated ProfileCard strangers_profile_card = 1; 133 | } 134 | ``` 135 | 136 | ## 设置Bot的名片信息 137 | 138 | 设置Bot的名片信息,该接口仅提供较为基础的设置操作。 139 | 140 | ### 参数 141 | 142 | - **方法名**: `SetProfileCard` 143 | - **请求类型**: `SetProfileCardRequest` 144 | - **响应类型**: `SetProfileCardResponse` 145 | 146 | ### 请求与响应 147 | 148 | ```protobuf 149 | message SetProfileCardRequest { 150 | optional string nick_name = 1; 151 | optional string company = 2; 152 | optional string email = 3; 153 | optional string college = 4; 154 | optional string personal_note = 5; 155 | optional uint32 birthday = 6; 156 | optional uint32 age = 7; 157 | } 158 | 159 | message SetProfileCardResponse { 160 | } 161 | ``` 162 | 163 | ## 是否是黑名单用户 164 | 165 | 判断是否是黑名单用户。 166 | 167 | ### 参数 168 | 169 | - **方法名**: `IsBlackListUser` 170 | - **请求类型**: `IsBlackListUserRequest` 171 | - **响应类型**: `IsBlackListUserResponse` 172 | 173 | ### 请求与响应 174 | 175 | ```protobuf 176 | message IsBlackListUserRequest { 177 | oneof target { 178 | string target_uid = 1; 179 | uint64 target_uin = 2; 180 | } 181 | } 182 | 183 | message IsBlackListUserResponse { 184 | bool is_black_list_user = 1; 185 | } 186 | ``` 187 | 188 | ## 点赞 189 | 190 | 点赞好友或陌生人。 191 | 192 | ### 参数 193 | 194 | - **方法名**: `VoteUser` 195 | - **请求类型**: `VoteUserRequest` 196 | - **响应类型**: `VoteUserResponse` 197 | 198 | ### 请求与响应 199 | 200 | ```protobuf 201 | message VoteUserRequest { 202 | oneof target { 203 | string target_uid = 1; 204 | uint64 target_uin = 2; 205 | } 206 | uint32 vote_count = 3; 207 | } 208 | 209 | message VoteUserResponse { 210 | } 211 | ``` 212 | 213 | ## 获取Uid通过QQ号(缓存) 214 | 215 | 获取Uid通过QQ号,通过Kritor端本地缓存。 216 | 217 | ### 参数 218 | 219 | - **方法名**: `GetUidByUin` 220 | - **请求类型**: `GetUidByUinRequest` 221 | - **响应类型**: `GetUidByUinResponse` 222 | 223 | ### 请求与响应 224 | 225 | ```protobuf 226 | message GetUidByUinRequest { 227 | repeated uint64 target_uins = 1; 228 | } 229 | 230 | message GetUidByUinResponse { 231 | map uid_map = 1; 232 | } 233 | ``` 234 | 235 | ## 获取Uin通过Uid(缓存) 236 | 237 | 获取Uin通过Uid,通过Kritor端本地缓存。 238 | 239 | ### 参数 240 | 241 | - **方法名**: `GetUinByUid` 242 | - **请求类型**: `GetUinByUidRequest` 243 | - **响应类型**: `GetUinByUidResponse` 244 | 245 | ### 请求与响应 246 | 247 | ```protobuf 248 | message GetUinByUidRequest { 249 | repeated string target_uids = 1; 250 | } 251 | 252 | message GetUinByUidResponse { 253 | map uin_map = 1; 254 | } 255 | ``` -------------------------------------------------------------------------------- /protos/message/message.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.message; 10 | 11 | option csharp_namespace = "Kritor.Message"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.message"; 14 | option go_package = "grpc/kritor/message"; 15 | 16 | import "common/contact.proto"; 17 | import "common/message_data.proto"; 18 | import "common/message_element.proto"; 19 | 20 | service MessageService { 21 | rpc SendMessage(SendMessageRequest) returns (SendMessageResponse); // 发送消息 22 | rpc SendMessageByResId(SendMessageByResIdRequest) returns (SendMessageByResIdResponse); // 通过资源ID发送消息(转发消息 23 | rpc SetMessageReaded(SetMessageReadRequest) returns (SetMessageReadResponse); // 清空本地聊天记录 24 | rpc RecallMessage(RecallMessageRequest) returns (RecallMessageResponse); // 撤回消息 25 | rpc ReactMessageWithEmoji(ReactMessageWithEmojiRequest) returns (ReactMessageWithEmojiResponse); // 设置消息评论表情 26 | 27 | rpc GetMessage(GetMessageRequest) returns (GetMessageResponse); // 获取消息 28 | rpc GetMessageBySeq(GetMessageBySeqRequest) returns (GetMessageBySeqResponse); // 获取消息 29 | rpc GetHistoryMessage(GetHistoryMessageRequest) returns (GetHistoryMessageResponse); // 获取历史消息 30 | rpc GetHistoryMessageBySeq(GetHistoryMessageBySeqRequest) returns (GetHistoryMessageBySeqResponse); // 获取历史消息 31 | 32 | rpc UploadForwardMessage(UploadForwardMessageRequest) returns (UploadForwardMessageResponse); // 上传合并转发消息 33 | rpc DownloadForwardMessage(DownloadForwardMessageRequest) returns (DownloadForwardMessageResponse); // 下载合并转发消息 34 | 35 | rpc GetEssenceMessageList(GetEssenceMessageListRequest) returns (GetEssenceMessageListResponse); // 获取精华消息 36 | rpc SetEssenceMessage(SetEssenceMessageRequest) returns (SetEssenceMessageResponse); // 设置精华消息 37 | rpc DeleteEssenceMessage(DeleteEssenceMessageRequest) returns (DeleteEssenceMessageResponse); // 删除精华消息 38 | } 39 | 40 | message SendMessageRequest { 41 | kritor.common.Contact contact = 1; // 发送目标 42 | repeated kritor.common.Element elements = 2; // 发的什么东西 43 | optional uint32 retry_count = 3; // 重试次数 44 | 45 | // passive_id 46 | optional string message_id = 4; 47 | optional string notice_id = 5; 48 | optional string request_id = 6; 49 | } 50 | 51 | message SendMessageResponse { 52 | string message_id = 1; // 发送成功后的消息ID 53 | uint64 message_time = 2; // 发送时间 54 | } 55 | 56 | message SendMessageByResIdRequest { 57 | kritor.common.Contact contact = 1; 58 | string res_id = 2; 59 | optional uint32 retry_count = 3; 60 | } 61 | 62 | message SendMessageByResIdResponse { 63 | string message_id = 1; 64 | uint64 message_time = 2; 65 | } 66 | 67 | message SetMessageReadRequest { 68 | kritor.common.Contact contact = 1; // 要清空的目标 69 | } 70 | 71 | message SetMessageReadResponse { 72 | } 73 | 74 | message RecallMessageRequest { 75 | kritor.common.Contact contact = 1; // 要撤回的目标,私聊则为对方,而不是写自己 76 | string message_id = 2; // 要撤回的消息ID 77 | } 78 | 79 | message RecallMessageResponse { 80 | } 81 | 82 | message ReactMessageWithEmojiRequest { 83 | kritor.common.Contact contact = 1; 84 | string message_id = 2; // 要设置的消息ID 85 | uint32 face_id = 3; // 表情ID 86 | bool is_set = 4; // 是否是评论,如果是false,则为撤销 87 | } 88 | 89 | message ReactMessageWithEmojiResponse { 90 | } 91 | 92 | message GetMessageRequest { 93 | kritor.common.Contact contact = 1; // 要获取的目标 94 | string message_id = 2; // 要获取的消息ID 95 | } 96 | 97 | message GetMessageResponse { 98 | kritor.common.PushMessageBody message = 1; // 获取到的消息 99 | } 100 | 101 | message GetMessageBySeqRequest { 102 | kritor.common.Contact contact = 1; // 要获取的目标 103 | uint64 message_seq = 2; // 要获取的消息序号 104 | } 105 | 106 | message GetMessageBySeqResponse { 107 | kritor.common.PushMessageBody message = 1; // 获取到的消息 108 | } 109 | 110 | message GetHistoryMessageRequest { 111 | kritor.common.Contact contact = 1; // 要获取的目标 112 | optional string start_message_id = 2; // 起始消息ID 默认最新一条开始 113 | optional uint32 count = 3; // 获取数量 默认10 114 | } 115 | 116 | message GetHistoryMessageResponse { 117 | repeated kritor.common.PushMessageBody messages = 1; // 获取到的消息 118 | } 119 | 120 | message GetHistoryMessageBySeqRequest { 121 | kritor.common.Contact contact = 1; // 要获取的目标 122 | optional uint64 start_message_seq = 2; // 起始消息ID 默认最新一条开始 123 | optional uint32 count = 3; // 获取数量 默认10 124 | } 125 | 126 | message GetHistoryMessageBySeqResponse { 127 | repeated kritor.common.PushMessageBody messages = 1; // 获取到的消息 128 | } 129 | 130 | message UploadForwardMessageRequest { 131 | kritor.common.Contact contact = 1; 132 | repeated kritor.common.ForwardMessageBody messages = 2; 133 | optional uint32 retry_count = 3; 134 | } 135 | 136 | message UploadForwardMessageResponse { 137 | string res_id = 1; 138 | } 139 | 140 | message DownloadForwardMessageRequest { 141 | string res_id = 1; // 资源ID 142 | } 143 | 144 | message DownloadForwardMessageResponse { 145 | repeated kritor.common.PushMessageBody messages = 1; // 获取到的消息 146 | } 147 | 148 | message GetEssenceMessageListRequest { 149 | uint64 group_id = 1; 150 | uint32 page = 2; 151 | uint32 page_size = 3; 152 | } 153 | 154 | message GetEssenceMessageListResponse { 155 | repeated kritor.common.EssenceMessageBody messages = 1; 156 | } 157 | 158 | message SetEssenceMessageRequest { 159 | uint64 group_id = 1; 160 | string message_id = 2; // 要设置为精华消息的消息ID 161 | } 162 | 163 | message SetEssenceMessageResponse { 164 | } 165 | 166 | message DeleteEssenceMessageRequest { 167 | uint64 group_id = 1; 168 | string message_id = 2; // 要删除的消息ID 169 | } 170 | 171 | message DeleteEssenceMessageResponse { 172 | } -------------------------------------------------------------------------------- /protos/guild/guild.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.guild; 10 | 11 | option csharp_namespace = "Kritor.Guild"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.guild"; 14 | option go_package = "grpc/kritor/guild"; 15 | 16 | import "guild/guild_data.proto"; 17 | 18 | service GuildService { 19 | rpc GetBotInfo(GetBotInfoRequest) returns (GetBotInfoResponse); // 获取BOT资料 20 | rpc GetChannelList(GetChannelListRequest) returns (GetChannelListResponse); // 获取频道列表 21 | rpc GetGuildMetaByGuest(GetGuildMetaByGuestRequest) returns (GetGuildMetaByGuestResponse); // 通过访客获取频道元数据 22 | rpc GetGuildChannelList(GetGuildChannelListRequest) returns (GetGuildChannelListResponse); // 获取子频道列表 23 | rpc GetGuildMemberList(GetGuildMemberListRequest) returns (GetGuildMemberListResponse); // 获取频道成员列表 24 | rpc GetGuildMember(GetGuildMemberRequest) returns (GetGuildMemberResponse); // 单独获取频道成员资料 25 | rpc SendChannelMessage(SendChannelMessageRequest) returns (SendChannelMessageResponse); // 发送信息到子频道 26 | rpc GetGuildFeedList(GetGuildFeedListRequest) returns (GetGuildFeedListResponse); // 获取频道帖子广场帖子 27 | rpc GetGuildRoleList(GetGuildRoleListRequest) returns (GetGuildRoleListResponse); // 获取频道角色列表 28 | rpc DeleteGuildRole(DeleteGuildRoleRequest) returns (DeleteGuildRoleResponse); // 删除频道身份组 29 | rpc SetGuildMemberRole(SetGuildMemberRoleRequest) returns (SetGuildMemberRoleResponse); // 设置用户在频道中的角色 30 | rpc UpdateGuildRole(UpdateGuildRoleRequest) returns (UpdateGuildRoleResponse); // 修改频道角色 31 | rpc CreateGuildRole(CreateGuildRoleRequest) returns (CreateGuildRoleResponse); // 创建频道角色 32 | } 33 | 34 | // 获取BOT资料请求 35 | message GetBotInfoRequest { 36 | } 37 | 38 | // 获取BOT资料响应 39 | message GetBotInfoResponse { 40 | string nickname = 1; // 昵称 41 | uint64 tiny_id = 2; // bot的频道id 42 | string avatar = 3; // 头像 43 | } 44 | 45 | // 获取频道列表请求 46 | message GetChannelListRequest { 47 | } 48 | 49 | // 获取频道列表响应 50 | message GetChannelListResponse { 51 | repeated GuildInfo get_guild_list = 1; // 频道列表 52 | } 53 | 54 | // 通过访客获取频道元数据请求 55 | message GetGuildMetaByGuestRequest { 56 | uint64 guild_id = 1; // 频道ID 57 | } 58 | 59 | // 通过访客获取频道元数据响应 60 | message GetGuildMetaByGuestResponse { 61 | uint64 guild_id = 1; // 频道ID 62 | string guild_name = 2; // 频道名称 63 | string guild_profile = 3; // 频道简介 64 | uint64 create_time = 4; // 创建时间 65 | uint64 max_member_count = 5; // 最大成员数量 66 | uint64 max_robot_count = 6; // 最大机器人数量 67 | uint64 max_admin_count = 7; // 最大管理员数量 68 | uint64 member_count = 8; // 当前成员数量 69 | uint64 owner_id = 9; // 频道所有者ID 70 | string guild_display_id = 10; // 频道显示ID 71 | } 72 | 73 | // 获取子频道列表请求 74 | message GetGuildChannelListRequest { 75 | uint64 guild_id = 1; // 频道ID 76 | bool refresh = 2; // 是否刷新数据,默认false 77 | } 78 | 79 | // 获取子频道列表响应 80 | message GetGuildChannelListResponse { 81 | repeated ChannelInfo channels_info = 1; // 子频道列表 82 | } 83 | 84 | // 获取频道成员列表请求 85 | message GetGuildMemberListRequest { 86 | uint64 guild_id = 1; // 频道ID 87 | string next_token = 2; // 不提供则从首页开始获取 88 | bool all = 3; // 是否一次性获取完所有成员,默认false 89 | bool refresh = 4; // 是否刷新数据,默认false 90 | } 91 | 92 | // 获取频道成员列表响应 93 | message GetGuildMemberListResponse { 94 | repeated MemberInfo members_info = 1; // 成员列表 95 | string next_token = 2; // 下一页的token 96 | bool finished = 3; // 是否已经获取完所有成员 97 | } 98 | 99 | // 单独获取频道成员资料请求 100 | message GetGuildMemberRequest { 101 | uint64 guild_id = 1; // 频道ID 102 | uint64 tiny_id = 2; // 成员tinyId 103 | } 104 | 105 | // 单独获取频道成员资料响应 106 | message GetGuildMemberResponse { 107 | MemberProfile member_info = 1; // 成员资料 108 | } 109 | 110 | // 发送信息到子频道请求 111 | message SendChannelMessageRequest { 112 | uint64 guild_id = 1; // 频道ID 113 | uint64 channel_id = 2; // 子频道ID 114 | string message = 3; // 消息体 115 | int32 retry_cnt = 4; // 最大重试次数 116 | int64 recall_duration = 5; // 自动撤回间隔 117 | } 118 | 119 | // 发送信息到子频道响应 120 | message SendChannelMessageResponse { 121 | string message_id = 1; // 消息ID 122 | uint64 message_time = 2; // 时间 123 | } 124 | 125 | // 获取频道帖子广场帖子请求 126 | message GetGuildFeedListRequest { 127 | uint64 guild_id = 1; // 频道ID 128 | uint32 from = 2; // 开始获取的位置 129 | } 130 | 131 | // 获取频道帖子广场帖子响应 132 | message GetGuildFeedListResponse { 133 | bytes data = 1; // 该请求携带了大量原生响应数据,无法详细介绍,请自行测试! 134 | } 135 | 136 | // 获取频道角色列表请求 137 | message GetGuildRoleListRequest { 138 | uint64 guild_id = 1; // 频道ID 139 | } 140 | 141 | // 获取频道角色列表响应 142 | message GetGuildRoleListResponse { 143 | repeated RoleInfo roles_info = 1; // 角色列表 144 | } 145 | 146 | // 删除频道身份组请求 147 | message DeleteGuildRoleRequest { 148 | uint64 guild_id = 1; // 频道ID 149 | uint64 role_id = 2; // 角色ID 150 | } 151 | 152 | // 删除频道身份组响应 153 | message DeleteGuildRoleResponse { 154 | // 无返回值 155 | } 156 | 157 | // 设置用户在频道中的角色 158 | message SetGuildMemberRoleRequest { 159 | uint64 guild_id = 1; // 频道ID 160 | uint64 role_id = 2; // 角色ID 161 | bool set = 3; // 设置还是移除,默认false 162 | repeated string tiny_ids = 4; // 用户tinyId列表 163 | } 164 | 165 | // 设置用户在频道中的角色响应 166 | message SetGuildMemberRoleResponse { 167 | // 无返回值 168 | } 169 | 170 | // 修改频道角色请求 171 | message UpdateGuildRoleRequest { 172 | uint64 guild_id = 1; // 频道ID 173 | uint64 role_id = 2; // 角色ID 174 | string name = 3; // 名称 175 | int64 color = 4; // 颜色ARGB 176 | } 177 | 178 | // 修改频道角色响应 179 | message UpdateGuildRoleResponse { 180 | // 无返回值 181 | } 182 | 183 | // 创建频道角色请求 184 | message CreateGuildRoleRequest { 185 | uint64 guild_id = 1; // 频道ID 186 | string name = 2; // 名称 187 | int64 color = 3; // 颜色ARGB 188 | } 189 | 190 | // 创建频道角色响应 191 | message CreateGuildRoleResponse { 192 | uint64 role_id = 1; // 角色ID 193 | } 194 | -------------------------------------------------------------------------------- /protos/common/message_element.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.common; 10 | 11 | option csharp_namespace = "Kritor.Common"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.common"; 14 | option go_package = "grpc/kritor/common"; 15 | 16 | import "common/contact.proto"; 17 | 18 | message Element { 19 | enum ElementType { 20 | UNSPECIFIED = 0; 21 | TEXT = 1; 22 | AT = 2; 23 | FACE = 3; 24 | BUBBLE_FACE = 4; 25 | REPLY = 5; 26 | IMAGE = 6; 27 | VOICE = 7; 28 | VIDEO = 8; 29 | BASKETBALL = 9; 30 | DICE = 10; 31 | RPS = 11; 32 | POKE = 12; 33 | MUSIC = 13; 34 | WEATHER = 14; 35 | LOCATION = 15; 36 | SHARE = 16; 37 | GIFT = 17; 38 | MARKET_FACE = 18; 39 | FORWARD = 19; 40 | CONTACT = 20; 41 | JSON = 21; 42 | XML = 22; 43 | FILE = 23; 44 | MARKDOWN = 24; 45 | KEYBOARD = 25; 46 | } 47 | 48 | // be friendly to some languages that don't support oneof 49 | ElementType type = 1; 50 | oneof data { 51 | TextElement text = 2; 52 | AtElement at = 3; 53 | FaceElement face = 4; 54 | BubbleFaceElement bubble_face = 5; 55 | ReplyElement reply = 6; 56 | ImageElement image = 7; 57 | VoiceElement voice = 8; 58 | VideoElement video = 9; 59 | BasketballElement basketball = 10; 60 | DiceElement dice = 11; 61 | RpsElement rps = 12; 62 | PokeElement poke = 13; 63 | MusicElement music = 14; 64 | WeatherElement weather = 15; 65 | LocationElement location = 16; 66 | ShareElement share = 17; 67 | GiftElement gift = 18; 68 | MarketFaceElement market_face = 19; 69 | ForwardElement forward = 20; 70 | ContactElement contact = 21; 71 | JsonElement json = 22; 72 | XmlElement xml = 23; 73 | FileElement file = 24; 74 | MarkdownElement markdown = 25; 75 | KeyboardElement keyboard = 26; 76 | } 77 | } 78 | 79 | message TextElement { 80 | string text = 1; // 文本 81 | } 82 | 83 | message AtElement { 84 | optional string uid = 1; // 全体成员这里请写all 85 | optional uint64 uin = 2; 86 | } 87 | 88 | message FaceElement { 89 | uint32 id = 1; // 表情id 90 | optional bool is_big = 2; // 是否大表情,默认不是 91 | optional uint32 result = 3; 92 | } 93 | 94 | message BubbleFaceElement { 95 | uint32 id = 1; // 表情id 96 | uint32 count = 2; // 表情数量 97 | } 98 | 99 | message ReplyElement { 100 | string message_id = 1; // 回复的消息id 101 | } 102 | 103 | message ImageElement { 104 | enum ImageType { 105 | UNSPECIFIED = 0; 106 | COMMON = 1; 107 | ORIGIN = 2; 108 | FLASH = 3; 109 | } 110 | 111 | oneof data { 112 | bytes file = 1; // 文件内容 113 | string file_name = 2; // 文件文件名 114 | string file_path = 3; // 文件绝对路径 115 | string file_url = 4; // 文件下载地址 116 | } 117 | optional string file_md5 = 5; 118 | optional uint32 sub_type = 6; 119 | optional ImageType file_type = 10; 120 | } 121 | 122 | message VoiceElement { 123 | oneof data { 124 | bytes file = 1; // 文件内容 125 | string file_name = 2; // 文件文件名 126 | string file_path = 3; // 文件绝对路径 127 | string file_url = 4; // 文件下载地址 128 | } 129 | optional string file_md5 = 5; 130 | optional bool magic = 6; // 是否魔法语音 131 | } 132 | 133 | message VideoElement { 134 | oneof data { 135 | bytes file = 1; // 文件内容 136 | string file_name = 2; // 文件名 137 | string file_path = 3; // 文件绝对路径 138 | string file_url = 4; // 文件下载地址 139 | } 140 | optional string file_md5 = 5; 141 | } 142 | 143 | message BasketballElement { 144 | uint32 id = 1; 145 | } // NT改版,这类消息的值由服务器随机生成 146 | 147 | message DiceElement { uint32 id = 1; } 148 | 149 | message RpsElement { uint32 id = 1; } 150 | 151 | message PokeElement { 152 | uint32 id = 1; // 戳一戳id 153 | uint32 poke_type = 2; // 戳一戳类型 154 | uint32 strength = 3; // 戳一戳强度 155 | } 156 | 157 | message CustomMusicData { 158 | string url = 1; 159 | string audio = 2; 160 | string title = 3; 161 | string author = 4; 162 | string pic = 5; 163 | } 164 | 165 | message MusicElement { 166 | enum MusicPlatform { 167 | UNSPECIFIED = 0; 168 | QQ = 1; 169 | NETEASE = 2; 170 | CUSTOM = 11; 171 | } 172 | 173 | MusicPlatform platform = 1; 174 | oneof data { 175 | string id = 2; 176 | CustomMusicData custom = 3; 177 | } 178 | } 179 | 180 | message WeatherElement { 181 | string city = 1; 182 | string code = 2; 183 | } 184 | 185 | message LocationElement { 186 | float lat = 1; 187 | float lon = 2; 188 | string title = 3; 189 | string address = 4; 190 | } 191 | 192 | message ShareElement { 193 | string url = 1; 194 | string title = 2; 195 | string content = 3; 196 | string image = 4; 197 | } 198 | 199 | message GiftElement { 200 | uint64 qq = 1; 201 | uint32 id = 2; 202 | } // 不支持发送 203 | 204 | message MarketFaceElement { string id = 1; } 205 | 206 | message ForwardElement { 207 | string res_id = 1; 208 | string uniseq = 2; 209 | string summary = 3; 210 | string description = 4; 211 | } 212 | 213 | message ContactElement { 214 | Scene scene = 1; 215 | string peer = 2; 216 | } 217 | 218 | message JsonElement { string json = 1; } 219 | 220 | message XmlElement { string xml = 1; } 221 | 222 | message FileElement { 223 | optional string name = 1; 224 | optional uint64 size = 2; 225 | optional uint64 expire_time = 3; 226 | optional string id = 4; 227 | optional string url = 5; 228 | optional int32 biz = 6; 229 | optional string sub_id = 7; 230 | } // 不支持通过这里发送 231 | 232 | message MarkdownElement { string markdown = 1; } 233 | 234 | message ButtonActionPermission { 235 | int32 type = 1; 236 | repeated string role_ids = 2; 237 | repeated string user_ids = 3; 238 | } 239 | 240 | message ButtonAction { 241 | int32 type = 1; 242 | ButtonActionPermission permission = 2; 243 | string unsupported_tips = 3; 244 | string data = 4; 245 | bool reply = 5; 246 | bool enter = 6; 247 | } 248 | 249 | message ButtonRender { 250 | string label = 1; 251 | string visited_label = 2; 252 | int32 style = 3; 253 | } 254 | 255 | message Button { 256 | string id = 1; 257 | ButtonRender render_data = 2; 258 | ButtonAction action = 3; 259 | } 260 | 261 | message KeyboardRow { repeated Button buttons = 1; } 262 | 263 | message KeyboardElement { 264 | repeated KeyboardRow rows = 1; 265 | uint64 bot_appid = 2; 266 | } -------------------------------------------------------------------------------- /protos/group/group.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | package kritor.group; 10 | 11 | option csharp_namespace = "Kritor.Group"; 12 | option java_multiple_files = true; 13 | option java_package = "io.kritor.group"; 14 | option go_package = "grpc/kritor/group"; 15 | 16 | import "group/group_data.proto"; 17 | 18 | service GroupService { 19 | rpc BanMember(BanMemberRequest) returns (BanMemberResponse); // 禁言用户 20 | rpc PokeMember(PokeMemberRequest) returns (PokeMemberResponse); // 戳一戳用户 21 | rpc KickMember(KickMemberRequest) returns (KickMemberResponse); // 踢出用户 22 | rpc LeaveGroup(LeaveGroupRequest) returns (LeaveGroupResponse); // 退出群组 23 | rpc ModifyMemberCard(ModifyMemberCardRequest) returns (ModifyMemberCardResponse); // 修改群名片 24 | rpc ModifyGroupName(ModifyGroupNameRequest) returns (ModifyGroupNameResponse); // 修改群名称 25 | rpc ModifyGroupRemark(ModifyGroupRemarkRequest) returns (ModifyGroupRemarkResponse); // 修改群备注 26 | rpc SetGroupAdmin(SetGroupAdminRequest) returns (SetGroupAdminResponse); // 设置群管理员 27 | rpc SetGroupUniqueTitle(SetGroupUniqueTitleRequest) returns (SetGroupUniqueTitleResponse); // 设置群头衔 28 | rpc SetGroupWholeBan(SetGroupWholeBanRequest) returns (SetGroupWholeBanResponse); // 设置全员禁言 29 | 30 | rpc GetGroupInfo(GetGroupInfoRequest) returns (GetGroupInfoResponse); // 获取群信息 31 | rpc GetGroupList(GetGroupListRequest) returns (GetGroupListResponse); // 获取群列表 32 | rpc GetGroupMemberInfo(GetGroupMemberInfoRequest) returns (GetGroupMemberInfoResponse); // 获取群成员信息 33 | rpc GetGroupMemberList(GetGroupMemberListRequest) returns (GetGroupMemberListResponse); // 获取群成员列表 34 | 35 | rpc GetProhibitedUserList(GetProhibitedUserListRequest) returns (GetProhibitedUserListResponse); // 获取禁言用户列表 36 | rpc GetRemainCountAtAll(GetRemainCountAtAllRequest) returns (GetRemainCountAtAllResponse); // 获取艾特全体成员剩余次数 37 | rpc GetNotJoinedGroupInfo(GetNotJoinedGroupInfoRequest) returns (GetNotJoinedGroupInfoResponse); // 获取未加入群组信息 38 | rpc GetGroupHonor(GetGroupHonorRequest) returns (GetGroupHonorResponse); // 获取群荣誉信息 39 | 40 | rpc UploadGroupFile(UploadGroupFileRequest) returns (UploadGroupFileResponse); // 上传群文件 41 | } 42 | 43 | message BanMemberRequest { 44 | uint64 group_id = 1; // 群组ID 45 | oneof target{ 46 | string target_uid = 2; // 被禁言目标uid 47 | uint64 target_uin = 3; // 被禁言目标uin 48 | } 49 | uint32 duration = 4; // 单位:秒 50 | } 51 | 52 | message BanMemberResponse { 53 | } 54 | 55 | message PokeMemberRequest { 56 | uint64 group_id = 1; // 群组ID 57 | oneof target{ 58 | string target_uid = 2; // 被戳一戳目标uid 59 | uint64 target_uin = 3; // 被戳一戳目标uin 60 | } 61 | } 62 | 63 | message PokeMemberResponse { 64 | } 65 | 66 | message KickMemberRequest { 67 | uint64 group_id = 1; // 群组ID 68 | oneof target{ 69 | string target_uid = 2; // 被踢出目标uid 70 | uint64 target_uin = 3; // 被踢出目标uin 71 | } 72 | optional bool reject_add_request = 6; // 是否拒绝再次申请 默认false 73 | optional string kick_reason = 5; // 踢出原因,可选 74 | } 75 | 76 | message KickMemberResponse { 77 | } 78 | 79 | message LeaveGroupRequest { 80 | uint64 group_id = 1; // 群组ID 81 | } 82 | 83 | message LeaveGroupResponse { 84 | } 85 | 86 | message ModifyMemberCardRequest { 87 | uint64 group_id = 1; // 群组ID 88 | oneof target{ 89 | string target_uid = 2; // 目标uid 90 | uint64 target_uin = 3; // 目标uin 91 | } 92 | string card = 4; // 新的群名片 93 | } 94 | 95 | message ModifyMemberCardResponse { 96 | } 97 | 98 | message ModifyGroupNameRequest { 99 | uint64 group_id = 1; // 群组ID 100 | string group_name = 2; // 新的群名称 101 | } 102 | 103 | message ModifyGroupNameResponse { 104 | } 105 | 106 | message ModifyGroupRemarkRequest { 107 | uint64 group_id = 1; // 群组ID 108 | string remark = 2; // 新的群备注 109 | } 110 | 111 | message ModifyGroupRemarkResponse { 112 | } 113 | 114 | message SetGroupAdminRequest { 115 | uint64 group_id = 1; // 群组ID 116 | oneof target{ 117 | string target_uid = 2; // 目标uid 118 | uint64 target_uin = 3; // 目标uin 119 | } 120 | bool is_admin = 4; // 是否设置为管理员 121 | } 122 | 123 | message SetGroupAdminResponse { 124 | } 125 | 126 | message SetGroupUniqueTitleRequest { 127 | uint64 group_id = 1; // 群组ID 128 | oneof target{ 129 | string target_uid = 2; // 目标uid 130 | uint64 target_uin = 3; // 目标uin 131 | } 132 | string unique_title = 4; // 新的群头衔 133 | } 134 | 135 | message SetGroupUniqueTitleResponse { 136 | } 137 | 138 | message SetGroupWholeBanRequest { 139 | uint64 group_id = 1; // 群组ID 140 | bool is_ban = 2; // 是否全员禁言 141 | } 142 | 143 | message SetGroupWholeBanResponse { 144 | } 145 | 146 | message GetGroupInfoRequest { 147 | uint64 group_id = 1; // 群组ID 148 | } 149 | 150 | message GetGroupInfoResponse { 151 | GroupInfo group_info = 1; // 群组信息 152 | } 153 | 154 | message GetGroupListRequest { 155 | optional bool refresh = 1; // 是否刷新缓存 156 | } 157 | 158 | message GetGroupListResponse { 159 | repeated GroupInfo groups_info = 1; // 群组信息 160 | } 161 | 162 | message GetGroupMemberInfoRequest { 163 | uint64 group_id = 1; // 群组ID 164 | oneof target{ 165 | string target_uid = 2; // 获取目标uid 166 | uint64 target_uin = 3; // 获取目标uin 167 | } 168 | optional bool refresh = 4; // 是否刷新缓存 169 | } 170 | 171 | message GetGroupMemberInfoResponse { 172 | GroupMemberInfo group_member_info = 1; // 群成员信息 173 | } 174 | 175 | message GetGroupMemberListRequest { 176 | uint64 group_id = 1; // 群组ID 177 | optional bool refresh = 2; // 是否刷新缓存 178 | } 179 | 180 | message GetGroupMemberListResponse { 181 | repeated GroupMemberInfo group_members_info = 1; // 群成员信息 182 | } 183 | 184 | message GetProhibitedUserListRequest { 185 | uint64 group_id = 1; // 群组ID 186 | } 187 | 188 | message GetProhibitedUserListResponse { 189 | repeated ProhibitedUserInfo prohibited_users_info = 1; // 禁言用户信息 190 | } 191 | 192 | message GetRemainCountAtAllRequest { 193 | uint64 group_id = 1; // 群组ID 194 | } 195 | 196 | message GetRemainCountAtAllResponse { 197 | bool access_at_all = 1; 198 | uint32 remain_count_for_group = 2; // 剩余次数对于全群 199 | uint32 remain_count_for_self = 3; // 剩余次数对于自己 200 | } 201 | 202 | message GetNotJoinedGroupInfoRequest { 203 | uint64 group_id = 1; // 群号 204 | } 205 | 206 | message GetNotJoinedGroupInfoResponse { 207 | NotJoinedGroupInfo group_info = 1; // 未加入群组信息 208 | } 209 | 210 | message GetGroupHonorRequest { 211 | uint64 group_id = 1; // 群号 212 | optional bool refresh = 2; // 是否刷新缓存 213 | } 214 | 215 | message GetGroupHonorResponse { 216 | repeated GroupHonorInfo group_honors_info = 1; // 群荣誉信息 217 | } 218 | 219 | message UploadGroupFileRequest { 220 | uint64 group_id = 1; // 群号 221 | string file = 2; // 本地文件绝对路径 222 | string name = 3; // 文件名称 223 | optional string folder = 4; // 父目录ID 不提供则上传到根目录 224 | } 225 | 226 | message UploadGroupFileResponse { 227 | string file_id = 1; // 文件ID 228 | string file_url = 2; // 文件URL 229 | optional string file_name = 3; // 文件名 230 | optional string file_size = 4; // 文件大小 231 | optional string file_bizid = 5; // 文件bizid 232 | optional string file_sha = 6; // 文件sha 233 | optional string file_md5 = 7; // 文件md5 234 | } -------------------------------------------------------------------------------- /docs/request/message.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 消息接口服务 6 | 7 | 提供发消息,获取消息相关的服务。 8 | 9 | ## 基础信息 10 | 11 | - **服务名**: `MessageService` 12 | - **Java包名**: `io.kritor.message` 13 | - **C#命名空间**: `Kritor.Message` 14 | - **[source proto file](/protos/src/main/proto/kritor/message/message.proto)** 15 | 16 | ## 基础定义 17 | 18 | ### 消息元素 19 | 20 | ```protobuf 21 | enum ElementType { 22 | TEXT = 0; 23 | AT = 1; 24 | FACE = 2; 25 | BUBBLE_FACE = 3; 26 | REPLY = 4; 27 | IMAGE = 5; 28 | VOICE = 6; 29 | VIDEO = 7; 30 | BASKETBALL = 8; 31 | DICE = 9; 32 | RPS = 10; 33 | POKE = 11; 34 | MUSIC = 12; 35 | WEATHER = 13; 36 | LOCATION = 14; 37 | SHARE = 15; 38 | GIFT = 16; 39 | MARKET_FACE = 17; 40 | FORWARD = 18; 41 | CONTACT = 19; 42 | JSON = 20; 43 | XML = 21; 44 | FILE = 22; 45 | MARKDOWN = 23; 46 | BUTTON = 24; 47 | NODE = 99; 48 | } 49 | 50 | message Element { 51 | ElementType type = 1; 52 | oneof data { 53 | // ... 省略 ... 54 | } 55 | } 56 | ``` 57 | 58 | 如果需要详细的消息元素内容,请参考[消息元素](/protos/src/main/proto/kritor/message/comm_message.proto)。 59 | 60 | ## 发送消息 61 | 62 | 发送消息到指定的聊天窗口。 63 | 64 | ### 参数 65 | 66 | - **方法名**: `SendMessage` 67 | - **请求类型**: `SendMessageRequest` 68 | - **响应类型**: `SendMessageResponse` 69 | 70 | ### 请求与响应 71 | 72 | ```protobuf 73 | message SendMessageRequest { 74 | kritor.common.Contact contact = 1; // 发送目标 75 | repeated kritor.common.Element elements = 2; // 发的什么东西 76 | optional uint32 retry_count = 3; // 重试次数 77 | } 78 | 79 | message SendMessageResponse { 80 | string message_id = 1; // 发送成功后的消息ID 81 | uint32 message_time = 2; // 发送时间 82 | } 83 | ``` 84 | 85 | ## 通过ResID发送消息 86 | 87 | 通过ResID发送消息到指定的聊天窗口。 88 | 89 | ### 参数 90 | 91 | - **方法名**: `SendMessageByResId` 92 | - **请求类型**: `SendMessageByResIdRequest` 93 | - **响应类型**: `SendMessageByResIdResponse` 94 | 95 | ### 请求与响应 96 | 97 | ```protobuf 98 | message SendMessageByResIdRequest { 99 | kritor.common.Contact contact = 1; // 发送目标 100 | string res_id = 2; // 资源ID 101 | optional uint32 retry_count = 3; // 重试次数 102 | } 103 | 104 | message SendMessageByResIdResponse { 105 | string message_id = 1; // 发送成功后的消息ID 106 | uint32 message_time = 2; // 发送时间 107 | } 108 | ``` 109 | 110 | ## 置消息已读 111 | 112 | 将指定会话的消息设置为已读状态。 113 | 114 | ### 参数 115 | 116 | - **方法名**: `SetMessageRead` 117 | - **请求类型**: `SetMessageReadRequest` 118 | - **响应类型**: `SetMessageReadResponse` 119 | 120 | ### 请求与响应 121 | 122 | ```protobuf 123 | message SetMessageReadRequest { 124 | kritor.common.Contact contact = 1; // 要清空的目标 125 | } 126 | 127 | message SetMessageReadResponse { 128 | } 129 | ``` 130 | 131 | ## 撤回消息 132 | 133 | 撤回指定的消息。 134 | 135 | ### 参数 136 | 137 | - **方法名**: `RecallMessage` 138 | - **请求类型**: `RecallMessageRequest` 139 | - **响应类型**: `RecallMessageResponse` 140 | 141 | ### 请求与响应 142 | 143 | ```protobuf 144 | message RecallMessageRequest { 145 | Contact contact = 1; // 要撤回的目标,私聊则为对方,而不是写自己 146 | uint64 message_id = 2; // 要撤回的消息ID,消息id固有格式:前32bit为时间戳,后32bit为扩展字段,可携带聊天类型等各种信息 147 | } 148 | 149 | message RecallMessageResponse { 150 | } 151 | ``` 152 | 153 | ## 在消息下回应表情 154 | 155 | 在消息的底下回应一个表情。 156 | 157 | ### 参数 158 | 159 | - **方法名**: `SetMessageCommentEmoji` 160 | - **请求类型**: `ReactMessageWithEmojiRequest` 161 | - **响应类型**: `ReactMessageWithEmojiResponse` 162 | 163 | ### 请求与响应 164 | 165 | ```protobuf 166 | message ReactMessageWithEmojiRequest { 167 | kritor.common.Contact contact = 1; 168 | string message_id = 2; // 要设置的消息ID 169 | uint32 face_id = 3; // 表情ID 170 | bool is_comment = 4; // 是否是评论,如果是false,则为撤销 171 | } 172 | 173 | message ReactMessageWithEmojiResponse { 174 | } 175 | ``` 176 | 177 | ## 获取消息 178 | 179 | 获取指定消息。 180 | 181 | ### 参数 182 | 183 | - **方法名**: `GetMessage` 184 | - **请求类型**: `GetMessageRequest` 185 | - **响应类型**: `GetMessageResponse` 186 | 187 | ### 请求与响应 188 | 189 | ```protobuf 190 | message GetMessageRequest { 191 | kritor.common.Contact contact = 1; // 要获取的目标 192 | string message_id = 2; // 要获取的消息ID 193 | } 194 | 195 | message GetMessageResponse { 196 | kritor.common.PushMessageBody message = 1; // 获取到的消息 197 | } 198 | ``` 199 | 200 | ## 通过`seq`获取消息 201 | 202 | 通过`seq`获取指定消息。 203 | 204 | ### 参数 205 | 206 | - **方法名**: `GetMessageBySeq` 207 | - **请求类型**: `GetMessageBySeqRequest` 208 | - **响应类型**: `GetMessageBySeqResponse` 209 | 210 | ### 请求与响应 211 | 212 | ```protobuf 213 | message GetMessageBySeqRequest { 214 | kritor.common.Contact contact = 1; // 要获取的目标 215 | uint64 message_seq = 2; // 要获取的消息序号 216 | } 217 | 218 | message GetMessageBySeqResponse { 219 | kritor.common.PushMessageBody message = 1; // 获取到的消息 220 | } 221 | ``` 222 | 223 | ## 获取历史消息 224 | 225 | 获取指定目标的历史消息。 226 | 227 | ### 参数 228 | 229 | - **方法名**: `GetHistoryMessage` 230 | - **请求类型**: `GetHistoryMessageRequest` 231 | - **响应类型**: `GetHistoryMessageResponse` 232 | 233 | ### 请求与响应 234 | 235 | ```protobuf 236 | message GetHistoryMessageRequest { 237 | kritor.common.Contact contact = 1; // 要获取的目标 238 | optional string start_message_id = 2; // 起始消息ID 默认最新一条开始 239 | optional uint32 count = 3; // 获取数量 默认10 240 | } 241 | 242 | message GetHistoryMessageResponse { 243 | repeated kritor.common.PushMessageBody messages = 1; // 获取到的消息 244 | } 245 | ``` 246 | 247 | ## 上传合并转发消息 248 | 249 | 上传合并转发消息。 250 | 251 | ### 参数 252 | 253 | - **方法名**: `UploadForwardMessage` 254 | - **请求类型**: `UploadForwardMessageRequest` 255 | - **响应类型**: `UploadForwardMessageResponse` 256 | 257 | ### 请求与响应 258 | 259 | ```protobuf 260 | message UploadForwardMessageRequest { 261 | kritor.common.Contact contact = 1; 262 | repeated kritor.common.ForwardMessageBody messages = 2; 263 | optional uint32 retry_count = 3; 264 | } 265 | 266 | message UploadForwardMessageResponse { 267 | string res_id = 1; 268 | } 269 | ``` 270 | 271 | ## 获取合并转发消息 272 | 273 | 获取合并转发消息。 274 | 275 | ### 参数 276 | 277 | - **方法名**: `DownloadForwardMessage` 278 | - **请求类型**: `DownloadForwardMessageRequest` 279 | - **响应类型**: `DownloadForwardMessageResponse` 280 | 281 | ### 请求与响应 282 | 283 | ```protobuf 284 | message DownloadForwardMessageResponse { 285 | repeated kritor.common.PushMessageBody messages = 1; // 获取到的消息 286 | } 287 | 288 | message DeleteEssenceMessageRequest { 289 | uint64 group_id = 1; 290 | string message_id = 2; // 要删除的消息ID 291 | } 292 | ``` 293 | ## 获取群精华消息列表 294 | 295 | 获取群精华消息列表。 296 | 297 | ### 参数 298 | 299 | - **方法名**: `GetEssenceMessages` 300 | - **请求类型**: `GetEssenceMessagesRequest` 301 | - **响应类型**: `GetEssenceMessagesResponse` 302 | 303 | ### 请求与响应 304 | 305 | ```protobuf 306 | message GetEssenceMessageListRequest { 307 | uint64 group_id = 1; 308 | uint32 page = 2; 309 | uint32 page_size = 3; 310 | } 311 | 312 | message GetEssenceMessageListResponse { 313 | repeated kritor.common.EssenceMessageBody messages = 1; 314 | } 315 | ``` 316 | 317 | ## 设置群精华消息 318 | 319 | 设置群精华消息。 320 | 321 | ### 参数 322 | 323 | - **方法名**: `SetEssenceMessage` 324 | - **请求类型**: `SetEssenceMessageRequest` 325 | - **响应类型**: `SetEssenceMessageResponse` 326 | 327 | ### 请求与响应 328 | 329 | ```protobuf 330 | message SetEssenceMessageRequest { 331 | uint64 group_id = 1; 332 | string message_id = 2; // 要设置为精华消息的消息ID 333 | } 334 | 335 | message SetEssenceMessageResponse { 336 | } 337 | ``` 338 | 339 | ## 删除群精华消息 340 | 341 | 删除群精华消息。 342 | 343 | ### 参数 344 | 345 | - **方法名**: `DeleteEssenceMsg` 346 | - **请求类型**: `DeleteEssenceMsgRequest` 347 | - **响应类型**: `DeleteEssenceMsgResponse` 348 | 349 | ### 请求与响应 350 | 351 | ```protobuf 352 | message DeleteEssenceMsgRequest { 353 | uint64 group_id = 1; 354 | uint64 message_id = 2; // 要删除的消息ID 355 | } 356 | 357 | message DeleteEssenceMsgResponse { 358 | } 359 | ``` 360 | -------------------------------------------------------------------------------- /docs/request/group.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 群聊服务 6 | 7 | 实现群聊相关的服务,提供简化操作的群管理接口。 8 | 9 | ## 基础信息 10 | 11 | - **服务名**: `GroupService` 12 | - **Java包名**: `io.kritor.group` 13 | - **C#命名空间**: `Kritor.Group` 14 | - **[source proto file](/protos/src/main/proto/kritor/group/group.proto)** 15 | 16 | ## 基础定义 17 | 18 | ```protobuf 19 | message GroupInfo { 20 | uint64 group_id = 1; 21 | string group_name = 2; 22 | string group_remark = 3; 23 | uint64 owner = 4; 24 | repeated uint64 admins = 5; 25 | uint32 max_member_count = 6; 26 | uint32 member_count = 7; 27 | uint64 group_uin = 10; 28 | } 29 | 30 | message NotJoinedGroupInfo { 31 | uint64 group_id = 1; 32 | uint32 max_member_count = 2; 33 | uint32 member_count = 3; 34 | string group_name = 4; 35 | string group_desc = 5; 36 | uint64 owner = 6; 37 | uint32 create_time = 7; 38 | 39 | uint32 group_flag = 8; // 群聊类型什么的都在这里,如果获取不到可以不实现 40 | uint32 group_flag_ext = 9; // 扩展群聊类型 41 | } 42 | 43 | message ProhibitedUserInfo { 44 | optional string uid = 1; 45 | uint64 uin = 2; 46 | uint32 prohibited_time = 3; 47 | } 48 | 49 | message GroupHonorInfo { 50 | optional string uid = 1; // 荣誉成员uid 51 | uint64 uin = 2; // 荣誉成员uin 52 | string nick = 3; // 荣誉成员昵称 53 | string honor_name = 4; // 荣誉名称 54 | string avatar = 5; // 荣誉图标url 55 | uint32 id = 6; // 荣誉id 56 | string description = 7; // 荣誉描述 57 | } 58 | 59 | enum MemberRole { 60 | ADMIN = 0; 61 | MEMBER = 1; 62 | OWNER = 2; 63 | STRANGER = 3; 64 | } 65 | 66 | message GroupMemberInfo { 67 | optional string uid = 1; 68 | uint64 uin = 2; 69 | string nick = 3; 70 | uint32 age = 4; 71 | string unique_title = 5; 72 | uint32 unique_title_expire_time = 6; 73 | string card = 7; 74 | uint64 join_time = 8; 75 | uint64 last_active_time = 9; 76 | uint32 level = 10; 77 | uint64 shut_up_timestamp = 11; 78 | 79 | optional uint32 distance = 100; 80 | repeated uint32 honors = 101; 81 | optional bool unfriendly = 102; 82 | optional bool card_changeable = 103; 83 | } 84 | ``` 85 | 86 | ## 禁言用户 87 | 88 | 禁言用户,时间的单位一般是秒,时间为0则为解除禁言。 89 | 90 | ### 参数 91 | 92 | - **方法名**: `BanMember` 93 | - **请求类型**: `BanMemberRequest` 94 | - **响应类型**: `BanMemberResponse` 95 | 96 | ### 请求与响应 97 | 98 | ```protobuf 99 | message BanMemberRequest { 100 | uint64 group_id = 1; // 群组ID 101 | oneof target{ 102 | string target_uid = 2; // 被禁言目标uid 103 | uint64 target_uin = 3; // 被禁言目标uin 104 | } 105 | uint64 duration = 4; // 禁言时长(单位:秒) 106 | } 107 | 108 | message BanMemberResponse { 109 | } 110 | ``` 111 | 112 | ## 戳一戳用户头像 113 | 114 | 戳一戳用户头像。 115 | 116 | ### 参数 117 | 118 | - **方法名**: `PokeMember` 119 | - **请求类型**: `PokeMemberRequest` 120 | - **响应类型**: `PokeMemberResponse` 121 | 122 | ### 请求与响应 123 | 124 | ```protobuf 125 | message PokeMemberRequest { 126 | uint64 group_id = 1; // 群组ID 127 | oneof target{ 128 | string target_uid = 2; // 被戳目标uid 129 | uint64 target_uin = 3; // 被戳目标uin 130 | } 131 | } 132 | 133 | message PokeMemberResponse { 134 | } 135 | ``` 136 | 137 | ## 踢出群成员 138 | 139 | 踢出群成员。 140 | 141 | ### 参数 142 | 143 | - **方法名**: `KickMember` 144 | - **请求类型**: `KickMemberRequest` 145 | - **响应类型**: `KickMemberResponse` 146 | 147 | ### 请求与响应 148 | 149 | ```protobuf 150 | message KickMemberRequest { 151 | uint64 group_id = 1; // 群组ID 152 | oneof target{ 153 | string target_uid = 2; // 被踢目标uid 154 | uint64 target_uin = 3; // 被踢目标uin 155 | } 156 | optional bool reject_add_request = 4; // 是否拒绝再次申请 默认false 157 | optional string kick_reason = 5; // 踢出原因,可选 158 | } 159 | 160 | message KickMemberResponse { 161 | } 162 | ``` 163 | 164 | ## 离开群聊 165 | 166 | 离开群聊。 167 | 168 | ### 参数 169 | 170 | - **方法名**: `LeaveGroup` 171 | - **请求类型**: `LeaveGroupRequest` 172 | - **响应类型**: `LeaveGroupResponse` 173 | 174 | ### 请求与响应 175 | 176 | ```protobuf 177 | message LeaveGroupRequest { 178 | uint64 group_id = 1; // 群组ID 179 | } 180 | 181 | message LeaveGroupResponse { 182 | } 183 | ``` 184 | 185 | ## 修改群成员名片 186 | 187 | 修改群成员名片。 188 | 189 | ### 参数 190 | 191 | - **方法名**: `ModifyMemberCard` 192 | - **请求类型**: `ModifyMemberCardRequest` 193 | - **响应类型**: `ModifyMemberCardResponse` 194 | 195 | ### 请求与响应 196 | 197 | ```protobuf 198 | message ModifyMemberCardRequest { 199 | uint64 group_id = 1; // 群组ID 200 | oneof target{ 201 | string target_uid = 2; // 目标uid 202 | uint64 target_uin = 3; // 目标uin 203 | } 204 | string card = 4; // 新的群名片 205 | } 206 | 207 | message ModifyMemberCardResponse { 208 | } 209 | ``` 210 | 211 | ## 修改群名称 212 | 213 | 修改群名称。 214 | 215 | ### 参数 216 | 217 | - **方法名**: `ModifyGroupName` 218 | - **请求类型**: `ModifyGroupNameRequest` 219 | - **响应类型**: `ModifyGroupNameResponse` 220 | 221 | ### 请求与响应 222 | 223 | ```protobuf 224 | message ModifyGroupNameRequest { 225 | uint64 group_id = 1; // 群组ID 226 | string group_name = 2; // 新的群名称 227 | } 228 | 229 | message ModifyGroupNameResponse { 230 | } 231 | ``` 232 | 233 | ## 修改群备注 234 | 235 | 修改群备注。 236 | 237 | ### 参数 238 | 239 | - **方法名**: `ModifyGroupRemark` 240 | - **请求类型**: `ModifyGroupRemarkRequest` 241 | - **响应类型**: `ModifyGroupRemarkResponse` 242 | 243 | ### 请求与响应 244 | 245 | ```protobuf 246 | message ModifyGroupRemarkRequest { 247 | uint64 group_id = 1; // 群组ID 248 | string remark = 2; // 新的群备注 249 | } 250 | 251 | message ModifyGroupRemarkResponse { 252 | } 253 | ``` 254 | 255 | ## 设置群管理员 256 | 257 | 设置群管理员。 258 | 259 | ### 参数 260 | 261 | - **方法名**: `SetGroupAdmin` 262 | - **请求类型**: `SetGroupAdminRequest` 263 | - **响应类型**: `SetGroupAdminResponse` 264 | 265 | ### 请求与响应 266 | 267 | ```protobuf 268 | message SetGroupAdminRequest { 269 | uint64 group_id = 1; // 群组ID 270 | oneof target{ 271 | string target_uid = 2; // 目标uid 272 | uint64 target_uin = 3; // 目标uin 273 | } 274 | bool is_admin = 4; // 是否设置为管理员 275 | } 276 | 277 | message SetGroupAdminResponse { 278 | } 279 | ``` 280 | 281 | ## 设置群成员头衔 282 | 283 | 设置群成员专属头衔。 284 | 285 | ### 参数 286 | 287 | - **方法名**: `SetGroupUniqueTitle` 288 | - **请求类型**: `SetGroupUniqueTitleRequest` 289 | - **响应类型**: `SetGroupUniqueTitleResponse` 290 | 291 | ### 请求与响应 292 | 293 | ```protobuf 294 | message SetGroupUniqueTitleRequest { 295 | uint64 group_id = 1; // 群组ID 296 | oneof target{ 297 | string target_uid = 2; // 目标uid 298 | uint64 target_uin = 3; // 目标uin 299 | } 300 | string unique_title = 4; // 新的群头衔 301 | } 302 | 303 | message SetGroupUniqueTitleResponse { 304 | } 305 | ``` 306 | 307 | ## 打开/关闭全员禁言 308 | 309 | 打开/关闭全员禁言。 310 | 311 | ### 参数 312 | 313 | - **方法名**: `SetGroupWholeBan` 314 | - **请求类型**: `SetGroupWholeBanRequest` 315 | - **响应类型**: `SetGroupWholeBanResponse` 316 | 317 | ### 请求与响应 318 | 319 | ```protobuf 320 | message SetGroupWholeBanRequest { 321 | uint64 group_id = 1; // 群组ID 322 | bool is_ban = 2; // 是否全员禁言 323 | } 324 | 325 | message SetGroupWholeBanResponse { 326 | } 327 | ``` 328 | 329 | ## 获取群聊信息 330 | 331 | 获取群聊信息。 332 | 333 | ### 参数 334 | 335 | - **方法名**: `GetGroupInfo` 336 | - **请求类型**: `GetGroupInfoRequest` 337 | - **响应类型**: `GetGroupInfoResponse` 338 | 339 | ### 请求与响应 340 | 341 | ```protobuf 342 | message GetGroupInfoRequest { 343 | uint64 group_id = 1; // 群组ID 344 | } 345 | 346 | message GetGroupInfoResponse { 347 | GroupInfo group_info = 1; // 群组信息 348 | } 349 | ``` 350 | 351 | ## 获取群列表 352 | 353 | 获取群列表。 354 | 355 | ### 参数 356 | 357 | - **方法名**: `GetGroupList` 358 | - **请求类型**: `GetGroupListRequest` 359 | - **响应类型**: `GetGroupListResponse` 360 | 361 | ### 请求与响应 362 | 363 | ```protobuf 364 | message GetGroupListRequest { 365 | optional bool refresh = 1; // 是否刷新缓存 366 | } 367 | 368 | message GetGroupListResponse { 369 | repeated GroupInfo group_info = 1; // 群组信息 370 | } 371 | ``` 372 | 373 | ## 获取群成员信息 374 | 375 | 获取群成员信息。 376 | 377 | ### 参数 378 | 379 | - **方法名**: `GetGroupMemberInfo` 380 | - **请求类型**: `GetGroupMemberInfoRequest` 381 | - **响应类型**: `GetGroupMemberInfoResponse` 382 | 383 | ### 请求与响应 384 | 385 | ```protobuf 386 | message GetGroupMemberInfoRequest { 387 | uint64 group_id = 1; // 群组ID 388 | oneof target{ 389 | string target_uid = 2; // 目标uid 390 | uint64 target_uin = 3; // 目标uin 391 | } 392 | optional bool refresh = 4; // 是否刷新缓存 393 | } 394 | 395 | message GetGroupMemberInfoResponse { 396 | GroupMemberInfo group_member_info = 1; // 群成员信息 397 | } 398 | ``` 399 | 400 | ## 获取群成员列表 401 | 402 | 获取群成员列表。 403 | 404 | ### 参数 405 | 406 | - **方法名**: `GetGroupMemberList` 407 | - **请求类型**: `GetGroupMemberListRequest` 408 | - **响应类型**: `GetGroupMemberListResponse` 409 | 410 | ### 请求与响应 411 | 412 | ```protobuf 413 | message GetGroupMemberListRequest { 414 | uint64 group_id = 1; // 群组ID 415 | optional bool refresh = 2; // 是否刷新缓存 416 | } 417 | 418 | message GetGroupMemberListResponse { 419 | repeated GroupMemberInfo group_member_info = 1; // 群成员信息 420 | } 421 | ``` 422 | 423 | ## 获取被禁言的群成员列表 424 | 425 | 获取被禁言的群成员列表。 426 | 427 | ### 参数 428 | 429 | - **方法名**: `GetProhibitedUserList` 430 | - **请求类型**: `GetProhibitedUserListRequest` 431 | - **响应类型**: `GetProhibitedUserListResponse` 432 | 433 | ### 请求与响应 434 | 435 | ```protobuf 436 | message ProhibitedUserInfo { 437 | optional string target_uid = 1; 438 | uint64 target_uin = 2; 439 | uint32 prohibited_time = 3; 440 | } 441 | 442 | message GetProhibitedUserListRequest { 443 | uint64 group_id = 1; // 群组ID 444 | } 445 | 446 | message GetProhibitedUserListResponse { 447 | repeated ProhibitedUserInfo prohibited_user_info = 1; // 禁言用户信息 448 | } 449 | ``` 450 | 451 | ## 获取 `@全体成员` 剩余次数 452 | 453 | 获取 `@全体成员` 剩余次数。 454 | 455 | ### 参数 456 | 457 | - **方法名**: `GetRemainCountAtAll` 458 | - **请求类型**: `GetRemainCountAtAllRequest` 459 | - **响应类型**: `GetRemainCountAtAllResponse` 460 | 461 | ### 请求与响应 462 | 463 | ```protobuf 464 | message GetRemainCountAtAllRequest { 465 | uint64 group_id = 1; // 群组ID 466 | } 467 | 468 | message GetRemainCountAtAllResponse { 469 | uint32 remain_count_for_group = 1; // 剩余次数对于全群 470 | bool access_at_all = 2; 471 | uint32 remain_count_for_self = 3; // 剩余次数对于自己 472 | } 473 | ``` 474 | 475 | ## 获取尚未加入的群聊信息 476 | 477 | 获取尚未加入的群聊信息。 478 | 479 | ### 参数 480 | 481 | - **方法名**: `GetNotJoinedGroupInfo` 482 | - **请求类型**: `GetNotJoinedGroupInfoRequest` 483 | - **响应类型**: `GetNotJoinedGroupInfoResponse` 484 | 485 | ### 请求与响应 486 | 487 | ```protobuf 488 | message NotJoinedGroupInfo { 489 | uint64 group_id = 1; 490 | uint32 max_member_count = 2; 491 | uint32 member_count = 3; 492 | string group_name = 4; 493 | string group_desc = 5; 494 | uint64 owner = 6; 495 | uint32 create_time = 7; 496 | 497 | uint32 group_flag = 8; // 群聊类型什么的都在这里,如果获取不到可以不实现 498 | uint32 group_flag_ext = 9; // 扩展群聊类型 499 | } 500 | 501 | message GetNotJoinedGroupInfoRequest { 502 | uint64 group_id = 1; // 群号 503 | } 504 | 505 | message GetNotJoinedGroupInfoResponse { 506 | NotJoinedGroupInfo group_info = 1; // 未加入群组信息 507 | } 508 | ``` 509 | 510 | ## 获取群荣誉列表 511 | 512 | 获取群荣誉列表。 513 | 514 | ### 参数 515 | 516 | - **方法名**: `GetGroupHonor` 517 | - **请求类型**: `GetGroupHonorRequest` 518 | - **响应类型**: `GetGroupHonorResponse` 519 | 520 | ### 请求与响应 521 | 522 | ```protobuf 523 | message GroupHonorInfo { 524 | optional string uid = 1; // 荣誉成员uid 525 | uint64 uin = 2; // 荣誉成员uin 526 | string nick = 3; // 荣誉成员昵称 527 | string honor_name = 4; // 荣誉名称 528 | string avatar = 5; // 荣誉图标url 529 | uint32 id = 6; // 荣誉id 530 | string description = 7; // 荣誉描述 531 | } 532 | 533 | message GetGroupHonorRequest { 534 | uint64 group_id = 1; // 群号 535 | optional bool refresh = 2; // 是否刷新缓存 536 | } 537 | 538 | message GetGroupHonorResponse { 539 | repeated GroupHonorInfo group_honor_info = 1; // 群荣誉信息 540 | } 541 | ``` 542 | -------------------------------------------------------------------------------- /docs/request/guild.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # 频道服务 6 | 7 | 实现频道相关的服务,提供简化操作的频道管理接口。 8 | 9 | ## 基础信息 10 | 11 | - **服务名**: `GuildService` 12 | - **Java包名**: `io.kritor.guild` 13 | - **C#命名空间**: `Kritor.Guild` 14 | - **[source proto file](/protos/src/main/proto/kritor/guild/guild.proto)** 15 | 16 | ## 基础定义 17 | 18 | ### 频道信息 19 | 20 | ```protobuf 21 | message GuildInfo { 22 | uint64 guild_id = 1; // 频道ID 23 | string guild_name = 2; // 频道名称 24 | string guild_display_id = 3; // 频道显示ID 25 | string profile = 4; // 频道简介 26 | bool is_enable = 5; // 是否启用 27 | bool is_banned = 6; // 是否被封禁 28 | bool is_frozen = 7; // 是否被冻结 29 | uint64 owner_id = 8; // 频道拥有者ID 30 | uint64 shutup_expire_time = 9; // 禁言过期时间 31 | bool allow_search = 10; // 是否允许搜索 32 | } 33 | ``` 34 | 35 | ### 子频道信息 36 | 37 | ```protobuf 38 | message ChannelInfo { 39 | uint64 channel_id = 1; // 子频道ID 40 | uint64 guild_id = 2; // 频道ID 41 | string channel_name = 3; // 子频道名称 42 | uint64 create_time = 4; // 创建时间 43 | uint64 max_member_count = 5; // 最大成员数 44 | uint64 creator_tiny_id = 6; // 创建者tinyid 45 | uint64 talk_permission = 7; // 发言权限 46 | uint64 visible_type = 8; // 可见类型 47 | uint64 current_slow_mode = 9; // 当前发言限制 48 | repeated SlowModes slow_modes = 10; // 发言限制 49 | string icon_url = 11; // 频道图标 50 | uint64 jump_switch = 12; // 跳转开关 51 | uint64 jump_type = 13; // 跳转类型 52 | string jump_url = 14; // 跳转地址 53 | uint64 category_id = 15; // 分类ID 54 | uint64 my_talk_permission = 16; // 我的发言权限 55 | } 56 | ``` 57 | 58 | ### 频道成员信息 59 | 60 | ```protobuf 61 | message MemberInfo { 62 | uint64 tiny_id = 1; // 用户tinyid 63 | string title = 2; // 用户头衔 64 | string nickname = 3; // 用户昵称 65 | uint64 role_id = 4; // 用户角色ID 66 | string role_name = 5; // 用户角色名称 67 | uint64 role_color = 6; // 用户角色颜色 68 | uint64 join_time = 7; // 加入时间 69 | uint64 robot_type = 8; // 机器人类型 70 | uint64 type = 9; // 用户类型 71 | bool in_black = 10; // 是否在黑名单 72 | uint64 platform = 11; // 平台 73 | } 74 | ``` 75 | 76 | ### 频道成员资料 77 | 78 | ```protobuf 79 | message MemberProfile { 80 | uint64 tiny_id = 1; // 用户tinyid 81 | string nickname = 2; // 用户昵称 82 | string avatar_url = 3; // 用户头像 83 | uint64 join_time = 4; // 加入时间 84 | repeated RoleInfo roles = 5; // 用户角色 85 | } 86 | ``` 87 | 88 | ### 用户角色信息 89 | 90 | ```protobuf 91 | message RoleInfo { 92 | uint64 role_id = 1; // 用户角色ID 93 | string role_name = 2; // 用户角色名称 94 | uint64 color = 3; // 用户角色颜色 95 | repeated PermissionInfo permissions = 4; // 用户角色权限 96 | uint64 type = 5; // 用户角色类型 97 | string display_name = 6; // 用户角色显示名称 98 | } 99 | ``` 100 | 101 | ### 频道身份组详细信息 102 | 103 | ```protobuf 104 | message RolesInfo { 105 | uint64 role_id = 1; // 身份组ID 106 | string role_name = 2; // 身份组名称 107 | uint64 argb_color = 3; // 身份组颜色 108 | bool disabled = 4; // 是否禁用 109 | bool independent = 5; // 是否独立 110 | uint64 max_count = 6; // 最大成员数 111 | uint64 member_count = 7; // 成员数 112 | bool owned = 8; // 是否拥有 113 | repeated Permission permissions = 9; // 权限 114 | } 115 | ``` 116 | 117 | ### 用户角色权限信息 118 | 119 | ```protobuf 120 | message PermissionInfo { 121 | uint64 root_id = 1; // 权限根ID 122 | repeated uint64 child_ids = 2; // 权限子ID 123 | } 124 | ``` 125 | 126 | ### 发言限制 127 | 128 | ```protobuf 129 | message SlowModes { 130 | uint64 slow_mode_key = 1; // 详情见下方 131 | string slow_mode_text = 2; // 发言限制描述 132 | uint64 speak_frequency = 3; // 每分钟发言频率 133 | uint64 slow_mode_circle = 4; // 发言限制周期 134 | } 135 | ``` 136 | 137 | | slow_mode_key | slow_mode_text | speak_frequency | slow_mode_circle | 138 | | ------------- | -------------- | --------------- | ---------------- | 139 | | 0 | 关闭 | 0 | 0 | 140 | | 1 | 每分钟1条 | 1 | 60 | 141 | | 2 | 每分钟2条 | 2 | 60 | 142 | | 3 | 每分钟5条 | 5 | 60 | 143 | | 4 | 每分钟10条 | 10 | 60 | 144 | | 5 | 每5分钟1条 | 1 | 300 | 145 | | 6 | 每10分钟1条 | 1 | 600 | 146 | | 7 | 每15分钟1条 | 1 | 900 | 147 | | 8 | 每30分钟1条 | 1 | 1800 | 148 | | 9 | 每1小时1条 | 1 | 3600 | 149 | | 10 | 每12小时1条 | 1 | 43200 | 150 | | 11 | 每24小时1条 | 1 | 86400 | 151 | 152 | 153 | ## 获取频道系统内BOT的资料 154 | 155 | 该接口用于获取频道系统内BOT的资料。 156 | 157 | ### 参数 158 | 159 | - **方法名**: `GetBotInfo` 160 | - **请求类型**: `GetBotInfoRequest` 161 | - **响应类型**: `GetBotInfoResponse` 162 | 163 | ### 请求与响应 164 | 165 | ```protobuf 166 | message GetBotInfoRequest { 167 | } 168 | 169 | message GetBotInfoResponse { 170 | string nickname = 1; // 昵称 171 | uint64 tiny_id = 2; // bot的频道id 172 | string avatar = 3; // 头像 173 | } 174 | ``` 175 | 176 | ## 获取频道列表 177 | 178 | 获取频道列表。 179 | 180 | ### 参数 181 | 182 | - **方法名**: `GetChannelList` 183 | - **请求类型**: `GetChannelListRequest` 184 | - **响应类型**: `GetChannelListResponse` 185 | 186 | ### 请求与响应 187 | 188 | ```protobuf 189 | message GetChannelListRequest { 190 | } 191 | 192 | message GetChannelListResponse { 193 | repeated GuildInfo get_guild_list = 1; // 频道列表 194 | } 195 | ``` 196 | 197 | ## 通过访客获取频道元数据 198 | 199 | 获取频道元数据,例如当前成员数量之类。 200 | 201 | ### 参数 202 | 203 | - **方法名**: `GetGuildMetaByGuest` 204 | - **请求类型**: `GetGuildMetaByGuestRequest` 205 | - **响应类型**: `GetGuildMetaByGuestResponse` 206 | 207 | ### 请求与响应 208 | 209 | ```protobuf 210 | message GetGuildMetaByGuestRequest { 211 | uint64 guild_id = 1; // 频道ID 212 | } 213 | 214 | message GetGuildMetaByGuestResponse { 215 | uint64 guild_id = 1; // 频道ID 216 | string guild_name = 2; // 频道名称 217 | string guild_profile = 3; // 频道简介 218 | uint64 create_time = 4; // 创建时间 219 | uint64 max_member_count = 5; // 最大成员数量 220 | uint64 max_robot_count = 6; // 最大机器人数量 221 | uint64 max_admin_count = 7; // 最大管理员数量 222 | uint64 member_count = 8; // 当前成员数量 223 | uint64 owner_id = 9; // 频道所有者ID 224 | string guild_display_id = 10; // 频道显示ID 225 | } 226 | ``` 227 | 228 | ## 获取子频道列表 229 | 230 | 获取一个频道的子频道(channel)列表。 231 | 232 | ### 参数 233 | 234 | - **方法名**: `GetGuildChannelList` 235 | - **请求类型**: `GetGuildChannelListRequest` 236 | - **响应类型**: `GetGuildChannelListResponse` 237 | 238 | ### 请求与响应 239 | 240 | ```protobuf 241 | message GetGuildChannelListRequest { 242 | uint64 guild_id = 1; // 频道ID 243 | bool refresh = 2; // 是否刷新数据,默认false 244 | } 245 | 246 | message GetGuildChannelListResponse { 247 | repeated ChannelInfo get_guild_list = 1; // 子频道列表 248 | } 249 | ``` 250 | 251 | ## 获取频道成员列表 252 | 253 | 获取一个频道成员列表,但是因为数据量大,可能需要分页。 254 | 255 | ### 参数 256 | 257 | - **方法名**: `GetGuildMemberList` 258 | - **请求类型**: `GetGuildMemberListRequest` 259 | - **响应类型**: `GetGuildMemberListResponse` 260 | 261 | ### 请求与响应 262 | 263 | ```protobuf 264 | message GetGuildMemberListRequest { 265 | uint64 guild_id = 1; // 频道ID 266 | string next_token = 2; // 不提供则从首页开始获取 267 | bool all = 3; // 是否一次性获取完所有成员,默认false 268 | bool refresh = 4; // 是否刷新数据,默认false 269 | } 270 | 271 | message GetGuildMemberListResponse { 272 | repeated MemberInfo get_member_list = 1; // 成员列表 273 | string next_token = 2; // 下一页的token 274 | bool finished = 3; // 是否已经获取完所有成员 275 | } 276 | ``` 277 | 278 | ## 单独获取频道成员资料 279 | 280 | 单独获取频道成员信息,附带有权限信息和身份组哦~! 281 | 282 | ### 参数 283 | 284 | - **方法名**: `GetGuildMember` 285 | - **请求类型**: `GetGuildMemberRequest` 286 | - **响应类型**: `GetGuildMemberResponse` 287 | 288 | ### 请求与响应 289 | 290 | ```protobuf 291 | message GetGuildMemberRequest { 292 | uint64 guild_id = 1; // 频道ID 293 | uint64 tiny_id = 2; // 成员tinyId 294 | } 295 | 296 | message GetGuildMemberResponse { 297 | MemberProfile member_info = 1; // 成员资料 298 | } 299 | ``` 300 | 301 | ## 发送信息到子频道 302 | 303 | 发送频道内信息,需要单独的API哦,不要使用/send_message去发频道消息,发不出去的~~ 304 | 305 | ### 参数 306 | 307 | - **方法名**: `SendChannelMessage` 308 | - **请求类型**: `SendChannelMessageRequest` 309 | - **响应类型**: `SendChannelMessageResponse` 310 | 311 | ### 请求与响应 312 | 313 | ```protobuf 314 | message SendChannelMessageRequest { 315 | uint64 guild_id = 1; // 频道ID 316 | uint64 channel_id = 2; // 子频道ID 317 | string message = 3; // 消息体 318 | int32 retry_cnt = 4; // 最大重试次数 319 | int64 recall_duration = 5; // 自动撤回间隔 320 | } 321 | 322 | message SendChannelMessageResponse { 323 | uint64 message_id = 1; // 消息ID 324 | int64 time = 2; // 时间 325 | } 326 | ``` 327 | 328 | ## 获取话题频道帖子 329 | 330 | 该API接口已经被遗弃! 331 | 332 | ## 获取频道帖子广场帖子 333 | 334 | 新的获取帖子广场的帖子哦! 335 | 336 | ### 参数 337 | 338 | - **方法名**: `GetGuildFeeds` 339 | - **请求类型**: `GetGuildFeedsRequest` 340 | - **响应类型**: `GetGuildFeedsResponse` 341 | 342 | ### 请求与响应 343 | 344 | ```protobuf 345 | message GetGuildFeedsRequest { 346 | uint64 guild_id = 1; // 频道ID 347 | uint32 from = 2; // 开始获取的位置 348 | } 349 | 350 | message GetGuildFeedsResponse { 351 | bytes data = 1; // 该请求携带了大量原生响应数据,无法详细介绍,请自行测试! 352 | } 353 | ``` 354 | 355 | ## 获取频道角色列表 356 | 357 | 获取身份组列表,包括隐藏的身份组哦~~ 358 | 359 | ### 参数 360 | 361 | - **方法名**: `GetGuildRoles` 362 | - **请求类型**: `GetGuildRolesRequest` 363 | - **响应类型**: `GetGuildRolesResponse` 364 | 365 | ### 请求与响应 366 | 367 | ```protobuf 368 | message GetGuildRolesRequest { 369 | uint64 guild_id = 1; // 频道ID 370 | } 371 | 372 | message GetGuildRolesResponse { 373 | repeated RolesInfo get_role_list = 1; // 角色列表 374 | } 375 | ``` 376 | 377 | ## 获取频道消息 378 | 379 | 该接口不会实现,因为您可以调用/get_msg来获取来自频道的消息,无需实现一个专属的接口。 380 | 381 | ## 删除频道身份组 382 | 383 | 删除一个身份组,首先,你得保证你有权限,因为这个API不会提供任何返回数据哦! 384 | 385 | ### 参数 386 | 387 | - **方法名**: `DeleteGuildRole` 388 | - **请求类型**: `DeleteGuildRoleRequest` 389 | - **响应类型**: `DeleteGuildRoleResponse` 390 | 391 | ### 请求与响应 392 | 393 | ```protobuf 394 | message DeleteGuildRoleRequest { 395 | uint64 guild_id = 1; // 频道ID 396 | uint64 role_id = 2; // 角色ID 397 | } 398 | 399 | message DeleteGuildRoleResponse { 400 | // 无返回值 401 | } 402 | 403 | ``` 404 | 405 | ## 设置用户在频道中的角色 406 | 407 | 设置用户身份组。 408 | 409 | ### 参数 410 | 411 | - **方法名**: `SetGuildMemberRole` 412 | - **请求类型**: `SetGuildMemberRoleRequest` 413 | - **响应类型**: `SetGuildMemberRoleResponse` 414 | 415 | ### 请求与响应 416 | 417 | ```protobuf 418 | message SetGuildMemberRoleRequest { 419 | uint64 guild_id = 1; // 频道ID 420 | uint64 role_id = 2; // 角色ID 421 | bool set = 3; // 设置还是移除,默认false 422 | repeated string users = 4; // 批量设置用户s 423 | int64 tiny_id = 5; // 单独设置某个用户的身份 424 | } 425 | 426 | message SetGuildMemberRoleResponse { 427 | // 无返回值 428 | } 429 | ``` 430 | 431 | ## 修改频道角色 432 | 433 | 修改频道角色,暂不支持设置权限,如有需要请提交issue。 434 | 435 | ### 参数 436 | 437 | - **方法名**: `UpdateGuildRole` 438 | - **请求类型**: `UpdateGuildRoleRequest` 439 | - **响应类型**: `UpdateGuildRoleResponse` 440 | 441 | ### 请求与响应 442 | 443 | ```protobuf 444 | message UpdateGuildRoleRequest { 445 | uint64 guild_id = 1; // 频道ID 446 | uint64 role_id = 2; // 角色ID 447 | string name = 3; // 名称 448 | int64 color = 4; // 颜色ARGB 449 | } 450 | 451 | message UpdateGuildRoleResponse { 452 | // 无返回值 453 | } 454 | ``` 455 | 456 | ## 创建频道角色 457 | 458 | 创建频道身份组。 459 | 460 | ### 参数 461 | 462 | - **方法名**: `CreateGuildRole` 463 | - **请求类型**: `CreateGuildRoleRequest` 464 | - **响应类型**: `CreateGuildRoleResponse` 465 | 466 | ### 请求与响应 467 | 468 | ```protobuf 469 | message CreateGuildRoleRequest { 470 | uint64 guild_id = 1; // 频道ID 471 | string name = 2; // 名称 472 | int64 color = 3; // 颜色ARGB 473 | repeated int64 initial_users = 4; // 默认身份组成员 474 | } 475 | 476 | message CreateGuildRoleResponse { 477 | uint64 role_id = 1; // 角色ID 478 | } 479 | ``` 480 | --------------------------------------------------------------------------------