diff --git a/client/entity/group_airecord.go b/client/entity/group_airecord.go new file mode 100644 index 0000000..e2250b2 --- /dev/null +++ b/client/entity/group_airecord.go @@ -0,0 +1,26 @@ +package entity + +type ChatType uint32 + +const ( + ChatTypeVoice ChatType = 1 + ChatTypeSong ChatType = 2 +) + +type ( + AiCharacter struct { + Name string `json:"name"` + VoiceID string `json:"voice_id"` + VoiceURL string `json:"voice_url"` + } + + AiCharacterInfo struct { + Type string `json:"type"` + Characters []AiCharacter `json:"characters"` + } + + AiCharacterList struct { + Type ChatType `json:"type"` + List []AiCharacterInfo `json:"chats"` + } +) diff --git a/client/operation.go b/client/operation.go index 9e0358d..2caede0 100644 --- a/client/operation.go +++ b/client/operation.go @@ -1484,3 +1484,37 @@ func (c *QQClient) GetAtAllRemain(uin, groupUin uint32) (*oidb2.AtAllRemainInfo, } return oidb2.ParseGetAtAllRemainResponse(resp) } + +// GetAiCharacters 获取AI语音角色列表 +func (c *QQClient) GetAiCharacters(groupUin uint32, chatType entity.ChatType) (*entity.AiCharacterList, error) { + if groupUin == 0 { + groupUin = 42 + } + pkt, err := oidb2.BuildAiCharacterListService(groupUin, chatType) + if err != nil { + return nil, err + } + rsp, err := c.sendOidbPacketAndWait(pkt) + if err != nil { + return nil, err + } + result, err := oidb2.ParseAiCharacterListService(rsp) + if err != nil { + return nil, err + } + result.Type = chatType + return result, nil +} + +// SendGroupAiRecord 发送群AI语音 +func (c *QQClient) SendGroupAiRecord(groupUin uint32, chatType entity.ChatType, voiceID, text string) (*message2.VoiceElement, error) { + pkt, err := oidb2.BuildGroupAiRecordService(groupUin, voiceID, text, chatType, crypto.RandU32()) + if err != nil { + return nil, err + } + rsp, err := c.sendOidbPacketAndWait(pkt) + if err != nil { + return nil, err + } + return oidb2.ParseGroupAiRecordService(rsp) +} diff --git a/client/packets/oidb/group_airecord.go b/client/packets/oidb/group_airecord.go new file mode 100644 index 0000000..8ec74fe --- /dev/null +++ b/client/packets/oidb/group_airecord.go @@ -0,0 +1,71 @@ +package oidb + +import ( + "encoding/hex" + "errors" + + "github.com/LagrangeDev/LagrangeGo/client/entity" + "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb" + "github.com/LagrangeDev/LagrangeGo/message" +) + +func BuildAiCharacterListService(groupUin uint32, chatType entity.ChatType) (*Packet, error) { + return BuildOidbPacket(0x929D, 0, &oidb.OidbSvcTrpcTcp0X929D_0_Req{GroupUin: groupUin, ChatType: uint32(chatType)}, false, false) +} + +func ParseAiCharacterListService(data []byte) (*entity.AiCharacterList, error) { + var rsp oidb.OidbSvcTrpcTcp0X929D_0_Rsp + _, err := ParseOidbPacket(data, &rsp) + if err != nil { + return nil, err + } + var ret entity.AiCharacterList + for _, property := range rsp.Property { + info := entity.AiCharacterInfo{Type: property.Type} + for _, v := range property.Value { + info.Characters = append(info.Characters, entity.AiCharacter{ + Name: v.CharacterName, + VoiceID: v.CharacterId, + VoiceURL: v.CharacterVoiceUrl, + }) + } + ret.List = append(ret.List, info) + } + if len(ret.List) == 0 { + return nil, errors.New("ai character list nil") + } + return &ret, nil +} + +func BuildGroupAiRecordService(groupUin uint32, voiceID, text string, chatType entity.ChatType, chatID uint32) (*Packet, error) { + return BuildOidbPacket(0x929B, 0, &oidb.OidbSvcTrpcTcp0X929B_0_Req{ + GroupUin: groupUin, + VoiceId: voiceID, + Text: text, + ChatType: uint32(chatType), + ClientMsgInfo: &oidb.OidbSvcTrpcTcp0X929B_0_Req_ClientMsgInfo{MsgRandom: chatID}, + }, false, false) +} + +func ParseGroupAiRecordService(data []byte) (*message.VoiceElement, error) { + var rsp oidb.OidbSvcTrpcTcp0X929B_0_Rsp + _, err := ParseOidbPacket(data, &rsp) + if err != nil { + return nil, err + } + if rsp.MsgInfo == nil || len(rsp.MsgInfo.MsgInfoBody) == 0 { + return nil, errors.New("rsp msg info nil") + } + index := rsp.MsgInfo.MsgInfoBody[0].Index + elem := &message.VoiceElement{ + UUID: index.FileUuid, + Name: index.Info.FileName, + Size: index.Info.FileSize, + Duration: index.Info.Time, + MsgInfo: rsp.MsgInfo, + // Compat ?? + } + elem.Md5, _ = hex.DecodeString(index.Info.FileHash) + elem.Sha1, _ = hex.DecodeString(index.Info.FileSha1) + return elem, nil +} diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x1096_1.pb.go b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x1096_1.pb.go index fe9abcb..f88e502 100644 --- a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x1096_1.pb.go +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x1096_1.pb.go @@ -7,7 +7,7 @@ import ( proto "github.com/RomiChan/protobuf/proto" ) -// SetGroupAdmin +// GroupSetAdmin type OidbSvcTrpcTcp0X1096_1 struct { GroupUin uint32 `protobuf:"varint,1,opt"` Uid string `protobuf:"bytes,2,opt"` diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929B_0.pb.go b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929B_0.pb.go new file mode 100644 index 0000000..93513e3 --- /dev/null +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929B_0.pb.go @@ -0,0 +1,26 @@ +// Code generated by protoc-gen-golite. DO NOT EDIT. +// source: pb/service/oidb/OidbSvcTrpcTcp0x929B_0.proto + +package oidb + +type OidbSvcTrpcTcp0X929B_0_Req struct { + GroupUin uint32 `protobuf:"varint,1,opt"` + VoiceId string `protobuf:"bytes,2,opt"` + Text string `protobuf:"bytes,3,opt"` + ChatType uint32 `protobuf:"varint,4,opt"` // 1 voice,2 song + ClientMsgInfo *OidbSvcTrpcTcp0X929B_0_Req_ClientMsgInfo `protobuf:"bytes,5,opt"` + _ [0]func() +} + +type OidbSvcTrpcTcp0X929B_0_Rsp struct { + Field1 uint32 `protobuf:"varint,1,opt"` // 1 complete, 2 wait + Field2 uint32 `protobuf:"varint,2,opt"` // 319 + Field3 uint32 `protobuf:"varint,3,opt"` // 20 + MsgInfo *MsgInfo `protobuf:"bytes,4,opt"` + _ [0]func() +} + +type OidbSvcTrpcTcp0X929B_0_Req_ClientMsgInfo struct { + MsgRandom uint32 `protobuf:"varint,1,opt"` + _ [0]func() +} diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929B_0.proto b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929B_0.proto new file mode 100644 index 0000000..2600b35 --- /dev/null +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929B_0.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; + +option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; + +import "pb/service/oidb/NTV2RichMediaReq.proto"; + +message OidbSvcTrpcTcp0x929B_0_Req { + uint32 groupUin = 1; + string voiceId = 2; + string text = 3; + uint32 chatType = 4; // 1 voice,2 song + ClientMsgInfo clientMsgInfo = 5; + message ClientMsgInfo { + uint32 msgRandom = 1; + } +} + +message OidbSvcTrpcTcp0x929B_0_Rsp { + uint32 field1 = 1; // 1 complete, 2 wait + uint32 field2 = 2; // 319 + uint32 field3 = 3; // 20 + MsgInfo msgInfo = 4; +} diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929D_0.pb.go b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929D_0.pb.go new file mode 100644 index 0000000..53cf847 --- /dev/null +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929D_0.pb.go @@ -0,0 +1,26 @@ +// Code generated by protoc-gen-golite. DO NOT EDIT. +// source: pb/service/oidb/OidbSvcTrpcTcp0x929D_0.proto + +package oidb + +type OidbSvcTrpcTcp0X929D_0_Req struct { + GroupUin uint32 `protobuf:"varint,1,opt"` + ChatType uint32 `protobuf:"varint,2,opt"` // 1 voice, 2 song + _ [0]func() +} + +type OidbSvcTrpcTcp0X929D_0_Rsp struct { + Property []*OidbSvcTrpcTcp0X929D_0_Rsp_Key `protobuf:"bytes,1,rep"` +} + +type OidbSvcTrpcTcp0X929D_0_Rsp_Key struct { + Type string `protobuf:"bytes,1,opt"` + Value []*OidbSvcTrpcTcp0X929D_0_Rsp_Property `protobuf:"bytes,2,rep"` +} + +type OidbSvcTrpcTcp0X929D_0_Rsp_Property struct { + CharacterId string `protobuf:"bytes,1,opt"` + CharacterName string `protobuf:"bytes,2,opt"` + CharacterVoiceUrl string `protobuf:"bytes,3,opt"` + _ [0]func() +} diff --git a/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929D_0.proto b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929D_0.proto new file mode 100644 index 0000000..746605f --- /dev/null +++ b/client/packets/pb/service/oidb/OidbSvcTrpcTcp0x929D_0.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +option go_package = "github.com/LagrangeDev/LagrangeGo/client/packets/pb/service/oidb"; + +message OidbSvcTrpcTcp0x929D_0_Req { + uint32 groupUin = 1; + uint32 chatType = 2; // 1 voice, 2 song +} + +message OidbSvcTrpcTcp0x929D_0_Rsp { + repeated Key property = 1; + message Key { + string type = 1; + repeated Property value = 2; + } + message Property { + string characterId = 1; + string characterName = 2; + string characterVoiceUrl = 3; + } +}