mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-11 04:04:48 +08:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
93aeda2aeb
@ -63,7 +63,7 @@ mirai 是一个在全平台下运行,提供 QQ Android 协议支持的高效
|
|||||||
### 衍生软件需声明引用
|
### 衍生软件需声明引用
|
||||||
|
|
||||||
- 若引用 mirai 发布的软件包而不修改 mirai,则衍生项目需在描述的任意部位提及使用 mirai。
|
- 若引用 mirai 发布的软件包而不修改 mirai,则衍生项目需在描述的任意部位提及使用 mirai。
|
||||||
- 若修改 mirai 源代码再发布,或参考 mirai 内部实现发布另一个项目,则衍生项目必须在**文章首部**或 'mirai' 相关内容**首次出现**的位置**明确声明**来源于本仓库 (`https://github.com/mamoe/mirai`)。不得扭曲或隐藏免费且开源的事实。
|
- 若修改 mirai 源代码再发布,**或参考 mirai 内部实现发布另一个项目**,则衍生项目必须在**文章首部**或 'mirai' 相关内容**首次出现**的位置**明确声明**来源于本仓库 (`https://github.com/mamoe/mirai`)。不得扭曲或隐藏免费且开源的事实。
|
||||||
|
|
||||||
## 协议支持
|
## 协议支持
|
||||||
|
|
||||||
|
@ -21,4 +21,6 @@ public interface MemberInfo : FriendInfo {
|
|||||||
public val specialTitle: String
|
public val specialTitle: String
|
||||||
|
|
||||||
public val muteTimestamp: Int
|
public val muteTimestamp: Int
|
||||||
|
|
||||||
|
public val anonymousId: String? get() = null
|
||||||
}
|
}
|
@ -40,7 +40,7 @@
|
|||||||
- 消息撤回: MessageRecallEvent
|
- 消息撤回: MessageRecallEvent
|
||||||
- 好友撤回: FriendRecall
|
- 好友撤回: FriendRecall
|
||||||
- 群撤回: GroupRecall
|
- 群撤回: GroupRecall
|
||||||
- 群撤回: TempRecall
|
- 群临时会话撤回: TempRecall
|
||||||
- 图片上传前: BeforeImageUploadEvent
|
- 图片上传前: BeforeImageUploadEvent
|
||||||
- 图片上传完成: ImageUploadEvent
|
- 图片上传完成: ImageUploadEvent
|
||||||
- 图片上传成功: Succeed
|
- 图片上传成功: Succeed
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
package net.mamoe.mirai
|
package net.mamoe.mirai
|
||||||
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import net.mamoe.mirai.contact.AnonymousMember
|
||||||
import net.mamoe.mirai.contact.Friend
|
import net.mamoe.mirai.contact.Friend
|
||||||
import net.mamoe.mirai.contact.Group
|
import net.mamoe.mirai.contact.Group
|
||||||
import net.mamoe.mirai.data.*
|
import net.mamoe.mirai.data.*
|
||||||
@ -201,4 +202,18 @@ public interface LowLevelApiAccessor {
|
|||||||
md5: ByteArray,
|
md5: ByteArray,
|
||||||
groupId: Long,
|
groupId: Long,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁言一个匿名用户
|
||||||
|
*
|
||||||
|
* @param anonymousId [AnonymousMember.anonymousId]
|
||||||
|
*/
|
||||||
|
@LowLevelApi
|
||||||
|
public suspend fun _lowLevelMuteAnonymous(
|
||||||
|
bot: Bot,
|
||||||
|
anonymousId: String,
|
||||||
|
anonymousNick: String,
|
||||||
|
groupId: Long,
|
||||||
|
seconds: Int,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -49,8 +49,8 @@ public class DeviceInfo(
|
|||||||
public val simInfo: ByteArray,
|
public val simInfo: ByteArray,
|
||||||
public val osType: ByteArray,
|
public val osType: ByteArray,
|
||||||
public val macAddress: ByteArray,
|
public val macAddress: ByteArray,
|
||||||
public val wifiBSSID: ByteArray?,
|
public val wifiBSSID: ByteArray,
|
||||||
public val wifiSSID: ByteArray?,
|
public val wifiSSID: ByteArray,
|
||||||
public val imsiMd5: ByteArray,
|
public val imsiMd5: ByteArray,
|
||||||
public val imei: String,
|
public val imei: String,
|
||||||
public val apn: ByteArray
|
public val apn: ByteArray
|
||||||
|
@ -59,7 +59,7 @@ internal class ConstrainSingleTest {
|
|||||||
|
|
||||||
val result = buildMessageChain {
|
val result = buildMessageChain {
|
||||||
add(" ")
|
add(" ")
|
||||||
add(Face(Face.hao))
|
add(Face(Face.OK))
|
||||||
add(TestConstrainSingleMessage())
|
add(TestConstrainSingleMessage())
|
||||||
add(
|
add(
|
||||||
PlainText("ss")
|
PlainText("ss")
|
||||||
|
@ -13,9 +13,7 @@ import io.ktor.client.request.*
|
|||||||
import io.ktor.client.request.forms.*
|
import io.ktor.client.request.forms.*
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.serialization.json.int
|
import kotlinx.serialization.json.*
|
||||||
import kotlinx.serialization.json.jsonObject
|
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
|
||||||
import net.mamoe.mirai.*
|
import net.mamoe.mirai.*
|
||||||
import net.mamoe.mirai.contact.*
|
import net.mamoe.mirai.contact.*
|
||||||
import net.mamoe.mirai.data.*
|
import net.mamoe.mirai.data.*
|
||||||
@ -748,6 +746,36 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun _lowLevelMuteAnonymous(
|
||||||
|
bot: Bot,
|
||||||
|
anonymousId: String,
|
||||||
|
anonymousNick: String,
|
||||||
|
groupId: Long,
|
||||||
|
seconds: Int
|
||||||
|
) {
|
||||||
|
bot as QQAndroidBot
|
||||||
|
val response = MiraiPlatformUtils.Http.post<String> {
|
||||||
|
url("https://qqweb.qq.com/c/anonymoustalk/blacklist")
|
||||||
|
body = MultiPartFormDataContent(formData {
|
||||||
|
append("anony_id", anonymousId)
|
||||||
|
append("group_code", groupId)
|
||||||
|
append("seconds", seconds)
|
||||||
|
append("anony_nick", anonymousNick)
|
||||||
|
append("bkn", bot.bkn)
|
||||||
|
})
|
||||||
|
headers {
|
||||||
|
append(
|
||||||
|
"cookie",
|
||||||
|
"uin=o${bot.id}; skey=${bot.client.wLoginSigInfo.sKey.data.encodeToString()};"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jsonObj = Json.decodeFromString(JsonObject.serializer(), response)
|
||||||
|
if ((jsonObj["retcode"] ?: jsonObj["cgicode"] ?: error("missing response code")).jsonPrimitive.long != 0L) {
|
||||||
|
throw IllegalStateException(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun createImage(imageId: String): Image {
|
override fun createImage(imageId: String): Image {
|
||||||
return when {
|
return when {
|
||||||
imageId matches FRIEND_IMAGE_ID_REGEX_1 -> OfflineFriendImage(imageId)
|
imageId matches FRIEND_IMAGE_ID_REGEX_1 -> OfflineFriendImage(imageId)
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||||
|
*
|
||||||
|
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||||
|
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||||
|
*
|
||||||
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
|
*/
|
||||||
|
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
|
|
||||||
|
package net.mamoe.mirai.internal.contact
|
||||||
|
|
||||||
|
import net.mamoe.mirai.Bot
|
||||||
|
import net.mamoe.mirai.contact.AnonymousMember
|
||||||
|
import net.mamoe.mirai.contact.MemberPermission
|
||||||
|
import net.mamoe.mirai.data.MemberInfo
|
||||||
|
import net.mamoe.mirai.internal.MiraiImpl
|
||||||
|
import net.mamoe.mirai.message.action.MemberNudge
|
||||||
|
import net.mamoe.mirai.message.data.Image
|
||||||
|
import net.mamoe.mirai.message.data.Message
|
||||||
|
import net.mamoe.mirai.utils.ExternalImage
|
||||||
|
import net.mamoe.mirai.utils.MemberDeprecatedApi
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
@OptIn(MemberDeprecatedApi::class)
|
||||||
|
internal class AnonymousMemberImpl(
|
||||||
|
override val group: GroupImpl,
|
||||||
|
override val coroutineContext: CoroutineContext,
|
||||||
|
private val memberInfo: MemberInfo,
|
||||||
|
override val anonymousId: String
|
||||||
|
) : AnonymousMember {
|
||||||
|
override val nameCard: String get() = memberInfo.nameCard
|
||||||
|
override val specialTitle: String get() = memberInfo.specialTitle
|
||||||
|
override val permission: MemberPermission get() = memberInfo.permission
|
||||||
|
override val bot: Bot get() = group.bot
|
||||||
|
override val id: Long get() = memberInfo.uin
|
||||||
|
override val muteTimeRemaining: Int get() = -1
|
||||||
|
override val nick: String get() = memberInfo.nick
|
||||||
|
override val remark: String get() = memberInfo.remark
|
||||||
|
|
||||||
|
override fun nudge(): MemberNudge = notSupported("Nudge")
|
||||||
|
override suspend fun uploadImage(image: ExternalImage): Image = notSupported("Upload image to")
|
||||||
|
override suspend fun unmute() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun mute(durationSeconds: Int) {
|
||||||
|
checkBotPermissionHigherThanThis("mute")
|
||||||
|
MiraiImpl._lowLevelMuteAnonymous(bot, anonymousId, nameCard, group.uin, durationSeconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = "AnonymousMember($nameCard, $anonymousId)"
|
||||||
|
|
||||||
|
private fun notSupported(action: String): Nothing =
|
||||||
|
throw IllegalStateException("$action anonymous is not allowed")
|
||||||
|
|
||||||
|
override suspend fun sendMessage(message: Message): Nothing = notSupported("Send message to")
|
||||||
|
override suspend fun sendMessage(message: String): Nothing = notSupported("Send message to")
|
||||||
|
override suspend fun kick(message: String): Unit = notSupported("Kick")
|
||||||
|
}
|
@ -231,6 +231,12 @@ internal class GroupImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun newMember(memberInfo: MemberInfo): Member {
|
override fun newMember(memberInfo: MemberInfo): Member {
|
||||||
|
memberInfo.anonymousId?.let { anId ->
|
||||||
|
return AnonymousMemberImpl(
|
||||||
|
this, this.coroutineContext,
|
||||||
|
memberInfo, anId
|
||||||
|
)
|
||||||
|
}
|
||||||
return MemberImpl(
|
return MemberImpl(
|
||||||
Mirai._lowLevelNewFriend(bot, memberInfo) as FriendImpl,
|
Mirai._lowLevelNewFriend(bot, memberInfo) as FriendImpl,
|
||||||
this,
|
this,
|
||||||
@ -239,7 +245,7 @@ internal class GroupImpl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun newAnonymous(name: String): Member = newMember(
|
internal fun newAnonymous(name: String, id: String): Member = newMember(
|
||||||
object : MemberInfo {
|
object : MemberInfo {
|
||||||
override val nameCard = name
|
override val nameCard = name
|
||||||
override val permission = MemberPermission.MEMBER
|
override val permission = MemberPermission.MEMBER
|
||||||
@ -248,6 +254,7 @@ internal class GroupImpl(
|
|||||||
override val uin = 80000000L
|
override val uin = 80000000L
|
||||||
override val nick = name
|
override val nick = name
|
||||||
override val remark: String = "匿名"
|
override val remark: String = "匿名"
|
||||||
|
override val anonymousId: String get() = id
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -202,15 +202,6 @@ internal class MemberImpl constructor(
|
|||||||
net.mamoe.mirai.event.events.MemberMuteEvent(this@MemberImpl, durationSeconds, null).broadcast()
|
net.mamoe.mirai.event.events.MemberMuteEvent(this@MemberImpl, durationSeconds, null).broadcast()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkBotPermissionHigherThanThis(operationName: String) {
|
|
||||||
check(group.botPermission > this.permission) {
|
|
||||||
throw PermissionDeniedException(
|
|
||||||
"`$operationName` operation requires a higher permission, while " +
|
|
||||||
"${group.botPermission} < ${this.permission}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
override suspend fun unmute() {
|
override suspend fun unmute() {
|
||||||
checkBotPermissionHigherThanThis("unmute")
|
checkBotPermissionHigherThanThis("unmute")
|
||||||
@ -250,6 +241,15 @@ internal class MemberImpl constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun Member.checkBotPermissionHigherThanThis(operationName: String) {
|
||||||
|
check(group.botPermission > this.permission) {
|
||||||
|
throw PermissionDeniedException(
|
||||||
|
"`$operationName` operation requires a higher permission, while " +
|
||||||
|
"${group.botPermission} < ${this.permission}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalContracts::class)
|
@OptIn(ExperimentalContracts::class)
|
||||||
internal fun Member.checkIsMemberImpl(): MemberImpl {
|
internal fun Member.checkIsMemberImpl(): MemberImpl {
|
||||||
contract {
|
contract {
|
||||||
|
@ -63,11 +63,13 @@ internal suspend fun <T : User> Friend.sendMessageImpl(
|
|||||||
chain
|
chain
|
||||||
) {
|
) {
|
||||||
source = it
|
source = it
|
||||||
}.sendAndExpect<MessageSvcPbSendMsg.Response>().let {
|
}.forEach { packet ->
|
||||||
|
packet.sendAndExpect<MessageSvcPbSendMsg.Response>().let {
|
||||||
check(it is MessageSvcPbSendMsg.Response.SUCCESS) {
|
check(it is MessageSvcPbSendMsg.Response.SUCCESS) {
|
||||||
"Send friend message failed: $it"
|
"Send friend message failed: $it"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
friendReceiptConstructor(source)
|
friendReceiptConstructor(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +97,10 @@ internal fun Contact.logMessageSent(message: Message) {
|
|||||||
internal fun net.mamoe.mirai.event.events.MessageEvent.logMessageReceived() {
|
internal fun net.mamoe.mirai.event.events.MessageEvent.logMessageReceived() {
|
||||||
when (this) {
|
when (this) {
|
||||||
is net.mamoe.mirai.event.events.GroupMessageEvent -> bot.logger.verbose {
|
is net.mamoe.mirai.event.events.GroupMessageEvent -> bot.logger.verbose {
|
||||||
"[${group.name}(${group.id})] ${senderName}(${sender.id}) -> $message".replaceMagicCodes()
|
"[${group.name}(${group.id})] ${senderName}(${
|
||||||
|
if (sender is AnonymousMember) "匿名"
|
||||||
|
else sender.id
|
||||||
|
}) -> $message".replaceMagicCodes()
|
||||||
}
|
}
|
||||||
is net.mamoe.mirai.event.events.TempMessageEvent -> bot.logger.verbose {
|
is net.mamoe.mirai.event.events.TempMessageEvent -> bot.logger.verbose {
|
||||||
"[${group.name}(${group.id})] $senderName(Temp ${sender.id}) -> $message".replaceMagicCodes()
|
"[${group.name}(${group.id})] $senderName(Temp ${sender.id}) -> $message".replaceMagicCodes()
|
||||||
|
@ -18,6 +18,7 @@ import kotlinx.io.core.readUInt
|
|||||||
import kotlinx.io.core.toByteArray
|
import kotlinx.io.core.toByteArray
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.LowLevelApi
|
import net.mamoe.mirai.LowLevelApi
|
||||||
|
import net.mamoe.mirai.contact.AnonymousMember
|
||||||
import net.mamoe.mirai.contact.ContactOrBot
|
import net.mamoe.mirai.contact.ContactOrBot
|
||||||
import net.mamoe.mirai.contact.Group
|
import net.mamoe.mirai.contact.Group
|
||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.HummerCommelem
|
import net.mamoe.mirai.internal.network.protocol.data.proto.HummerCommelem
|
||||||
@ -148,12 +149,20 @@ internal fun MessageChain.toRichTextElems(
|
|||||||
is OfflineFriendImage -> elements.add(ImMsgBody.Elem(notOnlineImage = it.toJceData()))
|
is OfflineFriendImage -> elements.add(ImMsgBody.Elem(notOnlineImage = it.toJceData()))
|
||||||
is FlashImage -> elements.add(it.toJceData()).also { transformOneMessage(UNSUPPORTED_FLASH_MESSAGE_PLAIN) }
|
is FlashImage -> elements.add(it.toJceData()).also { transformOneMessage(UNSUPPORTED_FLASH_MESSAGE_PLAIN) }
|
||||||
is AtAll -> elements.add(atAllData)
|
is AtAll -> elements.add(atAllData)
|
||||||
is Face -> elements.add(ImMsgBody.Elem(face = it.toJceData()))
|
is Face -> elements.add(
|
||||||
|
if (it.id >= 260) {
|
||||||
|
ImMsgBody.Elem(commonElem = it.toCommData())
|
||||||
|
} else {
|
||||||
|
ImMsgBody.Elem(face = it.toJceData())
|
||||||
|
}
|
||||||
|
)
|
||||||
is QuoteReply -> {
|
is QuoteReply -> {
|
||||||
if (forGroup) {
|
if (forGroup) {
|
||||||
when (val source = it.source) {
|
when (val source = it.source) {
|
||||||
is OnlineMessageSource.Incoming.FromGroup -> {
|
is OnlineMessageSource.Incoming.FromGroup -> {
|
||||||
transformOneMessage(At(source.sender))
|
val sender0 = source.sender
|
||||||
|
if (sender0 !is AnonymousMember)
|
||||||
|
transformOneMessage(At(sender0))
|
||||||
// transformOneMessage(PlainText(" "))
|
// transformOneMessage(PlainText(" "))
|
||||||
// removed by https://github.com/mamoe/mirai/issues/524
|
// removed by https://github.com/mamoe/mirai/issues/524
|
||||||
// 发送 QuoteReply 消息时无可避免的产生多余空格 #524
|
// 发送 QuoteReply 消息时无可避免的产生多余空格 #524
|
||||||
@ -249,7 +258,7 @@ internal fun List<MsgOnlinePush.PbPushMsg>.toMessageChain(
|
|||||||
groupIdOrZero: Long,
|
groupIdOrZero: Long,
|
||||||
onlineSource: Boolean,
|
onlineSource: Boolean,
|
||||||
isTemp: Boolean = false
|
isTemp: Boolean = false
|
||||||
): MessageChain = map{it.msg}.toMessageChain(bot, botId, groupIdOrZero, onlineSource, isTemp)
|
): MessageChain = map { it.msg }.toMessageChain(bot, botId, groupIdOrZero, onlineSource, isTemp)
|
||||||
|
|
||||||
internal fun MsgComm.Msg.toMessageChain(
|
internal fun MsgComm.Msg.toMessageChain(
|
||||||
bot: Bot?,
|
bot: Bot?,
|
||||||
@ -292,6 +301,7 @@ internal fun List<MsgComm.Msg>.toMessageChain(
|
|||||||
+OfflineMessageSourceImplByMsg(this@toMessageChain, botId)
|
+OfflineMessageSourceImplByMsg(this@toMessageChain, botId)
|
||||||
}
|
}
|
||||||
elements.joinToMessageChain(groupIdOrZero, botId, this)
|
elements.joinToMessageChain(groupIdOrZero, botId, this)
|
||||||
|
addAll(ppts)
|
||||||
}.cleanupRubbishMessageElements()
|
}.cleanupRubbishMessageElements()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,6 +522,11 @@ internal fun List<ImMsgBody.Elem>.joinToMessageChain(groupIdOrZero: Long, botId:
|
|||||||
list.add(FlashImage(OnlineFriendImageImpl(proto.flashC2cPic)))
|
list.add(FlashImage(OnlineFriendImageImpl(proto.flashC2cPic)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33 -> {
|
||||||
|
val proto = element.commonElem.pbElem.loadAs(HummerCommelem.MsgElemInfoServtype33.serializer())
|
||||||
|
list.add(Face(proto.index))
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
@ -9,8 +9,11 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.internal.message
|
package net.mamoe.mirai.internal.message
|
||||||
|
|
||||||
|
import kotlinx.io.core.toByteArray
|
||||||
|
import net.mamoe.mirai.internal.network.protocol.data.proto.HummerCommelem
|
||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
|
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
|
||||||
import net.mamoe.mirai.internal.utils.hexToBytes
|
import net.mamoe.mirai.internal.utils.hexToBytes
|
||||||
|
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
|
||||||
import net.mamoe.mirai.internal.utils.toByteArray
|
import net.mamoe.mirai.internal.utils.toByteArray
|
||||||
import net.mamoe.mirai.message.data.Face
|
import net.mamoe.mirai.message.data.Face
|
||||||
|
|
||||||
@ -23,3 +26,16 @@ internal fun Face.toJceData(): ImMsgBody.Face {
|
|||||||
buf = FACE_BUF
|
buf = FACE_BUF
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun Face.toCommData(): ImMsgBody.CommonElem {
|
||||||
|
return ImMsgBody.CommonElem(
|
||||||
|
serviceType = 33,
|
||||||
|
pbElem = HummerCommelem.MsgElemInfoServtype33(
|
||||||
|
index = this.id,
|
||||||
|
name = "/${this.name}".toByteArray(),
|
||||||
|
compat = "/${this.name}".toByteArray()
|
||||||
|
).toByteArray(HummerCommelem.MsgElemInfoServtype33.serializer()),
|
||||||
|
businessType = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -20,6 +20,7 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
|||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg
|
import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg
|
||||||
import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY
|
import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY
|
||||||
import net.mamoe.mirai.internal.utils._miraiContentToString
|
import net.mamoe.mirai.internal.utils._miraiContentToString
|
||||||
|
import net.mamoe.mirai.internal.utils.encodeToBase64
|
||||||
import net.mamoe.mirai.internal.utils.encodeToString
|
import net.mamoe.mirai.internal.utils.encodeToString
|
||||||
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
|
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
|
||||||
import net.mamoe.mirai.message.data.Message
|
import net.mamoe.mirai.message.data.Message
|
||||||
@ -163,7 +164,7 @@ internal data class MessageSourceFromGroupImpl(
|
|||||||
) as GroupImpl).run {
|
) as GroupImpl).run {
|
||||||
get(msg.first().msgHead.fromUin)
|
get(msg.first().msgHead.fromUin)
|
||||||
?: msg.first().msgBody.richText.elems.firstOrNull { it.anonGroupMsg != null }?.run {
|
?: msg.first().msgBody.richText.elems.firstOrNull { it.anonGroupMsg != null }?.run {
|
||||||
newAnonymous(anonGroupMsg!!.anonNick.encodeToString())
|
newAnonymous(anonGroupMsg!!.anonNick.encodeToString(), anonGroupMsg.anonId.encodeToBase64())
|
||||||
}
|
}
|
||||||
?: error("cannot find member for MessageSourceFromGroupImpl. msg=${msg._miraiContentToString()}")
|
?: error("cannot find member for MessageSourceFromGroupImpl. msg=${msg._miraiContentToString()}")
|
||||||
}
|
}
|
||||||
|
@ -116,13 +116,13 @@ internal open class QQAndroidClient(
|
|||||||
|
|
||||||
val bot: QQAndroidBot by bot.unsafeWeakRef()
|
val bot: QQAndroidBot by bot.unsafeWeakRef()
|
||||||
|
|
||||||
var tgtgtKey: ByteArray = generateTgtgtKey(device.guid)
|
internal var tgtgtKey: ByteArray = generateTgtgtKey(device.guid)
|
||||||
val randomKey: ByteArray = getRandomByteArray(16)
|
internal val randomKey: ByteArray = getRandomByteArray(16)
|
||||||
|
|
||||||
|
|
||||||
val miscBitMap: Int get() = protocol.miscBitMap // 184024956 // 也可能是 150470524 ?
|
internal val miscBitMap: Int = protocol.miscBitMap // 184024956 // 也可能是 150470524 ?
|
||||||
private val mainSigMap: Int = protocol.mainSigMap
|
internal val mainSigMap: Int = protocol.mainSigMap
|
||||||
var subSigMap: Int = protocol.subSigMap // 0x10400 //=66,560
|
internal var subSigMap: Int = protocol.subSigMap // 0x10400 //=66,560
|
||||||
|
|
||||||
private val _ssoSequenceId: AtomicInt = atomic(85600)
|
private val _ssoSequenceId: AtomicInt = atomic(85600)
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ import kotlinx.serialization.Serializable
|
|||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY
|
import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY
|
||||||
import net.mamoe.mirai.internal.utils.io.ProtoBuf
|
import net.mamoe.mirai.internal.utils.io.ProtoBuf
|
||||||
import kotlin.jvm.JvmField
|
|
||||||
|
|
||||||
internal class HummerCommelem : ProtoBuf {
|
internal class HummerCommelem : ProtoBuf {
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -234,6 +233,14 @@ internal class HummerCommelem : ProtoBuf {
|
|||||||
@ProtoNumber(2) @JvmField val ext: ByteArray = EMPTY_BYTE_ARRAY
|
@ProtoNumber(2) @JvmField val ext: ByteArray = EMPTY_BYTE_ARRAY
|
||||||
) : ProtoBuf
|
) : ProtoBuf
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
internal class MsgElemInfoServtype33(
|
||||||
|
@ProtoNumber(1) @JvmField val index: Int = 0,
|
||||||
|
@ProtoNumber(2) @JvmField val name: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(3) @JvmField val compat: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
|
@ProtoNumber(4) @JvmField val buf: ByteArray = EMPTY_BYTE_ARRAY
|
||||||
|
) : ProtoBuf
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
internal class MsgElemInfoServtype4(
|
internal class MsgElemInfoServtype4(
|
||||||
@ProtoNumber(1) @JvmField val imsgType: Int = 0,
|
@ProtoNumber(1) @JvmField val imsgType: Int = 0,
|
||||||
|
@ -163,6 +163,7 @@ internal fun BytePacketBuilder.t100(
|
|||||||
subAppId: Long,
|
subAppId: Long,
|
||||||
appClientVersion: Int,
|
appClientVersion: Int,
|
||||||
ssoVersion: Int,
|
ssoVersion: Int,
|
||||||
|
mainSigMap: Int
|
||||||
) {
|
) {
|
||||||
writeShort(0x100)
|
writeShort(0x100)
|
||||||
writeShortLVPacket {
|
writeShortLVPacket {
|
||||||
@ -171,7 +172,7 @@ internal fun BytePacketBuilder.t100(
|
|||||||
writeInt(appId.toInt())
|
writeInt(appId.toInt())
|
||||||
writeInt(subAppId.toInt())
|
writeInt(subAppId.toInt())
|
||||||
writeInt(appClientVersion)
|
writeInt(appClientVersion)
|
||||||
writeInt(34869472) // sigMap, 34869472?
|
writeInt(mainSigMap) // sigMap, 34869472?
|
||||||
} shouldEqualsTo 22
|
} shouldEqualsTo 22
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,10 +33,9 @@ import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory
|
|||||||
import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
|
import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
|
||||||
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
|
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
|
||||||
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
|
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
|
||||||
import net.mamoe.mirai.message.data.MessageChain
|
import net.mamoe.mirai.message.data.*
|
||||||
import net.mamoe.mirai.message.data.PttMessage
|
|
||||||
import net.mamoe.mirai.message.data.Voice
|
|
||||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||||
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
@ -57,18 +56,155 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun MessageChain.fragmented(): List<MessageChain> {
|
||||||
|
val results = mutableListOf<MessageChain>()
|
||||||
|
var txtAdd = false
|
||||||
|
val last = mutableListOf<Message>()
|
||||||
|
fun flush() {
|
||||||
|
txtAdd = false
|
||||||
|
if (last.isNotEmpty()) {
|
||||||
|
results.add(ArrayList(last).asMessageChain())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
forEach { element ->
|
||||||
|
if (last.size >= 4) {
|
||||||
|
flush()
|
||||||
|
}
|
||||||
|
if (element is PlainText) {
|
||||||
|
if (txtAdd) {
|
||||||
|
flush()
|
||||||
|
}
|
||||||
|
if (element.content.length < 80) {
|
||||||
|
txtAdd = true
|
||||||
|
last.add(element)
|
||||||
|
} else {
|
||||||
|
val splitted = element.content.chunked(80)
|
||||||
|
flush()
|
||||||
|
splitted.forEach { results.add(PlainText(it).asMessageChain()) }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
last.add(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flush()
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline fun buildOutgoingMessageCommon(
|
||||||
|
client: QQAndroidClient,
|
||||||
|
message: MessageChain,
|
||||||
|
fragmentTranslator: (MessageChain) -> ImMsgBody.MsgBody,
|
||||||
|
pbSendMsgReq: (
|
||||||
|
msgBody: ImMsgBody.MsgBody,
|
||||||
|
msgSeq: Int,
|
||||||
|
msgRand: Int,
|
||||||
|
contentHead: MsgComm.ContentHead
|
||||||
|
) -> MsgSvc.PbSendMsgReq,
|
||||||
|
sequenceIds: AtomicReference<IntArray>,
|
||||||
|
sequenceIdsInitializer: (Int) -> IntArray,
|
||||||
|
randIds: AtomicReference<IntArray>,
|
||||||
|
postInit: () -> Unit
|
||||||
|
): List<OutgoingPacket> {
|
||||||
|
val fragmented = message.fragmented()
|
||||||
|
val response = mutableListOf<OutgoingPacket>()
|
||||||
|
val div = if (fragmented.size == 1) 0 else Random.nextInt().absoluteValue
|
||||||
|
val pkgNum = fragmented.size
|
||||||
|
|
||||||
|
val seqIds = sequenceIdsInitializer(pkgNum)
|
||||||
|
val randIds0 = IntArray(pkgNum) { Random.nextInt().absoluteValue }
|
||||||
|
sequenceIds.set(seqIds)
|
||||||
|
randIds.set(randIds0)
|
||||||
|
postInit()
|
||||||
|
fragmented.forEachIndexed { pkgIndex, fMsg ->
|
||||||
|
response.add(buildOutgoingUniPacket(client) {
|
||||||
|
writeProtoBuf(
|
||||||
|
MsgSvc.PbSendMsgReq.serializer(),
|
||||||
|
pbSendMsgReq(
|
||||||
|
fragmentTranslator(fMsg),
|
||||||
|
seqIds[pkgIndex],
|
||||||
|
randIds0[pkgIndex],
|
||||||
|
MsgComm.ContentHead(
|
||||||
|
pkgNum = pkgNum,
|
||||||
|
divSeq = div,
|
||||||
|
pkgIndex = pkgIndex
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送好友消息
|
* 发送好友消息
|
||||||
*/
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
internal fun createToFriendImpl(
|
internal inline fun createToFriendImpl(
|
||||||
client: QQAndroidClient,
|
client: QQAndroidClient,
|
||||||
targetFriend: Friend,
|
targetFriend: Friend,
|
||||||
message: MessageChain,
|
message: MessageChain,
|
||||||
source: MessageSourceToFriendImpl
|
crossinline sourceCallback: (MessageSourceToFriendImpl) -> Unit
|
||||||
): OutgoingPacket = buildOutgoingUniPacket(client) {
|
): List<OutgoingPacket> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
val sequenceIds = AtomicReference<IntArray>()
|
||||||
|
val randIds = AtomicReference<IntArray>()
|
||||||
|
return buildOutgoingMessageCommon(
|
||||||
|
client = client,
|
||||||
|
message = message,
|
||||||
|
fragmentTranslator = {
|
||||||
|
ImMsgBody.MsgBody(
|
||||||
|
richText = ImMsgBody.RichText(
|
||||||
|
elems = it.toRichTextElems(messageTarget = targetFriend, withGeneralFlags = true)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
pbSendMsgReq = { msgBody, msgSeq, msgRand, contentHead ->
|
||||||
|
MsgSvc.PbSendMsgReq(
|
||||||
|
routingHead = MsgSvc.RoutingHead(c2c = MsgSvc.C2C(toUin = targetFriend.uin)),
|
||||||
|
contentHead = contentHead,
|
||||||
|
msgBody = msgBody,
|
||||||
|
msgSeq = msgSeq,
|
||||||
|
msgRand = msgRand,
|
||||||
|
syncCookie = client.syncingController.syncCookie ?: byteArrayOf()
|
||||||
|
// msgVia = 1
|
||||||
|
)
|
||||||
|
},
|
||||||
|
sequenceIds = sequenceIds,
|
||||||
|
randIds = randIds,
|
||||||
|
sequenceIdsInitializer = { size ->
|
||||||
|
IntArray(size) { client.nextFriendSeq() }
|
||||||
|
},
|
||||||
|
postInit = {
|
||||||
|
sourceCallback(
|
||||||
|
MessageSourceToFriendImpl(
|
||||||
|
internalIds = randIds.get(),
|
||||||
|
sender = client.bot,
|
||||||
|
target = targetFriend,
|
||||||
|
time = currentTimeSeconds().toInt(),
|
||||||
|
sequenceIds = sequenceIds.get(),
|
||||||
|
originalMessage = message
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/*= buildOutgoingUniPacket(client) {
|
||||||
///writeFully("0A 08 0A 06 08 89 FC A6 8C 0B 12 06 08 01 10 00 18 00 1A 1F 0A 1D 12 08 0A 06 0A 04 F0 9F 92 A9 12 11 AA 02 0E 88 01 00 9A 01 08 78 00 F8 01 00 C8 02 00 20 9B 7A 28 F4 CA 9B B8 03 32 34 08 92 C2 C4 F1 05 10 92 C2 C4 F1 05 18 E6 ED B9 C3 02 20 89 FE BE A4 06 28 89 84 F9 A2 06 48 DE 8C EA E5 0E 58 D9 BD BB A0 09 60 1D 68 92 C2 C4 F1 05 70 00 40 01".hexToBytes())
|
///writeFully("0A 08 0A 06 08 89 FC A6 8C 0B 12 06 08 01 10 00 18 00 1A 1F 0A 1D 12 08 0A 06 0A 04 F0 9F 92 A9 12 11 AA 02 0E 88 01 00 9A 01 08 78 00 F8 01 00 C8 02 00 20 9B 7A 28 F4 CA 9B B8 03 32 34 08 92 C2 C4 F1 05 10 92 C2 C4 F1 05 18 E6 ED B9 C3 02 20 89 FE BE A4 06 28 89 84 F9 A2 06 48 DE 8C EA E5 0E 58 D9 BD BB A0 09 60 1D 68 92 C2 C4 F1 05 70 00 40 01".hexToBytes())
|
||||||
|
|
||||||
|
val rand = Random.nextInt().absoluteValue
|
||||||
|
val source = MessageSourceToFriendImpl(
|
||||||
|
internalIds = intArrayOf(rand),
|
||||||
|
sender = client.bot,
|
||||||
|
target = qq,
|
||||||
|
time = currentTimeSeconds().toInt(),
|
||||||
|
sequenceIds = intArrayOf(client.nextFriendSeq()),
|
||||||
|
originalMessage = message
|
||||||
|
)
|
||||||
|
sourceCallback(source)
|
||||||
|
|
||||||
///return@buildOutgoingUniPacket
|
///return@buildOutgoingUniPacket
|
||||||
writeProtoBuf(
|
writeProtoBuf(
|
||||||
MsgSvc.PbSendMsgReq.serializer(), MsgSvc.PbSendMsgReq(
|
MsgSvc.PbSendMsgReq.serializer(), MsgSvc.PbSendMsgReq(
|
||||||
@ -86,6 +222,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,28 +351,19 @@ internal inline fun MessageSvcPbSendMsg.createToFriend(
|
|||||||
qq: Friend,
|
qq: Friend,
|
||||||
message: MessageChain,
|
message: MessageChain,
|
||||||
crossinline sourceCallback: (MessageSourceToFriendImpl) -> Unit
|
crossinline sourceCallback: (MessageSourceToFriendImpl) -> Unit
|
||||||
): OutgoingPacket {
|
): List<OutgoingPacket> {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
|
||||||
}
|
}
|
||||||
val rand = Random.nextInt().absoluteValue
|
|
||||||
val source = MessageSourceToFriendImpl(
|
|
||||||
internalIds = intArrayOf(rand),
|
|
||||||
sender = client.bot,
|
|
||||||
target = qq,
|
|
||||||
time = currentTimeSeconds().toInt(),
|
|
||||||
sequenceIds = intArrayOf(client.nextFriendSeq()),
|
|
||||||
originalMessage = message
|
|
||||||
)
|
|
||||||
sourceCallback(source)
|
|
||||||
return createToFriendImpl(
|
return createToFriendImpl(
|
||||||
client,
|
client,
|
||||||
qq,
|
qq,
|
||||||
message,
|
message,
|
||||||
source
|
sourceCallback
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal inline fun MessageSvcPbSendMsg.createToGroup(
|
internal inline fun MessageSvcPbSendMsg.createToGroup(
|
||||||
client: QQAndroidClient,
|
client: QQAndroidClient,
|
||||||
group: Group,
|
group: Group,
|
||||||
|
@ -29,6 +29,7 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush
|
|||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0x8fc
|
import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0x8fc
|
||||||
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
|
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
|
||||||
import net.mamoe.mirai.internal.utils._miraiContentToString
|
import net.mamoe.mirai.internal.utils._miraiContentToString
|
||||||
|
import net.mamoe.mirai.internal.utils.encodeToBase64
|
||||||
import net.mamoe.mirai.internal.utils.encodeToString
|
import net.mamoe.mirai.internal.utils.encodeToString
|
||||||
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
|
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
|
||||||
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
|
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
|
||||||
@ -78,10 +79,10 @@ internal object OnlinePushPbPushGroupMsg : IncomingPacketFactory<Packet?>("Onlin
|
|||||||
}
|
}
|
||||||
|
|
||||||
val sender = if (anonymous != null) {
|
val sender = if (anonymous != null) {
|
||||||
group.newAnonymous(anonymous.anonNick.encodeToString())
|
group.newAnonymous(anonymous.anonNick.encodeToString(), anonymous.anonId.encodeToBase64())
|
||||||
} else {
|
} else {
|
||||||
group[pbPushMsg.msg.msgHead.fromUin]
|
group[pbPushMsg.msg.msgHead.fromUin] as MemberImpl
|
||||||
} as MemberImpl
|
}
|
||||||
|
|
||||||
val name = if (anonymous != null) {
|
val name = if (anonymous != null) {
|
||||||
sender.nameCard
|
sender.nameCard
|
||||||
@ -103,7 +104,7 @@ internal object OnlinePushPbPushGroupMsg : IncomingPacketFactory<Packet?>("Onlin
|
|||||||
val flags = extraInfo?.flags ?: 0
|
val flags = extraInfo?.flags ?: 0
|
||||||
return GroupMessageEvent(
|
return GroupMessageEvent(
|
||||||
senderName = name.also {
|
senderName = name.also {
|
||||||
if (it != sender.nameCard) {
|
if (sender is MemberImpl && it != sender.nameCard) {
|
||||||
val origin = sender._nameCard
|
val origin = sender._nameCard
|
||||||
sender._nameCard = name
|
sender._nameCard = name
|
||||||
MemberCardChangeEvent(origin, name, sender).broadcast()
|
MemberCardChangeEvent(origin, name, sender).broadcast()
|
||||||
|
@ -412,20 +412,25 @@ internal inline fun lambda528(crossinline block: MsgType0x210.(QQAndroidBot, Msg
|
|||||||
internal object Transformers528 : Map<Long, Lambda528> by mapOf(
|
internal object Transformers528 : Map<Long, Lambda528> by mapOf(
|
||||||
|
|
||||||
0x8AL to lambda528 { bot ->
|
0x8AL to lambda528 { bot ->
|
||||||
|
@Serializable
|
||||||
|
class Wording(
|
||||||
|
@ProtoNumber(1) val itemID: Int = 0,
|
||||||
|
@ProtoNumber(2) val itemName: String = ""
|
||||||
|
) : ProtoBuf
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class Sub8AMsgInfo(
|
class Sub8AMsgInfo(
|
||||||
@ProtoNumber(1) val fromUin: Long,
|
@ProtoNumber(1) val fromUin: Long,
|
||||||
@ProtoNumber(2) val botUin: Long,
|
@ProtoNumber(2) val botUin: Long,
|
||||||
@ProtoNumber(3) val srcId: Int,
|
@ProtoNumber(3) val srcId: Int,
|
||||||
@ProtoNumber(4) val srcInternalId: Int,
|
@ProtoNumber(4) val srcInternalId: Long,
|
||||||
@ProtoNumber(5) val time: Int,
|
@ProtoNumber(5) val time: Long,
|
||||||
@ProtoNumber(6) val random: Int, // 同srcInternalId
|
@ProtoNumber(6) val random: Int,
|
||||||
@ProtoNumber(7) val pkgNum: Int, // 1
|
@ProtoNumber(7) val pkgNum: Int, // 1
|
||||||
@ProtoNumber(8) val pkgIndex: Int, // 0
|
@ProtoNumber(8) val pkgIndex: Int, // 0
|
||||||
@ProtoNumber(9) val devSeq: Int, // 0
|
@ProtoNumber(9) val devSeq: Int, // 0
|
||||||
@ProtoNumber(10) val unknown1: Int = 0, // ? 补 id
|
@ProtoNumber(12) val flag: Int, // 1
|
||||||
@ProtoNumber(11) val unknown2: Int = 0, // ?
|
@ProtoNumber(13) val wording: Wording
|
||||||
@ProtoNumber(12) val flag: Int // 1
|
|
||||||
) : ProtoBuf
|
) : ProtoBuf
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -442,8 +447,8 @@ internal object Transformers528 : Map<Long, Lambda528> by mapOf(
|
|||||||
MessageRecallEvent.FriendRecall(
|
MessageRecallEvent.FriendRecall(
|
||||||
bot = bot,
|
bot = bot,
|
||||||
messageIds = intArrayOf(it.srcId),
|
messageIds = intArrayOf(it.srcId),
|
||||||
messageInternalIds = intArrayOf(it.srcInternalId),
|
messageInternalIds = intArrayOf(it.srcInternalId.toInt()),
|
||||||
messageTime = it.time,
|
messageTime = it.time.toInt(),
|
||||||
operatorId = it.fromUin
|
operatorId = it.fromUin
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ internal class WtLogin {
|
|||||||
if (ConfigManager.get_loginWithPicSt()) appIdList = longArrayOf(1600000226L)
|
if (ConfigManager.get_loginWithPicSt()) appIdList = longArrayOf(1600000226L)
|
||||||
*/
|
*/
|
||||||
t116(client.miscBitMap, client.subSigMap)
|
t116(client.miscBitMap, client.subSigMap)
|
||||||
t100(appId, client.subAppId, client.appClientVersion, client.ssoVersion)
|
t100(appId, client.subAppId, client.appClientVersion, client.ssoVersion, client.mainSigMap)
|
||||||
t107(0)
|
t107(0)
|
||||||
t108(client.device.imei.toByteArray())
|
t108(client.device.imei.toByteArray())
|
||||||
|
|
||||||
@ -230,21 +230,13 @@ internal class WtLogin {
|
|||||||
|
|
||||||
t187(client.device.macAddress)
|
t187(client.device.macAddress)
|
||||||
t188(client.device.androidId)
|
t188(client.device.androidId)
|
||||||
|
t194(client.device.imsiMd5)
|
||||||
val imsi = client.device.imsiMd5
|
|
||||||
if (imsi.isNotEmpty()) {
|
|
||||||
t194(imsi)
|
|
||||||
}
|
|
||||||
t191()
|
t191()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
t201(N = byteArrayOf())*/
|
t201(N = byteArrayOf())*/
|
||||||
|
|
||||||
val bssid = client.device.wifiBSSID
|
t202(client.device.wifiBSSID, client.device.wifiSSID)
|
||||||
val ssid = client.device.wifiSSID
|
|
||||||
if (bssid != null && ssid != null) {
|
|
||||||
t202(bssid, ssid)
|
|
||||||
}
|
|
||||||
|
|
||||||
t177(
|
t177(
|
||||||
buildTime = client.buildTime,
|
buildTime = client.buildTime,
|
||||||
@ -323,7 +315,7 @@ internal class WtLogin {
|
|||||||
return when (type.toInt()) {
|
return when (type.toInt()) {
|
||||||
0 -> onLoginSuccess(tlvMap, bot)
|
0 -> onLoginSuccess(tlvMap, bot)
|
||||||
2 -> onSolveLoginCaptcha(tlvMap, bot)
|
2 -> onSolveLoginCaptcha(tlvMap, bot)
|
||||||
160 /*-96*/ -> onUnsafeDeviceLogin(tlvMap)
|
160, 239 /*-96*/ -> onUnsafeDeviceLogin(tlvMap)
|
||||||
204 /*-52*/ -> onSMSVerifyNeeded(tlvMap, bot)
|
204 /*-52*/ -> onSMSVerifyNeeded(tlvMap, bot)
|
||||||
// 1, 15 -> onErrorMessage(tlvMap) ?: error("Cannot find error message")
|
// 1, 15 -> onErrorMessage(tlvMap) ?: error("Cannot find error message")
|
||||||
else -> {
|
else -> {
|
||||||
|
@ -18,6 +18,7 @@ import kotlinx.io.charsets.Charsets
|
|||||||
import kotlinx.io.core.ByteReadPacket
|
import kotlinx.io.core.ByteReadPacket
|
||||||
import kotlinx.io.core.String
|
import kotlinx.io.core.String
|
||||||
import kotlinx.io.core.use
|
import kotlinx.io.core.use
|
||||||
|
import java.util.*
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
import kotlin.jvm.JvmMultifileClass
|
import kotlin.jvm.JvmMultifileClass
|
||||||
@ -94,6 +95,10 @@ internal fun UByteArray.toUHexString(separator: String = " ", offset: Int = 0, l
|
|||||||
internal inline fun ByteArray.encodeToString(offset: Int = 0, charset: Charset = Charsets.UTF_8): String =
|
internal inline fun ByteArray.encodeToString(offset: Int = 0, charset: Charset = Charsets.UTF_8): String =
|
||||||
String(this, charset = charset, offset = offset, length = this.size - offset)
|
String(this, charset = charset, offset = offset, length = this.size - offset)
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
internal inline fun ByteArray.encodeToBase64(): String =
|
||||||
|
Base64.getEncoder().encodeToString(this)
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal inline fun ByteArray.toReadPacket(offset: Int = 0, length: Int = this.size - offset) =
|
internal inline fun ByteArray.toReadPacket(offset: Int = 0, length: Int = this.size - offset) =
|
||||||
ByteReadPacket(this, offset = offset, length = length)
|
ByteReadPacket(this, offset = offset, length = length)
|
||||||
|
Loading…
Reference in New Issue
Block a user