Group management Update

This commit is contained in:
jiahua.liu 2020-02-04 23:54:21 +08:00
parent 30d41f6e9d
commit 5c04ba445c
7 changed files with 611 additions and 23 deletions

View File

@ -1,5 +1,7 @@
package net.mamoe.mirai.qqandroid
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.FriendNameRemark
import net.mamoe.mirai.data.PreviousNameList
@ -23,6 +25,7 @@ import net.mamoe.mirai.utils.io.PlatformSocket
import net.mamoe.mirai.utils.io.discardExact
import net.mamoe.mirai.utils.unsafeWeakRef
import kotlin.coroutines.CoroutineContext
import kotlin.properties.Delegates
internal abstract class ContactImpl : Contact
@ -108,15 +111,106 @@ internal class MemberImpl(
}
/**
* 对GroupImpl
* 中name/announcement的更改会直接向服务器异步汇报
*/
@UseExperimental(MiraiInternalAPI::class)
internal class GroupImpl(
bot: QQAndroidBot, override val coroutineContext: CoroutineContext,
override val id: Long,
val uin: Long,
override var name: String,
override var announcement: String,
initName: String,
initAnnouncement: String,
initAllowMemberInvite: Boolean,
initConfessTalk: Boolean,
initMuteAll: Boolean,
initAutoApprove: Boolean,
initAnonymousChat: Boolean,
override var members: ContactList<Member>
) : ContactImpl(), Group {
override var name by Delegates.observable(initName) { _, oldValue, newValue ->
if (this.botPermission != MemberPermission.MEMBER && oldValue != newValue) {
this.bot.launch {
bot.network.run {
TroopManagement.updateGroupInfo.name(
client = bot.client,
groupCode = id,
newName = newValue
).sendWithoutExpect()
}
}
}
}
override var announcement: String by Delegates.observable(initAnnouncement) { _, oldValue, newValue ->
if (this.botPermission != MemberPermission.MEMBER && oldValue != newValue) {
this.bot.launch {
bot.network.run {
TroopManagement.updateGroupInfo.memo(
client = bot.client,
groupCode = id,
newMemo = newValue
).sendWithoutExpect()
}
}
}
}
override var allowMemberInvite: Boolean by Delegates.observable(initAllowMemberInvite) { _, oldValue, newValue ->
if (this.botPermission != MemberPermission.MEMBER && oldValue != newValue) {
this.bot.launch {
bot.network.run {
TroopManagement.updateGroupInfo.allowMemberInvite(
client = bot.client,
groupCode = id,
switch = newValue
).sendWithoutExpect()
}
}
}
}
override var autoApprove: Boolean by Delegates.observable(initAutoApprove) { _, oldValue, newValue ->
//暂时也不能改
}
override val anonymousChat: Boolean by Delegates.observable(initAnonymousChat) { _, oldValue, newValue ->
//暂时不能改
}
override var confessTalk: Boolean by Delegates.observable(initConfessTalk) { _, oldValue, newValue ->
if (this.botPermission != MemberPermission.MEMBER && oldValue != newValue) {
this.bot.launch {
bot.network.run {
TroopManagement.updateGroupInfo.confessTalk(
client = bot.client,
groupCode = id,
switch = newValue
).sendWithoutExpect()
}
}
}
}
override var muteAll: Boolean by Delegates.observable(initMuteAll) { _, oldValue, newValue ->
if (this.botPermission != MemberPermission.MEMBER && oldValue != newValue) {
this.bot.launch {
bot.network.run {
TroopManagement.updateGroupInfo.muteAll(
client = bot.client,
groupCode = id,
switch = newValue
).sendWithoutExpect()
}
}
}
}
override lateinit var owner: Member
override var botPermission: MemberPermission = MemberPermission.MEMBER
@ -124,6 +218,7 @@ internal class GroupImpl(
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override operator fun get(id: Long): Member {
return members.delegate.filteringGetOrNull { it.id == id } ?: throw NoSuchElementException("for group id $id")
}

View File

@ -24,6 +24,7 @@ import net.mamoe.mirai.qqandroid.event.ForceOfflineEvent
import net.mamoe.mirai.qqandroid.event.PacketReceivedEvent
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgSvc
import net.mamoe.mirai.qqandroid.network.protocol.packet.*
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
@ -167,8 +168,12 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
coroutineContext = this.coroutineContext,
id = it.groupCode,
uin = it.groupUin,
name = it.groupName,
announcement = it.groupMemo,
initName = it.groupName,
initAnnouncement = it.groupMemo,
initAllowMemberInvite = false,
initConfessTalk = false,
initMuteAll = false,
initAutoApprove = false,
members = contactList
)
group.owner =
@ -238,6 +243,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendWithoutExpect()
}
suspend fun getGroupInfo(uin: Long) {
val data = TroopManagement.getGroupInfo(
client = bot.client,
groupCode = uin
).sendAndExpect<TroopManagement.getGroupInfo.Response>(timeoutMillis = 3000)
}
suspend fun getTroopMemberList(group: GroupImpl, list: ContactList<Member>, owner: Long): ContactList<Member> {
bot.logger.info("开始获取群[${group.uin}]成员列表")
var size = 0

View File

@ -5,6 +5,266 @@ import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.ProtoBuf
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@Serializable
class Oidb0x88d : ProtoBuf {
@Serializable
class GroupExInfoOnly(
@SerialId(1) val tribeId: Int = 0,
@SerialId(2) val moneyForAddGroup: Int = 0
) : ProtoBuf
@Serializable
class ReqGroupInfo(
@SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val stgroupinfo: Oidb0x88d.GroupInfo? = null,
@SerialId(3) val lastGetGroupNameTime: Int = 0
) : ProtoBuf
@Serializable
class RspGroupInfo(
@SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val result: Int = 0,
@SerialId(3) val stgroupinfo: Oidb0x88d.GroupInfo? = null
) : ProtoBuf
@Serializable
class GroupGeoInfo(
@SerialId(1) val owneruin: Long = 0L,
@SerialId(2) val settime: Int = 0,
@SerialId(3) val cityid: Int = 0,
@SerialId(4) val int64Longitude: Long = 0L,
@SerialId(5) val int64Latitude: Long = 0L,
@SerialId(6) val geocontent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(7) val poiId: Long = 0L
) : ProtoBuf
@Serializable
class TagRecord(
@SerialId(1) val fromUin: Long = 0L,
@SerialId(2) val groupCode: Long = 0L,
@SerialId(3) val tagId: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(4) val setTime: Long = 0L,
@SerialId(5) val goodNum: Int = 0,
@SerialId(6) val badNum: Int = 0,
@SerialId(7) val tagLen: Int = 0,
@SerialId(8) val tagValue: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class GroupInfo(
@SerialId(1) val groupOwner: Long? = null,
@SerialId(2) val groupCreateTime: Int? = null,
@SerialId(3) val groupFlag: Int? = null,
@SerialId(4) val groupFlagExt: Int? = null,
@SerialId(5) val groupMemberMaxNum: Int? = null,
@SerialId(6) val groupMemberNum: Int? = null,
@SerialId(7) val groupOption: Int? = null,
@SerialId(8) val groupClassExt: Int? = null,
@SerialId(9) val groupSpecialClass: Int? = null,
@SerialId(10) val groupLevel: Int? = null,
@SerialId(11) val groupFace: Int? = null,
@SerialId(12) val groupDefaultPage: Int? = null,
@SerialId(13) val groupInfoSeq: Int? = null,
@SerialId(14) val groupRoamingTime: Int? = null,
@SerialId(15) val ingGroupName: ByteArray? = null,
@SerialId(16) val ingGroupMemo: ByteArray? = null,
@SerialId(17) val ingGroupFingerMemo: ByteArray? = null,
@SerialId(18) val ingGroupClassText: ByteArray? = null,
@SerialId(19) val groupAllianceCode: List<Int>? = null,
@SerialId(20) val groupExtraAdmNum: Int? = null,
@SerialId(21) val groupUin: Long? = null,
@SerialId(22) val groupCurMsgSeq: Int? = null,
@SerialId(23) val groupLastMsgTime: Int? = null,
@SerialId(24) val ingGroupQuestion: ByteArray? = null,
@SerialId(25) val ingGroupAnswer: ByteArray? = null,
@SerialId(26) val groupVisitorMaxNum: Int? = null,
@SerialId(27) val groupVisitorCurNum: Int? = null,
@SerialId(28) val levelNameSeq: Int? = null,
@SerialId(29) val groupAdminMaxNum: Int? = null,
@SerialId(30) val groupAioSkinTimestamp: Int? = null,
@SerialId(31) val groupBoardSkinTimestamp: Int? = null,
@SerialId(32) val ingGroupAioSkinUrl: ByteArray? = null,
@SerialId(33) val ingGroupBoardSkinUrl: ByteArray? = null,
@SerialId(34) val groupCoverSkinTimestamp: Int? = null,
@SerialId(35) val ingGroupCoverSkinUrl: ByteArray? = null,
@SerialId(36) val groupGrade: Int? = null,
@SerialId(37) val activeMemberNum: Int? = null,
@SerialId(38) val certificationType: Int? = null,
@SerialId(39) val ingCertificationText: ByteArray? = null,
@SerialId(40) val ingGroupRichFingerMemo: ByteArray? = null,
@SerialId(41) val tagRecord: List<TagRecord>? = null,
@SerialId(42) val groupGeoInfo: GroupGeoInfo? = null,
@SerialId(43) val headPortraitSeq: Int? = null,
@SerialId(44) val msgHeadPortrait: GroupHeadPortrait? = null,
@SerialId(45) val shutupTimestamp: Int? = null,
@SerialId(46) val shutupTimestampMe: Int? = null,
@SerialId(47) val createSourceFlag: Int? = null,
@SerialId(48) val cmduinMsgSeq: Int? = null,
@SerialId(49) val cmduinJoinTime: Int? = null,
@SerialId(50) val cmduinUinFlag: Int? = null,
@SerialId(51) val cmduinFlagEx: Int? = null,
@SerialId(52) val cmduinNewMobileFlag: Int? = null,
@SerialId(53) val cmduinReadMsgSeq: Int? = null,
@SerialId(54) val cmduinLastMsgTime: Int? = null,
@SerialId(55) val groupTypeFlag: Int? = null,
@SerialId(56) val appPrivilegeFlag: Int? = null,
@SerialId(57) val stGroupExInfo: GroupExInfoOnly? = null,
@SerialId(58) val groupSecLevel: Int? = null,
@SerialId(59) val groupSecLevelInfo: Int? = null,
@SerialId(60) val cmduinPrivilege: Int? = null,
@SerialId(61) val ingPoidInfo: ByteArray? = null,
@SerialId(62) val cmduinFlagEx2: Int? = null,
@SerialId(63) val confUin: Long? = null,
@SerialId(64) val confMaxMsgSeq: Int? = null,
@SerialId(65) val confToGroupTime: Int? = null,
@SerialId(66) val passwordRedbagTime: Int? = null,
@SerialId(67) val subscriptionUin: Long? = null,
@SerialId(68) val memberListChangeSeq: Int? = null,
@SerialId(69) val membercardSeq: Int? = null,
@SerialId(70) val rootId: Long? = null,
@SerialId(71) val parentId: Long? = null,
@SerialId(72) val teamSeq: Int? = null,
@SerialId(73) val historyMsgBeginTime: Long? = null,
@SerialId(74) val inviteNoAuthNumLimit: Long? = null,
@SerialId(75) val cmduinHistoryMsgSeq: Int? = null,
@SerialId(76) val cmduinJoinMsgSeq: Int? = null,
@SerialId(77) val groupFlagext3: Int? = null,
@SerialId(78) val groupOpenAppid: Int? = null,
@SerialId(79) val isConfGroup: Int? = null,
@SerialId(80) val isModifyConfGroupFace: Int? = null,
@SerialId(81) val isModifyConfGroupName: Int? = null,
@SerialId(82) val noFingerOpenFlag: Int? = null,
@SerialId(83) val noCodeFingerOpenFlag: Int? = null,
@SerialId(84) val autoAgreeJoinGroupUserNumForNormalGroup: Int? = null,
@SerialId(85) val autoAgreeJoinGroupUserNumForConfGroup: Int? = null,
@SerialId(86) val isAllowConfGroupMemberNick: Int? = null,
@SerialId(87) val isAllowConfGroupMemberAtAll: Int? = null,
@SerialId(88) val isAllowConfGroupMemberModifyGroupName: Int? = null,
@SerialId(89) val ingLongGroupName: ByteArray? = null,
@SerialId(90) val cmduinJoinRealMsgSeq: Int? = null,
@SerialId(91) val isGroupFreeze: Int? = null,
@SerialId(92) val msgLimitFrequency: Int? = null,
@SerialId(93) val joinGroupAuth: ByteArray? = null,
@SerialId(94) val hlGuildAppid: Int? = null,
@SerialId(95) val hlGuildSubType: Int? = null,
@SerialId(96) val hlGuildOrgid: Int? = null,
@SerialId(97) val isAllowHlGuildBinary: Int? = null,
@SerialId(98) val cmduinRingtoneId: Int? = null,
@SerialId(99) val groupFlagext4: Int? = null,
@SerialId(100) val groupFreezeReason: Int? = null
) : ProtoBuf
@Serializable
class GroupHeadPortraitInfo(
@SerialId(1) val uint32PicId: Int = 0,
@SerialId(2) val leftX: Int = 0,
@SerialId(3) val leftY: Int = 0,
@SerialId(4) val rightX: Int = 0,
@SerialId(5) val rightY: Int = 0
) : ProtoBuf
@Serializable
class RspBody(
@SerialId(1) val stzrspgroupinfo: List<Oidb0x88d.RspGroupInfo>? = null,
@SerialId(2) val errorinfo: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class ReqBody(
@SerialId(1) val appid: Int = 0,
@SerialId(2) val stzreqgroupinfo: List<Oidb0x88d.ReqGroupInfo>? = null,
@SerialId(3) val pcClientVersion: Int = 0
) : ProtoBuf
@Serializable
class GroupHeadPortrait(
@SerialId(1) val picCnt: Int = 0,
@SerialId(2) val msgInfo: List<Oidb0x88d.GroupHeadPortraitInfo>? = null,
@SerialId(3) val defaultId: Int = 0,
@SerialId(4) val verifyingPicCnt: Int = 0,
@SerialId(5) val msgVerifyingpicInfo: List<Oidb0x88d.GroupHeadPortraitInfo>? = null
) : ProtoBuf
}
@Serializable
class Oidb0x89a : ProtoBuf {
@Serializable
class GroupNewGuidelinesInfo(
@SerialId(1) val boolEnabled: Boolean = false,
@SerialId(2) val ingContent: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class Groupinfo(
@SerialId(1) val groupExtAdmNum: Int? = null,
@SerialId(2) val flag: Int? = null,
@SerialId(3) val ingGroupName: ByteArray? = null,
@SerialId(4) val ingGroupMemo: ByteArray? = null,
@SerialId(5) val ingGroupFingerMemo: ByteArray? = null,
@SerialId(6) val ingGroupAioSkinUrl: ByteArray? = null,
@SerialId(7) val ingGroupBoardSkinUrl: ByteArray? = null,
@SerialId(8) val ingGroupCoverSkinUrl: ByteArray? = null,
@SerialId(9) val groupGrade: Int? = null,
@SerialId(10) val activeMemberNum: Int? = null,
@SerialId(11) val certificationType: Int? = null,
@SerialId(12) val ingCertificationText: ByteArray? = null,
@SerialId(13) val ingGroupRichFingerMemo: ByteArray? = null,
@SerialId(14) val stGroupNewguidelines: Oidb0x89a.GroupNewGuidelinesInfo? = null,
@SerialId(15) val groupFace: Int? = null,
@SerialId(16) val addOption: Int? = null,
@SerialId(17) val shutupTime: Int? = null,
@SerialId(18) val groupTypeFlag: Int? = null,
@SerialId(19) val stringGroupTag: List<ByteArray>? = null,
@SerialId(20) val msgGroupGeoInfo: Oidb0x89a.GroupGeoInfo? = null,
@SerialId(21) val groupClassExt: Int? = null,
@SerialId(22) val ingGroupClassText: ByteArray? = null,
@SerialId(23) val appPrivilegeFlag: Int? = null,
@SerialId(24) val appPrivilegeMask: Int? = null,
@SerialId(25) val stGroupExInfo: Oidb0x89a.GroupExInfoOnly? = null,
@SerialId(26) val groupSecLevel: Int? = null,
@SerialId(27) val groupSecLevelInfo: Int? = null,
@SerialId(28) val subscriptionUin: Long? = null,
@SerialId(29) val allowMemberInvite: Int? = null,
@SerialId(30) val ingGroupQuestion: ByteArray? = null,
@SerialId(31) val ingGroupAnswer: ByteArray? = null,
@SerialId(32) val groupFlagext3: Int? = null,
@SerialId(33) val groupFlagext3Mask: Int? = null,
@SerialId(34) val groupOpenAppid: Int? = null,
@SerialId(35) val noFingerOpenFlag: Int? = null,
@SerialId(36) val noCodeFingerOpenFlag: Int? = null,
@SerialId(37) val rootId: Long? = null,
@SerialId(38) val msgLimitFrequency: Int? = null
) : ProtoBuf
@Serializable
class RspBody(
@SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val errorinfo: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf
@Serializable
class GroupExInfoOnly(
@SerialId(1) val tribeId: Int = 0,
@SerialId(2) val moneyForAddGroup: Int = 0
) : ProtoBuf
@Serializable
class GroupGeoInfo(
@SerialId(1) val cityId: Int = 0,
@SerialId(2) val longtitude: Long = 0L,
@SerialId(3) val latitude: Long = 0L,
@SerialId(4) val ingGeoContent: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(5) val poiId: Long = 0L
) : ProtoBuf
@Serializable
class ReqBody(
@SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val stGroupInfo: Oidb0x89a.Groupinfo? = null,
@SerialId(3) val originalOperatorUin: Long = 0L,
@SerialId(4) val reqGroupOpenAppid: Int = 0
) : ProtoBuf
}
@Serializable
class Cmd0x7cb : ProtoBuf {

View File

@ -127,7 +127,8 @@ internal object KnownPacketFactories {
LongConn.OffPicDown,
TroopManagement.EditNametag,
TroopManagement.Mute,
TroopManagement.MuteAll
TroopManagement.updateGroupInfo,
TroopManagement.getGroupInfo
)
object IncomingFactories : List<IncomingPacketFactory<*>> by mutableListOf(

View File

@ -3,10 +3,14 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.buildPacket
import kotlinx.io.core.readBytes
import kotlinx.io.core.toByteArray
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import net.mamoe.mirai.qqandroid.io.serialization.writeProtoBuf
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Oidb0x88d
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Oidb0x89a
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.OidbSso
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
@ -14,6 +18,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.utils.daysToSeconds
import net.mamoe.mirai.utils.io.debugPrintThis
internal object TroopManagement {
@ -53,10 +58,9 @@ internal object TroopManagement {
}
internal object MuteAll : OutgoingPacketFactory<MuteAll.Response>("OidbSvc.0x89a_0") {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
return Response
}
internal object getGroupInfo : OutgoingPacketFactory<getGroupInfo.Response>("OidbSvc.0x88d_7") {
class Response() : Packet
operator fun invoke(
client: QQAndroidClient,
@ -66,18 +70,198 @@ internal object TroopManagement {
writeProtoBuf(
OidbSso.OIDBSSOPkg.serializer(),
OidbSso.OIDBSSOPkg(
command = 2202,
serviceType = 0,
command = 2189,
serviceType = 7,
result = 0,
bodybuffer = EMPTY_BYTE_ARRAY//TODO
bodybuffer = Oidb0x88d.ReqBody(
appid = 537062845,
stzreqgroupinfo = listOf(
Oidb0x88d.ReqGroupInfo(
stgroupinfo = Oidb0x88d.GroupInfo(
groupFlagExt = 0,
groupFlagext4 = 0,
groupFlag = 0,
groupFlagext3 = 0,//获取confess
noFingerOpenFlag = 0,
cmduinFlagEx2 = 0,
groupTypeFlag = 0,
appPrivilegeFlag = 0,
cmduinFlagEx = 0,
cmduinNewMobileFlag = 0,
cmduinUinFlag = 0,
createSourceFlag = 0,
noCodeFingerOpenFlag = 0,
ingGroupQuestion = EMPTY_BYTE_ARRAY,
ingGroupAnswer = EMPTY_BYTE_ARRAY
),
groupCode = groupCode
)
)
).toByteArray(Oidb0x88d.ReqBody.serializer())
)
)
}
}
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
debugPrintThis()
return Response()
}
}
internal object updateGroupInfo : OutgoingPacketFactory<updateGroupInfo.Response>("OidbSvc.0x89a_0") {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
return Response
}
fun muteAll(
client: QQAndroidClient,
groupCode: Long,
switch: Boolean
): OutgoingPacket {
return buildOutgoingUniPacket(client) {
writeProtoBuf(
OidbSso.OIDBSSOPkg.serializer(),
OidbSso.OIDBSSOPkg(
command = 2202,
bodybuffer = Oidb0x89a.ReqBody(
groupCode = groupCode,
stGroupInfo = Oidb0x89a.Groupinfo(
shutupTime = if (switch) {
1
} else {
0
}
)
).toByteArray(Oidb0x89a.ReqBody.serializer())
)
)
}
}
fun confessTalk(
client: QQAndroidClient,
groupCode: Long,
switch: Boolean
): OutgoingPacket {
return buildOutgoingUniPacket(client) {
writeProtoBuf(
OidbSso.OIDBSSOPkg.serializer(),
OidbSso.OIDBSSOPkg(
command = 2202,
bodybuffer = Oidb0x89a.ReqBody(
groupCode = groupCode,
stGroupInfo = Oidb0x89a.Groupinfo(
groupFlagext3Mask = 8192,
groupFlagext3 = if (switch) {
0
} else {
8192
}
)
).toByteArray(Oidb0x89a.ReqBody.serializer())
)
)
}
}
fun autoApprove(
client: QQAndroidClient,
groupCode: Long,
switch: Boolean
): OutgoingPacket {
return buildOutgoingUniPacket(client) {
writeProtoBuf(
OidbSso.OIDBSSOPkg.serializer(),
OidbSso.OIDBSSOPkg(
command = 2202,
bodybuffer = Oidb0x89a.ReqBody(
groupCode = groupCode,
stGroupInfo = Oidb0x89a.Groupinfo(
groupFlagext3 = if (switch) {
0x00100000
} else {
0x00000000
}//暂时无效
)
).toByteArray(Oidb0x89a.ReqBody.serializer())
)
)
}
}
fun name(
client: QQAndroidClient,
groupCode: Long,
newName: String
): OutgoingPacket {
return buildOutgoingUniPacket(client) {
writeProtoBuf(
OidbSso.OIDBSSOPkg.serializer(),
OidbSso.OIDBSSOPkg(
command = 2202,
bodybuffer = Oidb0x89a.ReqBody(
groupCode = groupCode,
stGroupInfo = Oidb0x89a.Groupinfo(
ingGroupName = newName.toByteArray()
)
).toByteArray(Oidb0x89a.ReqBody.serializer())
)
)
}
}
fun memo(
client: QQAndroidClient,
groupCode: Long,
newMemo: String
): OutgoingPacket {
return buildOutgoingUniPacket(client) {
writeProtoBuf(
OidbSso.OIDBSSOPkg.serializer(),
OidbSso.OIDBSSOPkg(
command = 2202,
bodybuffer = Oidb0x89a.ReqBody(
groupCode = groupCode,
stGroupInfo = Oidb0x89a.Groupinfo(
ingGroupMemo = newMemo.toByteArray()
)
).toByteArray(Oidb0x89a.ReqBody.serializer())
)
)
}
}
fun allowMemberInvite(
client: QQAndroidClient,
groupCode: Long,
switch: Boolean
): OutgoingPacket {
return buildOutgoingUniPacket(client) {
writeProtoBuf(
OidbSso.OIDBSSOPkg.serializer(),
OidbSso.OIDBSSOPkg(
command = 2202,
bodybuffer = Oidb0x89a.ReqBody(
groupCode = groupCode,
stGroupInfo = Oidb0x89a.Groupinfo(
allowMemberInvite = if (switch) {
1
} else {
0
}
)
).toByteArray(Oidb0x89a.ReqBody.serializer())
)
)
}
}
object Response : Packet
}
internal object EditNametag : OutgoingPacketFactory<LoginPacket.LoginPacketResponse>("OidbSvc.0x8fc_2") {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): LoginPacket.LoginPacketResponse {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.

View File

@ -6,7 +6,7 @@ import java.io.File
fun main() {
println(
File("""/Users/jiahua.liu/Desktop/QQAndroid-F/app/src/main/java/tencent/im/s2c/msgtype0x210/submsgtype0xc7/bussinfo/mutualmark""")
File("""/Users/jiahua.liu/Desktop/QQAndroid-F/app/src/main/java/tencent/im/oidb/cmd0x88d/""")
.generateUnarrangedClasses().toMutableList().arrangeClasses().joinToString("\n\n")
)
}

View File

@ -9,6 +9,51 @@ import kotlinx.coroutines.CoroutineScope
* . QQ Android 中叫做 "Troop"
*/
interface Group : Contact, CoroutineScope {
/**
* ====以下字段在更新值的时候会自动异步上报服务器更改群信息====
*/
/**
* 群名称
* [可查可改已完成]
*/
var name: String
/**
* 入群公告, 没有时为空字符串
* [可查可改已完成]
*/
var announcement: String
/**
* 全体禁言状态
* [可改已完成]
*/
var muteAll: Boolean
/**
* 坦白说状态
* [可查可改已完成]
*/
var confessTalk: Boolean
/**
* 允许群员拉人状态
* [可查可改已完成]
*/
var allowMemberInvite: Boolean
/**
* QQ中的自动加群审批
* [可查已完成]
*/
val autoApprove: Boolean
/**
* 匿名聊天
* [可查已完成]
*/
val anonymousChat: Boolean
/**
* ====以上字段在更新值的时候会自动异步上报服务器更改群信息====
*/
/**
* 同为 groupCode, 用户看到的群号码.
*/
@ -22,22 +67,12 @@ interface Group : Contact, CoroutineScope {
val botPermission: MemberPermission
/**
* 群名称 (同步事件更新)
*/
val name: String
/**
* 入群公告, 没有时为空字符串. (同步事件更新)
*/
val announcement: String
/**
* [Group] 实例创建的时候查询一次. 并与事件同步事件更新
*/
val members: ContactList<Member>
/**
* 获取群成员实例. 若此 id 的成员不存在, 则会抛出 [kotlin.NoSuchElementException]
*/
@ -58,5 +93,6 @@ interface Group : Contact, CoroutineScope {
*/
suspend fun quit(): Boolean
fun toFullString(): String = "Group(id=${this.id}, name=$name, owner=${owner.id}, members=${members.idContentString})"
}