mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-23 22:30:47 +08:00
Android GroupMessage support
This commit is contained in:
parent
c42169a238
commit
6c2b435779
@ -0,0 +1,108 @@
|
|||||||
|
package net.mamoe.mirai.qqandroid
|
||||||
|
|
||||||
|
import net.mamoe.mirai.Bot
|
||||||
|
import net.mamoe.mirai.contact.*
|
||||||
|
import net.mamoe.mirai.data.FriendNameRemark
|
||||||
|
import net.mamoe.mirai.data.GroupInfo
|
||||||
|
import net.mamoe.mirai.data.PreviousNameList
|
||||||
|
import net.mamoe.mirai.data.Profile
|
||||||
|
import net.mamoe.mirai.message.data.ImageId
|
||||||
|
import net.mamoe.mirai.message.data.MessageChain
|
||||||
|
import net.mamoe.mirai.utils.*
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
internal abstract class ContactImpl : Contact
|
||||||
|
|
||||||
|
internal class QQImpl(bot: Bot, override val coroutineContext: CoroutineContext, override val id: Long) : ContactImpl(), QQ {
|
||||||
|
override val bot: Bot by bot.unsafeWeakRef()
|
||||||
|
|
||||||
|
override suspend fun sendMessage(message: MessageChain) {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun uploadImage(image: ExternalImage): ImageId {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun queryProfile(): Profile {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun queryPreviousNameList(): PreviousNameList {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun queryRemark(): FriendNameRemark {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MemberImpl(bot: Bot, group: Group, override val coroutineContext: CoroutineContext, override val id: Long) : ContactImpl(), Member {
|
||||||
|
override val group: Group by group.unsafeWeakRef()
|
||||||
|
override val permission: MemberPermission
|
||||||
|
get() = TODO("not implemented")
|
||||||
|
override val bot: Bot by bot.unsafeWeakRef()
|
||||||
|
|
||||||
|
override suspend fun mute(durationSeconds: Int): Boolean {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun unmute() {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun queryProfile(): Profile {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun queryPreviousNameList(): PreviousNameList {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun queryRemark(): FriendNameRemark {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun sendMessage(message: MessageChain) {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun uploadImage(image: ExternalImage): ImageId {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@UseExperimental(MiraiInternalAPI::class)
|
||||||
|
internal class GroupImpl(bot: Bot, override val coroutineContext: CoroutineContext, override val id: Long) : ContactImpl(), Group {
|
||||||
|
override val internalId: GroupInternalId = GroupId(id).toInternalId()
|
||||||
|
override val owner: Member
|
||||||
|
get() = TODO("not implemented")
|
||||||
|
override val name: String
|
||||||
|
get() = TODO("not implemented")
|
||||||
|
override val announcement: String
|
||||||
|
get() = TODO("not implemented")
|
||||||
|
override val members: ContactList<Member> = ContactList(LockFreeLinkedList())
|
||||||
|
|
||||||
|
override fun getMember(id: Long): Member = members.delegate.filteringGetOrAdd({ it.id == id }, { MemberImpl(bot, this, coroutineContext, id) })
|
||||||
|
|
||||||
|
override suspend fun updateGroupInfo(): GroupInfo {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun quit(): Boolean {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val bot: Bot by bot.unsafeWeakRef()
|
||||||
|
|
||||||
|
override suspend fun sendMessage(message: MessageChain) {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun uploadImage(image: ExternalImage): ImageId {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
|
|||||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||||
import net.mamoe.mirai.qqandroid.utils.Context
|
import net.mamoe.mirai.qqandroid.utils.Context
|
||||||
import net.mamoe.mirai.utils.BotConfiguration
|
import net.mamoe.mirai.utils.BotConfiguration
|
||||||
|
import net.mamoe.mirai.utils.LockFreeLinkedList
|
||||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
@ -27,30 +28,30 @@ internal abstract class QQAndroidBotBase constructor(
|
|||||||
) : BotImpl<QQAndroidBotNetworkHandler>(account, configuration) {
|
) : BotImpl<QQAndroidBotNetworkHandler>(account, configuration) {
|
||||||
val client: QQAndroidClient = QQAndroidClient(context, account, bot = @Suppress("LeakingThis") this as QQAndroidBot)
|
val client: QQAndroidClient = QQAndroidClient(context, account, bot = @Suppress("LeakingThis") this as QQAndroidBot)
|
||||||
|
|
||||||
override val qqs: ContactList<QQ>
|
override val qqs: ContactList<QQ> = ContactList(LockFreeLinkedList())
|
||||||
get() = TODO("not implemented")
|
|
||||||
|
|
||||||
override fun getQQ(id: Long): QQ {
|
override fun getQQ(id: Long): QQ {
|
||||||
TODO("not implemented")
|
return qqs.delegate.filteringGetOrAdd({ it.id == id }, { QQImpl(this, coroutineContext, id) })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createNetworkHandler(coroutineContext: CoroutineContext): QQAndroidBotNetworkHandler {
|
override fun createNetworkHandler(coroutineContext: CoroutineContext): QQAndroidBotNetworkHandler {
|
||||||
return QQAndroidBotNetworkHandler(this as QQAndroidBot)
|
return QQAndroidBotNetworkHandler(this as QQAndroidBot)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val groups: ContactList<Group>
|
override val groups: ContactList<Group> = ContactList(LockFreeLinkedList())
|
||||||
get() = TODO("not implemented")
|
|
||||||
|
|
||||||
override suspend fun getGroup(id: GroupId): Group {
|
override suspend fun getGroup(id: GroupId): Group {
|
||||||
TODO("not implemented")
|
return groups.delegate.filteringGetOrAdd({ it.id == id.value }, { GroupImpl(this, coroutineContext, id.value) })
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getGroup(internalId: GroupInternalId): Group {
|
override suspend fun getGroup(internalId: GroupInternalId): Group {
|
||||||
TODO("not implemented")
|
internalId.toId().value.let { id ->
|
||||||
|
return groups.delegate.filteringGetOrAdd({ it.id == id }, { GroupImpl(this, coroutineContext, id) })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getGroup(id: Long): Group {
|
override suspend fun getGroup(id: Long): Group {
|
||||||
TODO("not implemented")
|
return groups.delegate.filteringGetOrAdd({ it.id == id }, { GroupImpl(this, coroutineContext, id) })
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun Image.getLink(): ImageLink {
|
override suspend fun Image.getLink(): ImageLink {
|
||||||
|
@ -4,6 +4,9 @@ import kotlinx.coroutines.*
|
|||||||
import kotlinx.io.core.*
|
import kotlinx.io.core.*
|
||||||
import kotlinx.io.pool.ObjectPool
|
import kotlinx.io.pool.ObjectPool
|
||||||
import net.mamoe.mirai.data.Packet
|
import net.mamoe.mirai.data.Packet
|
||||||
|
import net.mamoe.mirai.event.BroadcastControllable
|
||||||
|
import net.mamoe.mirai.event.Cancellable
|
||||||
|
import net.mamoe.mirai.event.Subscribable
|
||||||
import net.mamoe.mirai.event.broadcast
|
import net.mamoe.mirai.event.broadcast
|
||||||
import net.mamoe.mirai.network.BotNetworkHandler
|
import net.mamoe.mirai.network.BotNetworkHandler
|
||||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||||
@ -12,7 +15,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.KnownPacketFactories
|
|||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket.LoginPacketResponse.*
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket.LoginPacketResponse.*
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc
|
||||||
import net.mamoe.mirai.utils.*
|
import net.mamoe.mirai.utils.*
|
||||||
import net.mamoe.mirai.utils.io.*
|
import net.mamoe.mirai.utils.io.*
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
@ -48,7 +51,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}")
|
println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}")
|
||||||
SvcReqRegisterPacket(bot.client).sendAndExpect<SvcReqRegisterPacket.Response>()
|
StatSvc.Register(bot.client).sendAndExpect<StatSvc.Register.Response>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,11 +116,26 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
if (PacketReceivedEvent(packet).broadcast().cancelled) {
|
if (PacketReceivedEvent(packet).broadcast().cancelled) {
|
||||||
return@parseIncomingPacket
|
return@parseIncomingPacket
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pass to listeners (attached by sendAndExpect).
|
||||||
packetListeners.forEach { listener ->
|
packetListeners.forEach { listener ->
|
||||||
if (listener.filter(commandName, sequenceId) && packetListeners.remove(listener)) {
|
if (listener.filter(commandName, sequenceId) && packetListeners.remove(listener)) {
|
||||||
listener.complete(packet)
|
listener.complete(packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// broadcast
|
||||||
|
if (packet is Subscribable) {
|
||||||
|
if (packet is BroadcastControllable) {
|
||||||
|
if (packet.shouldBroadcast) packet.broadcast()
|
||||||
|
} else {
|
||||||
|
packet.broadcast()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet is Cancellable && packet.cancelled) return@parseIncomingPacket
|
||||||
|
}
|
||||||
|
|
||||||
|
bot.logger.info(packet)
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
println()
|
println()
|
||||||
|
@ -3,33 +3,56 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
|
|||||||
import kotlinx.io.core.ByteReadPacket
|
import kotlinx.io.core.ByteReadPacket
|
||||||
import kotlinx.io.core.discardExact
|
import kotlinx.io.core.discardExact
|
||||||
import kotlinx.io.core.readBytes
|
import kotlinx.io.core.readBytes
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.protobuf.ProtoBuf
|
import kotlinx.serialization.protobuf.ProtoBuf
|
||||||
|
import net.mamoe.mirai.contact.MemberPermission
|
||||||
import net.mamoe.mirai.message.GroupMessage
|
import net.mamoe.mirai.message.GroupMessage
|
||||||
|
import net.mamoe.mirai.message.data.Image
|
||||||
|
import net.mamoe.mirai.message.data.MessageChain
|
||||||
|
import net.mamoe.mirai.message.data.toMessage
|
||||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.MessageCommon
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.ImMsgBody
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.MsgOnlinePush
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.MsgOnlinePush
|
||||||
|
import net.mamoe.mirai.utils.io.encodeToString
|
||||||
|
|
||||||
internal class OnlinePush {
|
internal class OnlinePush {
|
||||||
internal object PbPushGroupMsg : PacketFactory<GroupMessage>("OnlinePush.PbPushGroupMsg") {
|
internal object PbPushGroupMsg : PacketFactory<GroupMessage>("OnlinePush.PbPushGroupMsg") {
|
||||||
|
@UseExperimental(ExperimentalStdlibApi::class)
|
||||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GroupMessage {
|
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GroupMessage {
|
||||||
// 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00
|
// 00 00 02 E4 0A D5 05 0A 4F 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 52 20 00 28 BC 3D 30 8C 82 AB F1 05 38 D2 80 E0 8C 80 80 80 80 02 4A 21 08 E7 C1 AD B8 02 10 01 18 BA 05 22 09 48 69 6D 31 38 38 6D 6F 65 30 06 38 02 42 05 4D 69 72 61 69 50 01 58 01 60 00 88 01 08 12 06 08 01 10 00 18 00 1A F9 04 0A F6 04 0A 26 08 00 10 87 82 AB F1 05 18 B7 B4 BF 30 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 E6 03 42 E3 03 12 2A 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 22 00 2A 04 03 00 00 00 32 60 15 36 20 39 36 6B 45 31 41 38 35 32 32 39 64 63 36 39 38 34 37 39 37 37 62 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 34 45 31 38 35 38 32 32 2D 30 45 37 42 2D 46 38 30 46 2D 43 35 42 31 2D 33 34 34 38 38 33 37 34 44 33 39 43 7D 2E 6A 70 67 31 32 31 32 41 38 C6 BB 8A A9 08 40 FB AE 9E C2 09 48 50 50 41 5A 00 60 01 6A 10 4E 18 58 22 0E 7B F8 0F C5 B1 34 48 83 74 D3 9C 72 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 31 39 38 3F 74 65 72 6D 3D 32 82 01 57 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 30 3F 74 65 72 6D 3D 32 B0 01 4D B8 01 2E C8 01 FF 05 D8 01 4D E0 01 2E FA 01 59 2F 67 63 68 61 74 70 69 63 5F 6E 65 77 2F 31 30 34 30 34 30 30 32 39 30 2F 36 35 35 30 35 37 31 32 37 2D 32 32 33 33 36 33 38 33 34 32 2D 34 45 31 38 35 38 32 32 30 45 37 42 46 38 30 46 43 35 42 31 33 34 34 38 38 33 37 34 44 33 39 43 2F 34 30 30 3F 74 65 72 6D 3D 32 80 02 4D 88 02 2E 12 45 AA 02 42 50 03 60 00 68 00 9A 01 39 08 09 20 BF 50 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 04 08 02 08 01 90 04 80 80 80 10 B8 04 00 C0 04 00 12 06 4A 04 08 00 40 01 12 14 82 01 11 0A 09 48 69 6D 31 38 38 6D 6F 65 18 06 20 08 28 03 10 8A CA 9D A1 07 1A 00
|
||||||
discardExact(4)
|
discardExact(4)
|
||||||
println(ProtoBuf.load(MsgOnlinePush.PbPushMsg.serializer(), readBytes()))
|
val pbPushMsg = ProtoBuf.load(MsgOnlinePush.PbPushMsg.serializer(), readBytes())
|
||||||
TODO()
|
val message = MessageChain(initialCapacity = pbPushMsg.msg!!.msgBody!!.richText!!.elems!!.size)
|
||||||
|
|
||||||
|
var extraInfo: ImMsgBody.ExtraInfo? = null
|
||||||
|
|
||||||
|
pbPushMsg.msg.msgBody!!.richText!!.elems!!.forEach {
|
||||||
|
when {
|
||||||
|
it.customFace != null -> message.add(Image(it.customFace.filePath))
|
||||||
|
it.text != null -> message.add(it.text.str.encodeToString().toMessage())
|
||||||
|
it.extraInfo != null -> extraInfo = it.extraInfo
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
val group = bot.getGroup(pbPushMsg.msg.msgHead!!.groupInfo!!.groupCode)
|
||||||
* 1 -> delimi
|
|
||||||
* 2 -> varint
|
val flags = extraInfo?.flags?:0
|
||||||
* 3 -> delimi
|
return GroupMessage(
|
||||||
* 4 -> varint
|
bot = bot,
|
||||||
* 9 -> varint
|
group = group,
|
||||||
*/
|
senderName = pbPushMsg.msg.msgHead.groupInfo!!.groupCard.encodeToString(),
|
||||||
@Serializable
|
sender = group.getMember(pbPushMsg.msg.msgHead.fromUin),
|
||||||
private class PbPushMsg(
|
message = message,
|
||||||
val msg: MessageCommon.Msg
|
permission = when{
|
||||||
|
flags and 16 != 0 -> MemberPermission.ADMINISTRATOR
|
||||||
|
flags and 8 != 0 -> MemberPermission.OWNER
|
||||||
|
flags and 0 != 0 -> MemberPermission.MEMBER
|
||||||
|
else -> {
|
||||||
|
bot.logger.warning("判断群员权限失败")
|
||||||
|
MemberPermission.MEMBER
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
@ -0,0 +1,131 @@
|
|||||||
|
package net.mamoe.mirai.qqandroid.network.protocol.packet.login
|
||||||
|
|
||||||
|
import kotlinx.io.core.ByteReadPacket
|
||||||
|
import kotlinx.serialization.protobuf.ProtoBuf
|
||||||
|
import net.mamoe.mirai.data.Packet
|
||||||
|
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||||
|
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||||
|
import net.mamoe.mirai.qqandroid.network.io.jceMap
|
||||||
|
import net.mamoe.mirai.qqandroid.network.io.jceStruct
|
||||||
|
import net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister
|
||||||
|
import net.mamoe.mirai.qqandroid.network.protocol.jce.writeUniRequestPacket
|
||||||
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||||
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
|
||||||
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
|
||||||
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
|
||||||
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
|
||||||
|
import net.mamoe.mirai.qqandroid.utils.NetworkType
|
||||||
|
import net.mamoe.mirai.utils.io.debugPrint
|
||||||
|
import net.mamoe.mirai.utils.io.encodeToString
|
||||||
|
import net.mamoe.mirai.utils.io.toReadPacket
|
||||||
|
import net.mamoe.mirai.utils.localIpAddress
|
||||||
|
|
||||||
|
@Suppress("EnumEntryName")
|
||||||
|
enum class RegPushReason {
|
||||||
|
appRegister,
|
||||||
|
createDefaultRegInfo,
|
||||||
|
fillRegProxy,
|
||||||
|
msfBoot,
|
||||||
|
msfByNetChange,
|
||||||
|
msfHeartTimeTooLong,
|
||||||
|
serverPush,
|
||||||
|
setOnlineStatus,
|
||||||
|
unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
class StatSvc {
|
||||||
|
internal object Register : PacketFactory<Register.Response>("StatSvc.register") {
|
||||||
|
|
||||||
|
internal object Response : Packet {
|
||||||
|
override fun toString(): String = "Response(StatSvc.register)"
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val subAppId = 537062845L
|
||||||
|
|
||||||
|
operator fun invoke(
|
||||||
|
client: QQAndroidClient,
|
||||||
|
regPushReason: RegPushReason = RegPushReason.appRegister
|
||||||
|
): OutgoingPacket = buildLoginOutgoingPacket(
|
||||||
|
client,
|
||||||
|
bodyType = 1,
|
||||||
|
extraData = client.wLoginSigInfo.d2.data,
|
||||||
|
key = client.wLoginSigInfo.d2Key
|
||||||
|
) { sequenceId ->
|
||||||
|
writeSsoPacket(
|
||||||
|
client, subAppId = subAppId, commandName = commandName,
|
||||||
|
extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId
|
||||||
|
) {
|
||||||
|
writeUniRequestPacket {
|
||||||
|
sServantName = "PushService"
|
||||||
|
sFuncName = "SvcReqRegister"
|
||||||
|
sBuffer = jceMap(
|
||||||
|
0,
|
||||||
|
"SvcReqRegister" to jceStruct(
|
||||||
|
0,
|
||||||
|
SvcReqRegister().apply {
|
||||||
|
cConnType = 0
|
||||||
|
lBid = 1 or 2 or 4
|
||||||
|
lUin = client.uin
|
||||||
|
iStatus = client.onlineStatus.id
|
||||||
|
bKikPC = 0 // 是否把 PC 踢下线
|
||||||
|
bKikWeak = 0
|
||||||
|
timeStamp = 0
|
||||||
|
// timeStamp = currentTimeSeconds // millis or seconds??
|
||||||
|
iLargeSeq = 1551 // ?
|
||||||
|
bOpenPush = 1
|
||||||
|
iLocaleID = 2052
|
||||||
|
bRegType =
|
||||||
|
(if (regPushReason == RegPushReason.appRegister ||
|
||||||
|
regPushReason == RegPushReason.fillRegProxy ||
|
||||||
|
regPushReason == RegPushReason.createDefaultRegInfo ||
|
||||||
|
regPushReason == RegPushReason.setOnlineStatus
|
||||||
|
) 0 else 1).toByte()
|
||||||
|
bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0
|
||||||
|
iOSVersion = client.device.version.sdk.toLong()
|
||||||
|
cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0
|
||||||
|
vecGuid = client.device.guid
|
||||||
|
strDevName = client.device.model.encodeToString()
|
||||||
|
strDevType = client.device.model.encodeToString()
|
||||||
|
strOSVer = client.device.version.release.encodeToString()
|
||||||
|
|
||||||
|
uOldSSOIp = 0
|
||||||
|
uNewSSOIp = localIpAddress().split(".").foldIndexed(0L) { index: Int, acc: Long, s: String ->
|
||||||
|
acc or ((s.toLong() shl (index * 16)))
|
||||||
|
}
|
||||||
|
strVendorName = "MIUI"
|
||||||
|
strVendorOSName = "?ONEPLUS A5000_23_17"
|
||||||
|
// register 时还需要
|
||||||
|
/*
|
||||||
|
var44.uNewSSOIp = field_127445;
|
||||||
|
var44.uOldSSOIp = field_127444;
|
||||||
|
var44.strVendorName = ROMUtil.getRomName();
|
||||||
|
var44.strVendorOSName = ROMUtil.getRomVersion(20);
|
||||||
|
*/
|
||||||
|
bytes_0x769_reqbody = ProtoBuf.dump(
|
||||||
|
Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody(
|
||||||
|
rpt_config_list = listOf(
|
||||||
|
Oidb0x769.ConfigSeq(
|
||||||
|
type = 46,
|
||||||
|
version = 0
|
||||||
|
),
|
||||||
|
Oidb0x769.ConfigSeq(
|
||||||
|
type = 283,
|
||||||
|
version = 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
bSetMute = 0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
this.writePacket(this.build().debugPrint("sso body"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
||||||
|
return Response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,127 +0,0 @@
|
|||||||
package net.mamoe.mirai.qqandroid.network.protocol.packet.login
|
|
||||||
|
|
||||||
import kotlinx.io.core.ByteReadPacket
|
|
||||||
import kotlinx.serialization.protobuf.ProtoBuf
|
|
||||||
import net.mamoe.mirai.data.Packet
|
|
||||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
|
||||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
|
||||||
import net.mamoe.mirai.qqandroid.network.io.jceMap
|
|
||||||
import net.mamoe.mirai.qqandroid.network.io.jceStruct
|
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister
|
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.jce.writeUniRequestPacket
|
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
|
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
|
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
|
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
|
|
||||||
import net.mamoe.mirai.qqandroid.utils.NetworkType
|
|
||||||
import net.mamoe.mirai.utils.io.debugPrint
|
|
||||||
import net.mamoe.mirai.utils.io.encodeToString
|
|
||||||
import net.mamoe.mirai.utils.io.toReadPacket
|
|
||||||
import net.mamoe.mirai.utils.localIpAddress
|
|
||||||
|
|
||||||
@Suppress("EnumEntryName")
|
|
||||||
enum class RegPushReason {
|
|
||||||
appRegister,
|
|
||||||
createDefaultRegInfo,
|
|
||||||
fillRegProxy,
|
|
||||||
msfBoot,
|
|
||||||
msfByNetChange,
|
|
||||||
msfHeartTimeTooLong,
|
|
||||||
serverPush,
|
|
||||||
setOnlineStatus,
|
|
||||||
unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Response>("StatSvc.register") {
|
|
||||||
|
|
||||||
internal object Response : Packet
|
|
||||||
|
|
||||||
private const val subAppId = 537062845L
|
|
||||||
|
|
||||||
operator fun invoke(
|
|
||||||
client: QQAndroidClient,
|
|
||||||
regPushReason: RegPushReason = RegPushReason.appRegister
|
|
||||||
): OutgoingPacket = buildLoginOutgoingPacket(
|
|
||||||
client,
|
|
||||||
bodyType = 1,
|
|
||||||
extraData = client.wLoginSigInfo.d2.data,
|
|
||||||
key = client.wLoginSigInfo.d2Key
|
|
||||||
) { sequenceId ->
|
|
||||||
writeSsoPacket(
|
|
||||||
client, subAppId = subAppId, commandName = commandName,
|
|
||||||
extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId
|
|
||||||
) {
|
|
||||||
writeUniRequestPacket {
|
|
||||||
sServantName = "PushService"
|
|
||||||
sFuncName = "SvcReqRegister"
|
|
||||||
sBuffer = jceMap(
|
|
||||||
0,
|
|
||||||
"SvcReqRegister" to jceStruct(
|
|
||||||
0,
|
|
||||||
SvcReqRegister().apply {
|
|
||||||
cConnType = 0
|
|
||||||
lBid = 1 or 2 or 4
|
|
||||||
lUin = client.uin
|
|
||||||
iStatus = client.onlineStatus.id
|
|
||||||
bKikPC = 0 // 是否把 PC 踢下线
|
|
||||||
bKikWeak = 0
|
|
||||||
timeStamp = 0
|
|
||||||
// timeStamp = currentTimeSeconds // millis or seconds??
|
|
||||||
iLargeSeq = 1551 // ?
|
|
||||||
bOpenPush = 1
|
|
||||||
iLocaleID = 2052
|
|
||||||
bRegType =
|
|
||||||
(if (regPushReason == RegPushReason.appRegister ||
|
|
||||||
regPushReason == RegPushReason.fillRegProxy ||
|
|
||||||
regPushReason == RegPushReason.createDefaultRegInfo ||
|
|
||||||
regPushReason == RegPushReason.setOnlineStatus
|
|
||||||
) 0 else 1).toByte()
|
|
||||||
bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0
|
|
||||||
iOSVersion = client.device.version.sdk.toLong()
|
|
||||||
cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0
|
|
||||||
vecGuid = client.device.guid
|
|
||||||
strDevName = client.device.model.encodeToString()
|
|
||||||
strDevType = client.device.model.encodeToString()
|
|
||||||
strOSVer = client.device.version.release.encodeToString()
|
|
||||||
|
|
||||||
uOldSSOIp = 0
|
|
||||||
uNewSSOIp = localIpAddress().split(".").foldIndexed(0L) { index: Int, acc: Long, s: String ->
|
|
||||||
acc or ((s.toLong() shl (index * 16)))
|
|
||||||
}
|
|
||||||
strVendorName = "MIUI"
|
|
||||||
strVendorOSName = "?ONEPLUS A5000_23_17"
|
|
||||||
// register 时还需要
|
|
||||||
/*
|
|
||||||
var44.uNewSSOIp = field_127445;
|
|
||||||
var44.uOldSSOIp = field_127444;
|
|
||||||
var44.strVendorName = ROMUtil.getRomName();
|
|
||||||
var44.strVendorOSName = ROMUtil.getRomVersion(20);
|
|
||||||
*/
|
|
||||||
bytes_0x769_reqbody = ProtoBuf.dump(
|
|
||||||
Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody(
|
|
||||||
rpt_config_list = listOf(
|
|
||||||
Oidb0x769.ConfigSeq(
|
|
||||||
type = 46,
|
|
||||||
version = 0
|
|
||||||
),
|
|
||||||
Oidb0x769.ConfigSeq(
|
|
||||||
type = 283,
|
|
||||||
version = 0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
bSetMute = 0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
this.writePacket(this.build().debugPrint("sso body"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
|
||||||
return Response
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,7 @@ import java.lang.reflect.Field
|
|||||||
import kotlin.reflect.full.allSuperclasses
|
import kotlin.reflect.full.allSuperclasses
|
||||||
|
|
||||||
|
|
||||||
actual fun Any.contentToStringReflectively(prefix: String): String {
|
actual fun Any.contentToStringReflectively(prefix: String, filter: ((name: String, value: Any?) -> Boolean)?): String {
|
||||||
val newPrefix = prefix
|
val newPrefix = prefix
|
||||||
return (this::class.simpleName ?: "<UnnamedClass>") + "#" + this::class.hashCode() + " {\n" +
|
return (this::class.simpleName ?: "<UnnamedClass>") + "#" + this::class.hashCode() + " {\n" +
|
||||||
this.allFieldsFromSuperClassesMatching { it.name.startsWith("net.mamoe.mirai") }
|
this.allFieldsFromSuperClassesMatching { it.name.startsWith("net.mamoe.mirai") }
|
||||||
@ -14,6 +14,11 @@ actual fun Any.contentToStringReflectively(prefix: String): String {
|
|||||||
prefix = newPrefix
|
prefix = newPrefix
|
||||||
) {
|
) {
|
||||||
it.isAccessible = true
|
it.isAccessible = true
|
||||||
|
if (filter != null) {
|
||||||
|
kotlin.runCatching {
|
||||||
|
if (!filter(it.name, it.get(this))) return@joinToStringPrefixed ""
|
||||||
|
}
|
||||||
|
}
|
||||||
it.name + "=" + kotlin.runCatching {
|
it.name + "=" + kotlin.runCatching {
|
||||||
val value = it.get(this)
|
val value = it.get(this)
|
||||||
if (value == this) "<this>"
|
if (value == this) "<this>"
|
||||||
|
@ -242,7 +242,7 @@ object NullMessageChain : MessageChain {
|
|||||||
|
|
||||||
override fun contains(sub: String): Boolean = error("accessing NullMessageChain")
|
override fun contains(sub: String): Boolean = error("accessing NullMessageChain")
|
||||||
override fun contains(element: Message): Boolean = error("accessing NullMessageChain")
|
override fun contains(element: Message): Boolean = error("accessing NullMessageChain")
|
||||||
override fun followedBy(tail: Message): MessageChain = error("accessing NullMessageChain")
|
override fun followedBy(tail: Message): MessageChain = tail.toChain()
|
||||||
|
|
||||||
override val size: Int get() = error("accessing NullMessageChain")
|
override val size: Int get() = error("accessing NullMessageChain")
|
||||||
override fun containsAll(elements: Collection<Message>): Boolean = error("accessing NullMessageChain")
|
override fun containsAll(elements: Collection<Message>): Boolean = error("accessing NullMessageChain")
|
||||||
|
@ -222,7 +222,7 @@ fun Any?.contentToString(prefix: String = ""): String = when (this) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expect fun Any.contentToStringReflectively(prefix: String = ""): String
|
expect fun Any.contentToStringReflectively(prefix: String = "", filter: ((String, Any?) -> Boolean)? = null): String
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun ByteReadPacket.readProtoMap(length: Long = this.remaining): ProtoMap {
|
fun ByteReadPacket.readProtoMap(length: Long = this.remaining): ProtoMap {
|
||||||
|
@ -6,19 +6,28 @@ import kotlin.reflect.full.allSuperclasses
|
|||||||
|
|
||||||
val FIELD_TRY_SET_ACCESSIBLE = Field::class.java.declaredMethods.firstOrNull { it.name == "trySetAccessible" }
|
val FIELD_TRY_SET_ACCESSIBLE = Field::class.java.declaredMethods.firstOrNull { it.name == "trySetAccessible" }
|
||||||
|
|
||||||
actual fun Any.contentToStringReflectively(prefix: String): String {
|
actual fun Any.contentToStringReflectively(prefix: String, filter: ((name: String, value: Any?) -> Boolean)?): String {
|
||||||
val newPrefix = prefix + ProtoMap.indent
|
val newPrefix = prefix + ProtoMap.indent
|
||||||
return (this::class.simpleName ?: "<UnnamedClass>") + "#" + this::class.hashCode() + " {\n" +
|
return (this::class.simpleName ?: "<UnnamedClass>") + "#" + this::class.hashCode() + " {\n" +
|
||||||
this.allFieldsFromSuperClassesMatching { it.name.startsWith("net.mamoe.mirai") }
|
this.allFieldsFromSuperClassesMatching { it.name.startsWith("net.mamoe.mirai") }
|
||||||
.distinctBy { it.name }
|
.distinctBy { it.name }
|
||||||
.filterNot { it.name.contains("$") || it.name == "Companion" || it.isSynthetic || it.name == "serialVersionUID" }
|
.filterNot { it.name.contains("$") || it.name == "Companion" || it.isSynthetic || it.name == "serialVersionUID" }
|
||||||
.filterNot { it.isEnumConstant }
|
.filterNot { it.isEnumConstant }
|
||||||
|
.map {
|
||||||
|
FIELD_TRY_SET_ACCESSIBLE?.invoke(it, true) ?: kotlin.run { it.isAccessible = true }
|
||||||
|
val value = it.get(this)
|
||||||
|
if (filter != null) {
|
||||||
|
kotlin.runCatching {
|
||||||
|
if (!filter(it.name, value)) return@map it.name to FIELD_TRY_SET_ACCESSIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
it.name to value
|
||||||
|
}
|
||||||
|
.filterNot { it.second === FIELD_TRY_SET_ACCESSIBLE }
|
||||||
.joinToStringPrefixed(
|
.joinToStringPrefixed(
|
||||||
prefix = newPrefix
|
prefix = newPrefix
|
||||||
) {
|
) { (name, value) ->
|
||||||
FIELD_TRY_SET_ACCESSIBLE?.invoke(it, true) ?: kotlin.run { it.isAccessible = true }
|
"$name=" + kotlin.runCatching {
|
||||||
it.name + "=" + kotlin.runCatching {
|
|
||||||
val value = it.get(this)
|
|
||||||
if (value == this) "<this>"
|
if (value == this) "<this>"
|
||||||
else value.contentToString(newPrefix)
|
else value.contentToString(newPrefix)
|
||||||
}.getOrElse { "<!>" }
|
}.getOrElse { "<!>" }
|
||||||
|
Loading…
Reference in New Issue
Block a user