From b488bee0f400345da2d6ccc22c8094af6830bfce Mon Sep 17 00:00:00 2001 From: Him188moe Date: Sat, 14 Sep 2019 00:23:25 +0800 Subject: [PATCH] updated --- .../java/net/mamoe/mirai/MiraiServer.java | 16 +- .../mirai/event/events/bot/BotEvent.java | 2 +- .../event/events/group/GroupMessageEvent.java | 20 +-- .../mirai/event/events/qq/FriendEvent.java | 10 +- .../event/events/qq/FriendMessageEvent.java | 8 +- .../java/net/mamoe/mirai/message/FaceID.java | 2 +- .../java/net/mamoe/mirai/message/Message.kt | 2 +- .../java/net/mamoe/mirai/message/MessageId.kt | 6 +- .../net/mamoe/mirai/message/defaults/Face.kt | 15 ++ .../net/mamoe/mirai/message/defaults/Image.kt | 56 +++++- .../mamoe/mirai/message/defaults/PlainText.kt | 9 + .../mirai/message/defaults/UnsolvedImage.kt | 18 +- .../java/net/mamoe/mirai/network/Protocol.kt | 2 +- .../network/handler/ActionPacketHandler.kt | 12 +- .../network/handler/MessagePacketHandler.kt | 54 ++++-- .../mamoe/mirai/network/packet/ServerEvent.kt | 160 ++++++++++++------ .../mirai/network/packet/ServerPacket.kt | 57 +++++-- .../network/packet/UnknownServerPacket.kt | 6 + .../action/ClientSendFriendMessagePacket.kt | 2 +- .../action/ClientSendGroupMessagePacket.kt | 24 +-- .../network/packet/image/UploadGroupImage.kt | 26 ++- .../mamoe/mirai/utils/ImageNetworkUtils.java | 12 +- .../main/java/net/mamoe/mirai/utils/Utils.kt | 22 +++ mirai-core/src/test/java/HexComparator.java | 3 + 24 files changed, 366 insertions(+), 178 deletions(-) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java b/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java index b722713c2..be790361f 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java @@ -213,21 +213,7 @@ public final class MiraiServer { String qqList = - "2573990098----qq123456789\n" + - "3303923865----q123456789\n" + - "3349933294----q123456789\n" + - "3303708824----q123456789\n" + - "3227036647----q123456789\n" + - "3451394431----q123456789\n" + - "3533243484----q123456789\n" + - "3364512686----q123456789\n" + - "3137567463----q123456789\n" + - "3414786399----q123456789\n" + - "3347405939----q123456789\n" + - "3544089622----q123456789\n" + - "3108512993----q123456789\n" + - "2985563549----q123456789\n" + - "3463531892----q123456789\n"; + "3034551466----zxcvbnm\n"; private Bot getAvailableBot() throws ExecutionException, InterruptedException { for (String it : qqList.split("\n")) { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/bot/BotEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/bot/BotEvent.java index e4ce2830a..9f097a979 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/bot/BotEvent.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/bot/BotEvent.java @@ -10,7 +10,7 @@ import java.util.Objects; * @author Him188moe */ public abstract class BotEvent extends MiraiEvent { - private final Bot bot; + public final Bot bot; public BotEvent(@NotNull Bot bot) { this.bot = Objects.requireNonNull(bot); diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/group/GroupMessageEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/group/GroupMessageEvent.java index 77e71e0d9..e1ae59106 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/group/GroupMessageEvent.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/group/GroupMessageEvent.java @@ -10,25 +10,25 @@ import org.jetbrains.annotations.NotNull; * @author Him188moe */ public final class GroupMessageEvent extends GroupEvent { - private final QQ sender; - private final MessageChain messageChain; - private final String messageString; + public final QQ sender; + public final MessageChain chain; + public final String message; - public GroupMessageEvent(@NotNull Bot bot, @NotNull Group group, @NotNull QQ sender, @NotNull MessageChain messageChain) { + public GroupMessageEvent(@NotNull Bot bot, @NotNull Group group, @NotNull QQ sender, @NotNull MessageChain chain) { super(bot, group); this.sender = sender; - this.messageChain = messageChain; - this.messageString = messageChain.toString(); + this.chain = chain; + this.message = chain.toString(); } @NotNull - public MessageChain getMessageChain() { - return messageChain; + public MessageChain getChain() { + return chain; } @NotNull - public String getMessageString() { - return messageString; + public String getMessage() { + return message; } @NotNull diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendEvent.java index 7e34ba5f4..4cec1d5ee 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendEvent.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendEvent.java @@ -11,15 +11,15 @@ import java.util.Objects; * @author Him188moe */ public abstract class FriendEvent extends BotEvent { - private final QQ qq; + public final QQ sender; - public FriendEvent(@NotNull Bot bot, @NotNull QQ qq) { + public FriendEvent(@NotNull Bot bot, @NotNull QQ sender) { super(bot); - this.qq = Objects.requireNonNull(qq); + this.sender = Objects.requireNonNull(sender); } @NotNull - public QQ getQQ() { - return qq; + public QQ getSender() { + return sender; } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendMessageEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendMessageEvent.java index 3952db4a3..80548798e 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendMessageEvent.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendMessageEvent.java @@ -11,15 +11,15 @@ import java.util.Objects; * @author Him188moe */ public final class FriendMessageEvent extends FriendEvent { - private final MessageChain messageChain; + public final MessageChain message; - public FriendMessageEvent(@NotNull Bot bot, @NotNull QQ sender, @NotNull MessageChain messageChain) { + public FriendMessageEvent(@NotNull Bot bot, @NotNull QQ sender, @NotNull MessageChain message) { super(bot, sender); - this.messageChain = Objects.requireNonNull(messageChain); + this.message = Objects.requireNonNull(message); } @NotNull public MessageChain message() { - return messageChain; + return message; } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/FaceID.java b/mirai-core/src/main/java/net/mamoe/mirai/message/FaceID.java index 2a8c11952..7245b721f 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/message/FaceID.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/message/FaceID.java @@ -166,7 +166,7 @@ public enum FaceID { return value; } } - return null; + return FaceID.unknown; } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/Message.kt b/mirai-core/src/main/java/net/mamoe/mirai/message/Message.kt index a44184591..a6f31088c 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/message/Message.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/message/Message.kt @@ -74,7 +74,7 @@ abstract class Message { /** * 比较两个 Message 的内容是否相等. 如: * - [PlainText] 比较 [PlainText.text] - * - [Image] 比较 [Image.imageID] + * - [Image] 比较 [Image.imageId] */ abstract infix fun valueEquals(another: Message): Boolean diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/MessageId.kt b/mirai-core/src/main/java/net/mamoe/mirai/message/MessageId.kt index 4e4f3dcad..024736652 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/message/MessageId.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/message/MessageId.kt @@ -10,13 +10,13 @@ package net.mamoe.mirai.message */ object MessageId { - const val AT: Int = 0x00//todo 不知道是多少 + const val AT: Int = 0x06 - const val FACE: Int = 0x00//todo 不知道是多少 + const val FACE: Int = 0x02 const val TEXT: Int = 0x01 - const val IMAGE: Int = 0x06 + const val IMAGE: Int = 0x03 const val CHAIN: Int = 0xff//仅用于 equals. Packet 中不存在 Chain 概念 } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Face.kt b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Face.kt index c22d31fe9..a3edd2f3d 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Face.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Face.kt @@ -3,8 +3,10 @@ package net.mamoe.mirai.message.defaults import net.mamoe.mirai.message.FaceID import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.MessageId +import net.mamoe.mirai.network.packet.readLVNumber import net.mamoe.mirai.network.packet.writeHex import net.mamoe.mirai.network.packet.writeLVByteArray +import net.mamoe.mirai.utils.lazyDecode import net.mamoe.mirai.utils.lazyEncode /** @@ -41,5 +43,18 @@ class Face(val id: FaceID) : Message() { } return this.id == another.id } + + companion object { + fun ofByteArray(data: ByteArray): Face = lazyDecode(data) { + //00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0 + //00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D + it.skip(1) + + val id1 = FaceID.ofId(it.readLVNumber().toInt())//可能这个是id, 也可能下面那个 + it.skip(it.readByte().toLong()) + it.readLVNumber()//某id? + return@lazyDecode Face(id1) + } + } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Image.kt b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Image.kt index 6204f9c82..c50cbcc7d 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Image.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Image.kt @@ -2,30 +2,33 @@ package net.mamoe.mirai.message.defaults import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.MessageId -import net.mamoe.mirai.network.packet.writeHex -import net.mamoe.mirai.network.packet.writeLVByteArray -import net.mamoe.mirai.network.packet.writeLVString +import net.mamoe.mirai.network.packet.* +import net.mamoe.mirai.utils.lazyDecode import net.mamoe.mirai.utils.lazyEncode +import net.mamoe.mirai.utils.skip +import net.mamoe.mirai.utils.toUHexString /** * 图片消息. * 由接收消息时构建, 可直接发送 * + * @param imageId 类似 `{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg`. 群的是大写id, 好友的是小写id + * * @author Him188moe */ -open class Image internal constructor(val imageID: String) : Message() { +open class Image internal constructor(val imageId: String) : Message() { override val type: Int = MessageId.IMAGE override fun toStringImpl(): String { - return imageID + return imageId } override fun toByteArray(): ByteArray = lazyEncode { section -> - section.writeByte(0x03)//todo 可能是 0x03? + section.writeByte(MessageId.IMAGE) section.writeLVByteArray(lazyEncode { child -> child.writeByte(0x02) - child.writeLVString(this.imageID) + child.writeLVString(this.imageId) child.writeHex("04 00 " + "04 9B 53 B0 08 " + "05 00 " + @@ -35,16 +38,51 @@ open class Image internal constructor(val imageID: String) : Message() { "07 00 " + "01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 11 00 00 00 15 00 04 00 00 02 BC 16 00 04 00 00 02 BC 18 00 04 00 00 7D 5E FF 00 5C 15 36 20 39 32 6B 41 31 43 39 62 35 33 62 30 30 38 64 39 38 61 35 61 37 30 20") child.writeHex("20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20") - child.writeBytes(this.imageID) + child.writeBytes(this.imageId) child.writeByte(0x41) }) } override fun valueEquals(another: Message): Boolean { if (another is Image) { - return this.imageID == another.imageID + return this.imageId == another.imageId } return false } + + companion object { + @JvmStatic + fun ofByteArray0x06(data: ByteArray): Image = lazyDecode(data) { + it.skip(1) + println("好友的图片") + println(data.toUHexString()) + val filenameLength = it.readShort() + val suffix = it.readString(filenameLength).substringAfter(".") + it.skip(data.size - 37 - 1 - filenameLength - 2) + val imageId = String(it.readNBytes(36)) + println(imageId) + it.skip(1)//0x41 + return@lazyDecode Image("{$imageId}.$suffix") + } + + @JvmStatic + fun ofByteArray0x03(data: ByteArray): Image = lazyDecode(data) { + it.skip(1) + return@lazyDecode Image(String(it.readLVByteArray())) + /* + println(String(it.readLVByteArray())) + it.readTLVMap() + return@lazyDecode Image(String(it.readLVByteArray().cutTail(5).getRight(42))) + / + it.skip(data.size - 47) + val imageId = String(it.readNBytes(42)) + it.skip(1)//0x41 + it.skip(1)//0x42 + it.skip(1)//0x43 + it.skip(1)//0x41 + + return@lazyDecode Image(imageId)*/ + } + } } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/PlainText.kt b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/PlainText.kt index e14938561..a6d089dbd 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/PlainText.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/PlainText.kt @@ -2,8 +2,10 @@ package net.mamoe.mirai.message.defaults import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.MessageId +import net.mamoe.mirai.network.packet.readLVString import net.mamoe.mirai.network.packet.writeLVByteArray import net.mamoe.mirai.network.packet.writeLVString +import net.mamoe.mirai.utils.lazyDecode import net.mamoe.mirai.utils.lazyEncode /** @@ -31,4 +33,11 @@ class PlainText(private val text: String) : Message() { } return this.text == another.text } + + companion object { + fun ofByteArray(data: ByteArray): PlainText = lazyDecode(data) { + it.skip(1) + PlainText(it.readLVString()) + } + } } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt index a8afd0295..b3cf226b9 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt @@ -3,9 +3,9 @@ package net.mamoe.mirai.message.defaults import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.network.LoginSession import net.mamoe.mirai.network.packet.image.ClientTryGetImageIDPacket -import net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageFailedPacket -import net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageResponsePacket -import net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageSuccessPacket +import net.mamoe.mirai.network.packet.image.ServerTryGetImageIDFailedPacket +import net.mamoe.mirai.network.packet.image.ServerTryGetImageIDResponsePacket +import net.mamoe.mirai.network.packet.image.ServerTryGetImageIDSuccessPacket import net.mamoe.mirai.network.packet.md5 import net.mamoe.mirai.utils.ImageNetworkUtils import net.mamoe.mirai.utils.toByteArray @@ -27,16 +27,16 @@ class UnsolvedImage(filename: String, val image: BufferedImage) : Image(getImage constructor(url: URL) : this(File(url.file)) fun upload(session: LoginSession, contact: Contact): CompletableFuture { - return session.expectPacket { - toSend { ClientTryGetImageIDPacket(session.bot.account.qqNumber, session.sessionKey, session.bot.account.qqNumber, image) } + return session.expectPacket { + toSend { ClientTryGetImageIDPacket(session.bot.account.qqNumber, session.sessionKey, contact.number, image) } expect { when (it) { - is ServerTryUploadGroupImageFailedPacket -> { + is ServerTryGetImageIDFailedPacket -> { //已经存在于服务器了 } - is ServerTryUploadGroupImageSuccessPacket -> { + is ServerTryGetImageIDSuccessPacket -> { val data = image.toByteArray() if (!ImageNetworkUtils.postImage(it.uKey.toUHexString(), data.size, session.bot.account.qqNumber, contact.number, data)) { throw RuntimeException("cannot upload image") @@ -56,8 +56,8 @@ class UnsolvedImage(filename: String, val image: BufferedImage) : Image(getImage return "{" + md5.copyOfRange(0, 4).toUHexString("") + "-" .plus(md5.copyOfRange(4, 6).toUHexString("")) + "-" .plus(md5.copyOfRange(6, 8).toUHexString("")) + "-" - .plus(md5.copyOfRange(8, 12).toUHexString("")) + "-" - .plus(md5.copyOfRange(12, 16).toUHexString("")) + "}." + if (filename.endsWith(".jpeg")) "jpg" else filename.substringAfter(".", "jpg") + .plus(md5.copyOfRange(8, 10).toUHexString("")) + "-" + .plus(md5.copyOfRange(10, 16).toUHexString("")) + "}." + if (filename.endsWith(".jpeg")) "jpg" else filename.substringAfter(".", "jpg") } } } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt index 187d7327c..098f65ca0 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt @@ -70,7 +70,7 @@ object Protocol { * 发送/接受消息中的一个const (?) * length=15 */ - const val friendMessageConst1 = "00 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91" + const val messageConst1 = "00 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91" private val hexToByteArrayCacheMap: MutableMap = mutableMapOf() diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/ActionPacketHandler.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/ActionPacketHandler.kt index bd68f3323..68e804e9c 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/ActionPacketHandler.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/ActionPacketHandler.kt @@ -6,9 +6,9 @@ import net.mamoe.mirai.network.packet.action.AddFriendResult import net.mamoe.mirai.network.packet.action.ClientAddFriendPacket import net.mamoe.mirai.network.packet.action.ClientCanAddFriendPacket import net.mamoe.mirai.network.packet.action.ServerCanAddFriendResponsePacket -import net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageFailedPacket -import net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageResponsePacket -import net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageSuccessPacket +import net.mamoe.mirai.network.packet.image.ServerTryGetImageIDFailedPacket +import net.mamoe.mirai.network.packet.image.ServerTryGetImageIDResponsePacket +import net.mamoe.mirai.network.packet.image.ServerTryGetImageIDSuccessPacket import net.mamoe.mirai.task.MiraiThreadPool import net.mamoe.mirai.utils.getGTK import java.awt.image.BufferedImage @@ -39,15 +39,15 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) { it.onPacketReceived(packet) } } - is ServerTryUploadGroupImageSuccessPacket -> { + is ServerTryGetImageIDSuccessPacket -> { // ImageNetworkUtils.postImage(packet.uKey.toUHexString(), ) } - is ServerTryUploadGroupImageFailedPacket -> { + is ServerTryGetImageIDFailedPacket -> { } - is ServerTryUploadGroupImageResponsePacket.Encrypted -> session.socket.distributePacket(packet.decrypt(session.sessionKey)) + is ServerTryGetImageIDResponsePacket.Encrypted -> session.socket.distributePacket(packet.decrypt(session.sessionKey)) is ServerAccountInfoResponsePacket.Encrypted -> session.socket.distributePacket(packet.decrypt(session.sessionKey)) is ServerAccountInfoResponsePacket -> { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/MessagePacketHandler.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/MessagePacketHandler.kt index 728bd20c3..8a95cc32a 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/MessagePacketHandler.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/MessagePacketHandler.kt @@ -2,18 +2,21 @@ package net.mamoe.mirai.network.handler import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.QQ +import net.mamoe.mirai.event.events.group.GroupMessageEvent import net.mamoe.mirai.event.events.qq.FriendMessageEvent import net.mamoe.mirai.event.hookWhile +import net.mamoe.mirai.message.defaults.Image import net.mamoe.mirai.message.defaults.MessageChain import net.mamoe.mirai.message.defaults.PlainText -import net.mamoe.mirai.message.defaults.UnsolvedImage import net.mamoe.mirai.network.LoginSession -import net.mamoe.mirai.network.packet.* +import net.mamoe.mirai.network.packet.ServerFriendMessageEventPacket +import net.mamoe.mirai.network.packet.ServerGroupMessageEventPacket +import net.mamoe.mirai.network.packet.ServerGroupUploadFileEventPacket +import net.mamoe.mirai.network.packet.ServerPacket import net.mamoe.mirai.network.packet.action.ClientSendFriendMessagePacket import net.mamoe.mirai.network.packet.action.ClientSendGroupMessagePacket import net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket import net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket -import java.io.File /** * 处理消息事件, 承担消息发送任务. @@ -31,21 +34,39 @@ class MessagePacketHandler(session: LoginSession) : PacketHandler(session) { return@hookWhile false } when { - it.message() valueEquals "你好" -> it.qq.sendMessage("你好!") - it.message().toString().startsWith("复读") -> it.qq.sendMessage(it.message()) - it.message().toString().startsWith("发群") -> { + it.message valueEquals "你好" -> it.sender.sendMessage("你好!") + it.message.toString().startsWith("复读") -> it.sender.sendMessage(it.message()) + it.message.toString().startsWith("发群") -> { it.message().list.toMutableList().let { messages -> messages.removeAt(0) sendGroupMessage(Group(session.bot, 580266363), MessageChain(messages)) } } - it.message() valueEquals "发图片" -> sendGroupMessage(Group(session.bot, 580266363), PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image -> - image.upload(session, it.qq).get() - }) + /*it.message valueEquals "发图片群" -> sendGroupMessage(Group(session.bot, 580266363), PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image -> + image.upload(session, Group(session.bot, 580266363)).get() + })*/ + it.message valueEquals "发图片群2" -> sendGroupMessage(Group(session.bot, 580266363), Image("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg").toChain()) + /* it.message valueEquals "发图片" -> sendFriendMessage(it.sender, PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image -> + image.upload(session, it.sender).get() + })*/ + it.message valueEquals "发图片2" -> sendFriendMessage(it.sender, PlainText("test") + Image("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg")) } return@hookWhile true } + + GroupMessageEvent::class.hookWhile { + if (session.socket.isClosed()) { + return@hookWhile false + } + + when { + it.message.contains("复读") -> it.group.sendMessage(it.chain) + } + + return@hookWhile true + + } } override fun onPacketReceived(packet: ServerPacket) { @@ -55,20 +76,17 @@ class MessagePacketHandler(session: LoginSession) : PacketHandler(session) { } is ServerFriendMessageEventPacket -> { - if (ignoreMessage) { - return - } + if (ignoreMessage) return FriendMessageEvent(session.bot, session.bot.contacts.getQQ(packet.qq), packet.message).broadcast() } is ServerGroupMessageEventPacket -> { - //todo message chain - //GroupMessageEvent(this.bot, bot.contacts.getGroupByNumber(packet.groupNumber), bot.contacts.getQQ(packet.qq), packet.message) - } + if (ignoreMessage) return - is UnknownServerEventPacket -> { - //todo + if (packet.qq == session.bot.account.qqNumber) return + + GroupMessageEvent(session.bot, session.bot.contacts.getGroupByNumber(packet.groupNumber), session.bot.contacts.getQQ(packet.qq), packet.message).broadcast() } is ServerSendFriendMessageResponsePacket, @@ -86,6 +104,6 @@ class MessagePacketHandler(session: LoginSession) : PacketHandler(session) { } fun sendGroupMessage(group: Group, message: MessageChain) { - session.socket.sendPacket(ClientSendGroupMessagePacket(group.groupId, session.bot.account.qqNumber, session.sessionKey, message)) + session.socket.sendPacket(ClientSendGroupMessagePacket(session.bot.account.qqNumber, group.groupId, session.sessionKey, message)) } } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt index 7b779d718..966938b4d 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt @@ -2,19 +2,17 @@ package net.mamoe.mirai.network.packet -import net.mamoe.mirai.message.FaceID import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.defaults.Face import net.mamoe.mirai.message.defaults.Image import net.mamoe.mirai.message.defaults.MessageChain import net.mamoe.mirai.message.defaults.PlainText import net.mamoe.mirai.network.Protocol -import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.hexToBytes +import net.mamoe.mirai.utils.lazyDecode import net.mamoe.mirai.utils.toUHexString -import java.io.ByteArrayOutputStream +import net.mamoe.mirai.utils.toUInt import java.io.DataInputStream -import java.util.zip.GZIPInputStream /** * Packet id: `00 CE` or `00 17` @@ -59,7 +57,12 @@ abstract class ServerEventPacket(input: DataInputStream, val packetId: ByteArray /** * Unknown event */ -class UnknownServerEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) +class UnknownServerEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) { + override fun decode() { + super.decode() + println("UnknownServerEventPacket data: " + this.input.goto(0).readAllBytes().toUHexString()) + } +} /** * Android 客户端上线 @@ -86,8 +89,8 @@ class ServerGroupUploadFileEventPacket(input: DataInputStream, packetId: ByteArr class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) { var groupNumber: Long = 0 var qq: Long = 0 - lateinit var message: String - lateinit var messageType: MessageType + lateinit var senderName: String + lateinit var message: MessageChain enum class MessageType { NORMAL, @@ -107,10 +110,29 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray, override fun decode() { println(this.input.goto(0).readAllBytes().toUHexString()) groupNumber = this.input.goto(51).readInt().toLong() - qq = this.input.goto(56).readLong() - val fontLength = this.input.goto(108).readShort() - //println(this.input.goto(110 + fontLength).readNBytesAt(2).toUHexString())//always 00 00 + qq = this.input.goto(56).readNBytes(4).toUInt().toLong() + this.input.goto(108) + this.input.readLVByteArray() + input.skip(2)//2个0x00 + message = input.readSections() + + val map = input.readTLVMap(true) + if (map.containsKey(18)) { + this.senderName = lazyDecode(map.getValue(18)) { + val tlv = it.readTLVMap(true) + tlv.printTLVMap() + + when { + tlv.containsKey(0x01) -> String(tlv.getValue(0x01)) + tlv.containsKey(0x02) -> String(tlv.getValue(0x02)) + else -> "null" + } + } + } + + + /* messageType = when (val id = this.input.goto(110 + fontLength + 2).readByte().toInt()) { 0x13 -> MessageType.NORMAL 0x0E -> MessageType.XML @@ -126,9 +148,9 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray, MiraiLogger.debug("ServerGroupMessageEventPacket id=$id") MessageType.OTHER } - } - + }*/ +/* when (messageType) { MessageType.NORMAL -> { val gzippedMessage = this.input.goto(110 + fontLength + 16).readNBytes(this.input.goto(110 + fontLength + 3).readShort().toInt() - 11) @@ -184,10 +206,26 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray, } }*/ } - } + }*/ } } +fun main() { + println(String("E7 BE A4".hexToBytes())) + + + println(".".toByteArray().toUByteArray().toUHexString()) + //长文本 22 96 29 7B B4 DF 94 AA 00 01 9F 8E 09 18 85 5B 1F 40 00 52 00 00 00 1B 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 0C 00 05 00 01 00 01 01 22 96 29 7B 01 3E 03 3F A2 00 03 7E F3 5D 7B 97 57 00 00 F3 32 00 B8 00 01 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00 5D 7B 97 56 7F D0 53 BB 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 12 01 00 0F E9 95 BF E6 96 87 E6 9C AC E6 B6 88 E6 81 AF 0E 00 0E 01 00 04 00 00 00 09 07 00 04 00 00 00 01 19 00 35 01 00 32 AA 02 2F 50 03 60 00 68 00 9A 01 26 08 09 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 B8 03 00 C0 03 00 D0 03 00 E8 03 00 12 00 25 05 00 04 00 00 00 01 08 00 04 00 00 00 01 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08 + val packet = ServerGroupMessageEventPacket(("" + + "22 96 29 7B B4 DF 94 AA 00 09 8F 37 0A 65 07 2E 1F 40 00 52 00 00 00 1B 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 0C 00 05 00 01 00 01 01 22 96 29 7B 01 3E 03 3F A2 00 03 7F 67 5D 7B AE D7 00 00 F3 36 02 E7 00 02 02 00 1B 10 00 00 00 00 4D 53 47 00 00 00 00 00 5D 7B AE D6 F4 91 87 BE 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 03 00 CB 02 00 2A 7B 37 41 41 34 42 33 41 41 2D 38 43 33 43 2D 30 46 34 35 2D 32 44 39 42 2D 37 46 33 30 32 41 30 41 43 45 41 41 7D 2E 6A 70 67 04 00 04 83 81 3B E2 05 00 04 B8 8B 33 79 06 00 04 00 00 00 50 07 00 01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 00 00 00 00 15 00 04 00 00 00 41 16 00 04 00 00 00 34 18 00 04 00 00 03 73 FF 00 5C 15 36 20 39 32 6B 41 31 43 38 33 38 31 33 62 65 32 62 38 38 62 33 33 37 39 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 37 41 41 34 42 33 41 41 2D 38 43 33 43 2D 30 46 34 35 2D 32 44 39 42 2D 37 46 33 30 32 41 30 41 43 45 41 41 7D 2E 6A 70 67 41 01 00 09 01 00 06 E7 89 9B E9 80 BC 03 00 77 02 00 2A 7B 37 41 41 34 42 33 41 41 2D 38 43 33 43 2D 30 46 34 35 2D 32 44 39 42 2D 37 46 33 30 32 41 30 41 43 45 41 41 7D 2E 6A 70 67 04 00 04 83 81 3B E2 05 00 04 B8 8B 33 79 06 00 04 00 00 00 50 07 00 01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 00 00 00 00 15 00 04 00 00 00 41 16 00 04 00 00 00 34 18 00 04 00 00 03 73 FF 00 08 15 37 20 20 38 41 41 41 02 00 14 01 00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0 03 00 CE 02 00 2A 7B 31 46 42 34 43 32 35 45 2D 42 34 46 45 2D 31 32 45 34 2D 46 33 42 42 2D 38 31 39 31 33 37 42 44 39 39 30 39 7D 2E 6A 70 67 04 00 04 B8 27 4B C6 05 00 04 79 5C B1 A3 06 00 04 00 00 00 50 07 00 01 41 08 00 00 09 00 01 01 0B 00 00 14 00 04 03 00 00 00 15 00 04 00 00 00 4E 16 00 04 00 00 00 23 18 00 04 00 00 02 A2 FF 00 5F 15 36 20 39 35 6B 44 31 41 62 38 32 37 34 62 63 36 37 39 35 63 62 31 61 33 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 31 46 42 34 43 32 35 45 2D 42 34 46 45 2D 31 32 45 34 2D 46 33 42 42 2D 38 31 39 31 33 37 42 44 39 39 30 39 7D 2E 6A 70 67 41 42 43 41 0E 00 07 01 00 04 00 00 00 09 19 00 38 01 00 35 AA 02 32 50 03 60 00 68 00 9A 01 29 08 09 20 BF 02 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 B8 03 00 C0 03 00 D0 03 00 E8 03 00 12 00 25 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08 05 00 04 00 00 00 01 08 00 04 00 00 00 01" + + "").hexToBytes().dataInputStream(), byteArrayOf(), byteArrayOf()) + packet.decode() + println(packet) +} + +//牛逼[图片]牛逼[图片] 22 96 29 7B B4 DF 94 AA 00 08 74 A4 09 18 8D CC 1F 40 00 52 00 00 00 1B 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 0C 00 05 00 01 00 01 01 22 96 29 7B 01 3E 03 3F A2 00 03 7F 64 5D 7B AC BD 00 00 F3 36 02 03 00 02 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00 5D 7B AC BD 12 73 DB A2 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 03 00 CB 02 00 2A 7B 37 41 41 34 42 33 41 41 2D 38 43 33 43 2D 30 46 34 35 2D 32 44 39 42 2D 37 46 33 30 32 41 30 41 43 45 41 41 7D 2E 6A 70 67 04 00 04 B4 52 77 F1 05 00 04 BC EB 03 B7 06 00 04 00 00 00 50 07 00 01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 00 00 00 00 15 00 04 00 00 00 41 16 00 04 00 00 00 34 18 00 04 00 00 03 73 FF 00 5C 15 36 20 39 32 6B 41 31 43 62 34 35 32 37 37 66 31 62 63 65 62 30 33 62 37 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 37 41 41 34 42 33 41 41 2D 38 43 33 43 2D 30 46 34 35 2D 32 44 39 42 2D 37 46 33 30 32 41 30 41 43 45 41 41 7D 2E 6A 70 67 41 01 00 09 01 00 06 E7 89 9B E9 80 BC 03 00 77 02 00 2A 7B 37 41 41 34 42 33 41 41 2D 38 43 33 43 2D 30 46 34 35 2D 32 44 39 42 2D 37 46 33 30 32 41 30 41 43 45 41 41 7D 2E 6A 70 67 04 00 04 B4 52 77 F1 05 00 04 BC EB 03 B7 06 00 04 00 00 00 50 07 00 01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 00 00 00 00 15 00 04 00 00 00 41 16 00 04 00 00 00 34 18 00 04 00 00 03 73 FF 00 08 15 37 20 20 38 41 41 41 0E 00 0E 01 00 04 00 00 00 09 07 00 04 00 00 00 01 19 00 35 01 00 32 AA 02 2F 50 03 60 00 68 00 9A 01 26 08 09 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 B8 03 00 C0 03 00 D0 03 00 E8 03 00 12 00 25 05 00 04 00 00 00 01 08 00 04 00 00 00 01 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08 +//牛逼[图片]牛逼 22 96 29 7B B4 DF 94 AA 00 0B C1 0A 09 18 89 93 1F 40 00 52 00 00 00 1B 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 0C 00 05 00 01 00 01 01 22 96 29 7B 01 3E 03 3F A2 00 03 7E F5 5D 7B 97 E7 00 00 F3 32 01 8D 00 02 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00 5D 7B 97 E6 FA BE 7F DC 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 03 00 CF 02 00 2A 7B 39 44 32 44 45 39 31 41 2D 33 39 38 39 2D 39 35 35 43 2D 44 35 42 34 2D 37 46 41 32 37 38 39 37 38 36 30 39 7D 2E 6A 70 67 04 00 04 97 15 7F 03 05 00 04 79 5C B1 A3 06 00 04 00 00 00 50 07 00 01 41 08 00 00 09 00 01 01 0B 00 00 14 00 04 03 00 00 00 15 00 04 00 00 00 3C 16 00 04 00 00 00 40 18 00 04 00 00 03 CC FF 00 60 15 36 20 39 36 6B 45 31 41 39 37 31 35 37 66 30 33 37 39 35 63 62 31 61 33 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 39 44 32 44 45 39 31 41 2D 33 39 38 39 2D 39 35 35 43 2D 44 35 42 34 2D 37 46 41 32 37 38 39 37 38 36 30 39 7D 2E 6A 70 67 31 32 31 32 41 01 00 09 01 00 06 E7 89 9B E9 80 BC 0E 00 0E 01 00 04 00 00 00 09 07 00 04 00 00 00 01 19 00 35 01 00 32 AA 02 2F 50 03 60 00 68 00 9A 01 26 08 09 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 B8 03 00 C0 03 00 D0 03 00 E8 03 00 12 00 25 05 00 04 00 00 00 01 08 00 04 00 00 00 01 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08 + class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) { var qq: Long = 0 lateinit var message: MessageChain @@ -195,18 +233,22 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray override fun decode() { input.goto(0) - println() - println(input.readAllBytes().toUHexString()) + println("ServerFriendMessageEventPacket.input=" + input.readAllBytes().toUHexString()) input.goto(0) qq = input.readUIntAt(0).toLong() val l1 = input.readShortAt(22) input.goto(93 + l1) - input.readVarByteArray()//font + input.readLVByteArray()//font input.skip(2)//2个0x00 message = input.readSections() - println(message.toObjectString()) + + val map: Map = input.readTLVMap(true) + println(map[18]) + + //todo 后面有昵称可读 + //19 00 38 01 00 35 AA 02 32 50 03 60 00 68 00 9A 01 29 08 09 20 BF 02 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 98 03 00 A0 03 20 B0 03 00 B8 03 00 C0 03 00 D0 03 00 E8 03 00 12 00 25 01 00 09 48 69 6D 31 38 38 6D 6F 65 03 00 01 04 04 00 04 00 00 00 08 05 00 04 00 00 00 01 08 00 04 00 00 00 01 /* val offset = unknownLength0 + fontLength//57 @@ -215,50 +257,64 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray input.goto(103 + offset).readString(length.toInt()) }))*/ } +} - private fun DataInputStream.readSection(): Message? { - val messageType = this.readByte().toInt() - val sectionLength = this.readShort().toLong()//sectionLength: short - this.skip(1)//message和face是 0x01, image是0x06 - return when (messageType) { - 0x01 -> PlainText(readVarString()) - 0x02 -> { - //00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0 - //00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D +private fun DataInputStream.readSection(): Message? { + val messageType = this.readByte().toInt() + val sectionLength = this.readShort().toLong()//sectionLength: short + val sectionData = this.readNBytes(sectionLength) + return when (messageType) { + 0x01 -> PlainText.ofByteArray(sectionData) + 0x02 -> Face.ofByteArray(sectionData) + 0x03 -> Image.ofByteArray0x03(sectionData) + 0x06 -> Image.ofByteArray0x06(sectionData) - val id1 = FaceID.ofId(readLVNumber().toInt())//可能这个是id, 也可能下面那个 - this.skip(this.readByte().toLong()) - this.readLVNumber()//某id? - return Face(id1) - } - 0x06 -> { - this.skip(sectionLength - 37 - 1) - val imageId = String(this.readNBytes(36)) - this.skip(1)//0x41 - return Image("{$imageId}.jpg")//todo 如何确定文件后缀?? - } - else -> null + + 0x19 -> {//长文本 + val value = readLVByteArray() + PlainText(String(value)) + + // PlainText(String(GZip.uncompress( value))) } + + 0x14 -> {//长文本 + val value = readLVByteArray() + println(value.size) + println(value.toUHexString()) + this.skip(7)//几个TLV + return PlainText(String(value)) + } + + 0x0E -> {//可能是结尾标志? + //null + null + } + + else -> { + println("未知的messageType=0x${messageType.toByte().toUHexString()}") + println("后文=${this.readAllBytes().toUHexString()}") + null + } } - private fun DataInputStream.readSections(): MessageChain { - val chain = MessageChain() - var got: Message? = null - do { - if (got != null) { - chain.concat(got) - } - got = this.readSection() - } while (got != null) - return chain - } } -fun main() { - println(String("16 20 20 39 39 31 30 20 38 38 31 43 42 20 20 20 20 20 20 31 37 36 32 65 42 39 45 32 37 32 31 43 39 36 44 37 39 41 38 32 31 36 45 30 41 44 34 30 42 35 39 35 39 31 38 36 2E 6A 70 67 66 2F 65 64 33 39 30 66 38 34 2D 34 66 38 37 2D 34 36 64 63 2D 62 33 38 35 2D 34 35 35 36 62 35 31 30 61 61 35 33 41".replace(" ", " ").hexToBytes())) - println(".jpg".toByteArray().size) +private fun DataInputStream.readSections(): MessageChain { + val chain = MessageChain() + var got: Message? = null + do { + if (got != null) { + chain.concat(got) + } + if (this.available() == 0) { + return chain + } + got = this.readSection() + } while (got != null) + return chain } + /* 牛逼 (10404 diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt index 580664e0f..c34996350 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt @@ -11,7 +11,7 @@ import net.mamoe.mirai.network.packet.PacketNameFormatter.adjustName import net.mamoe.mirai.network.packet.action.ServerCanAddFriendResponsePacket import net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket import net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket -import net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageResponsePacket +import net.mamoe.mirai.network.packet.image.ServerTryGetImageIDResponsePacket import net.mamoe.mirai.network.packet.login.* import net.mamoe.mirai.task.MiraiThreadPool import net.mamoe.mirai.utils.* @@ -82,7 +82,9 @@ abstract class ServerPacket(val input: DataInputStream) : Packet { println(bytes.size) return ServerLoginResponseFailedPacket(when (bytes.size) { - 63, 319, 135, 351 -> LoginState.WRONG_PASSWORD//这四个其中一个是被冻结 + 135 -> LoginState.UNKNOWN//账号已经在另一台电脑登录?? + + 63, 319, 351 -> LoginState.WRONG_PASSWORD//63不是密码错误, 应该是登录过频繁 //135 -> LoginState.RETYPE_PASSWORD 279 -> LoginState.BLOCKED 263 -> LoginState.UNKNOWN_QQ_NUMBER @@ -121,9 +123,9 @@ abstract class ServerPacket(val input: DataInputStream) : Packet { "00 A7" -> ServerCanAddFriendResponsePacket(stream) - "03 88" -> ServerTryUploadGroupImageResponsePacket.Encrypted(stream) + "03 88" -> ServerTryGetImageIDResponsePacket.Encrypted(stream) - else -> throw IllegalArgumentException(idHex) + else -> UnknownServerPacket(stream) } }.apply { this.idHex = idHex } } @@ -197,15 +199,48 @@ fun DataInputStream.readIP(): String { return buff } -fun DataInputStream.readVarString(): String { - return String(this.readVarByteArray()) +fun DataInputStream.readLVString(): String { + return String(this.readLVByteArray()) } -fun DataInputStream.readVarByteArray(): ByteArray { +fun DataInputStream.readLVByteArray(): ByteArray { return this.readNBytes(this.readShort().toInt()) } -fun DataInputStream.readString(length: Int): String { +fun DataInputStream.readTLVMap(expectingEOF: Boolean = false): Map { + val map = mutableMapOf() + var type: Int + + try { + type = readUnsignedByte() + } catch (e: EOFException) { + if (expectingEOF) { + return map + } + throw e + } + + while (type != 0xff) { + map[type] = this.readLVByteArray() + + try { + type = readUnsignedByte() + } catch (e: EOFException) { + if (expectingEOF) { + return map + } + throw e + } + } + return map +} + +fun Map.printTLVMap() { + println(this.mapValues { (_, value) -> value.toUHexString() }) +} + + +fun DataInputStream.readString(length: Number): String { return String(this.readNBytes(length)) } @@ -290,8 +325,8 @@ fun DataInputStream.gotoWhere(matcher: ByteArray): DataInputStream { if (b != matcher[i]) { continue@loop //todo goto mark } - return this } + return this } } while (true) } @@ -336,4 +371,6 @@ fun DataInputStream.gotoWhere(matcher: ByteArray) { } while (true) }*/ -fun ByteArray.cutTail(length: Int): ByteArray = this.copyOfRange(0, this.size - length) \ No newline at end of file +fun ByteArray.cutTail(length: Int): ByteArray = this.copyOfRange(0, this.size - length) + +fun ByteArray.getRight(length: Int): ByteArray = this.copyOfRange(this.size - length, this.size) \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/UnknownServerPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/UnknownServerPacket.kt index 9452ee380..37ec68e16 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/UnknownServerPacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/UnknownServerPacket.kt @@ -1,5 +1,7 @@ package net.mamoe.mirai.network.packet +import net.mamoe.mirai.utils.LoggerTextFormat +import net.mamoe.mirai.utils.toUHexString import java.io.DataInputStream /** @@ -7,6 +9,10 @@ import java.io.DataInputStream */ class UnknownServerPacket(input: DataInputStream) : ServerPacket(input) { override fun decode() { + println("UnknownServerPacket data: " + this.input.goto(0).readAllBytes().toUHexString()) + } + override fun toString(): String { + return LoggerTextFormat.LIGHT_RED.toString() + super.toString() } } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendFriendMessagePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendFriendMessagePacket.kt index d60aeacb1..10a7ecc08 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendFriendMessagePacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendFriendMessagePacket.kt @@ -38,7 +38,7 @@ class ClientSendFriendMessagePacket( it.writeTime() it.writeRandom(4) it.writeHex("00 00 00 00 09 00 86") - it.writeHex(Protocol.friendMessageConst1)//... 85 E9 BB 91 + it.writeHex(Protocol.messageConst1)//... 85 E9 BB 91 it.writeZero(2) it.write(message.toByteArray()) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendGroupMessagePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendGroupMessagePacket.kt index bc480103d..42479a511 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendGroupMessagePacket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendGroupMessagePacket.kt @@ -3,6 +3,7 @@ package net.mamoe.mirai.network.packet.action import net.mamoe.mirai.message.defaults.MessageChain import net.mamoe.mirai.network.Protocol import net.mamoe.mirai.network.packet.* +import net.mamoe.mirai.utils.lazyEncode import net.mamoe.mirai.utils.toUHexString import java.io.DataInputStream @@ -11,8 +12,8 @@ import java.io.DataInputStream */ @PacketId("00 02") class ClientSendGroupMessagePacket( - private val groupId: Long,//不是 number private val botQQ: Long, + private val groupId: Long,//不是 number private val sessionKey: ByteArray, private val message: MessageChain ) : ClientPacket() { @@ -26,18 +27,19 @@ class ClientSendGroupMessagePacket( it.writeByte(0x2A) it.writeGroup(groupId) - it.writeShort(50 + bytes.size) - it.writeHex("00 01 01") - it.writeHex("00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00") + it.writeLVByteArray(lazyEncode { child -> + child.writeHex("00 01 01") + child.writeHex("00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00") - it.writeTime() - it.writeRandom(4) - it.writeHex("00 00 00 00 09 00 86") - it.writeHex(Protocol.friendMessageConst1) - it.writeZero(2) + child.writeTime() + child.writeRandom(4) + child.writeHex("00 00 00 00 09 00 86") + child.writeHex(Protocol.messageConst1) + child.writeZero(2) - //messages - it.write(bytes) + //messages + child.write(bytes) + }) /*it.writeByte(0x01) it.writeShort(bytes.size + 3) it.writeByte(0x01) diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/image/UploadGroupImage.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/image/UploadGroupImage.kt index 839f9c8a9..f72a59020 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/image/UploadGroupImage.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/image/UploadGroupImage.kt @@ -11,8 +11,8 @@ import java.io.DataInputStream /** * 请求上传图片. 将发送图片的 md5, size. * 服务器返回以下之一: - * - 服务器已经存有这个图片 [ServerTryUploadGroupImageFailedPacket] - * - 服务器未存有, 返回一个 key 用于客户端上传 [ServerTryUploadGroupImageSuccessPacket] + * - 服务器已经存有这个图片 [ServerTryGetImageIDFailedPacket] + * - 服务器未存有, 返回一个 key 用于客户端上传 [ServerTryGetImageIDSuccessPacket] * * @author Him188moe */ @@ -20,7 +20,7 @@ import java.io.DataInputStream class ClientTryGetImageIDPacket( private val botNumber: Long, private val sessionKey: ByteArray, - private val groupNumberOrQQNumber: Long,//todo 为什么还要有qq number呢? bot不就是了么 + private val groupNumberOrQQNumber: Long, private val image: BufferedImage ) : ClientPacket() { override fun encode() { @@ -89,18 +89,18 @@ class ClientTryGetImageIDPacket( } } -abstract class ServerTryUploadGroupImageResponsePacket(input: DataInputStream) : ServerPacket(input) { +abstract class ServerTryGetImageIDResponsePacket(input: DataInputStream) : ServerPacket(input) { class Encrypted(input: DataInputStream) : ServerPacket(input) { - fun decrypt(sessionKey: ByteArray): ServerTryUploadGroupImageResponsePacket { + fun decrypt(sessionKey: ByteArray): ServerTryGetImageIDResponsePacket { val data = this.decryptAsByteArray(sessionKey) println(data.size) println(data.size) if (data.size == 209) { - return ServerTryUploadGroupImageSuccessPacket(data.dataInputStream()).setId(this.idHex) + return ServerTryGetImageIDSuccessPacket(data.dataInputStream()).setId(this.idHex) } - return ServerTryUploadGroupImageFailedPacket(data.dataInputStream()) + return ServerTryGetImageIDFailedPacket(data.dataInputStream()) } } } @@ -108,25 +108,21 @@ abstract class ServerTryUploadGroupImageResponsePacket(input: DataInputStream) : /** * 服务器未存有图片, 返回一个 key 用于客户端上传 */ -class ServerTryUploadGroupImageSuccessPacket(input: DataInputStream) : ServerTryUploadGroupImageResponsePacket(input) { +class ServerTryGetImageIDSuccessPacket(input: DataInputStream) : ServerTryGetImageIDResponsePacket(input) { lateinit var uKey: ByteArray override fun decode() { - uKey = this.input.gotoWhere(ubyteArrayOf(0x42u, 0x80u, 0x01u)).readNBytes(128) + this.input.gotoWhere(ubyteArrayOf(0x42u, 0x80u, 0x01u)) + uKey = this.input.readNBytes(128) } } /** * 服务器已经存有这个图片 */ -class ServerTryUploadGroupImageFailedPacket(input: DataInputStream) : ServerTryUploadGroupImageResponsePacket(input) { +class ServerTryGetImageIDFailedPacket(input: DataInputStream) : ServerTryGetImageIDResponsePacket(input) { override fun decode() { } -} - -fun main() { - - println(0xff) } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/ImageNetworkUtils.java b/mirai-core/src/main/java/net/mamoe/mirai/utils/ImageNetworkUtils.java index be23a8fcd..1db1ef455 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/utils/ImageNetworkUtils.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/ImageNetworkUtils.java @@ -9,18 +9,18 @@ import java.net.URL; * @author NaturalHG */ public class ImageNetworkUtils { - public static boolean postImage(String uKeyHex, int fileSize, long qqNumber, long groupCode, byte[] img) throws IOException { + public static boolean postImage(String uKeyHex, int fileSize, long botNumber, long groupCode, byte[] img) throws IOException { //http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc&ukey=” + 删全部空 (ukey) + “&filesize=” + 到文本 (fileSize) + “&range=0&uin=” + g_uin + “&groupcode=” + Group - String builder = "http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc" + "&ukey=" + - uKeyHex.replace(" ", "") + + String builder = "http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc" + + "&ukey=" + uKeyHex.replace(" ", "") + "&filezise=" + fileSize + "&range=" + "0" + - "&uin=" + qqNumber + + "&uin=" + botNumber + "&groupcode=" + groupCode; HttpURLConnection conn = (HttpURLConnection) new URL(builder).openConnection(); - conn.setRequestProperty("User-agent", "QQClient"); - conn.setRequestProperty("Content-length", "" + fileSize); + conn.setRequestProperty("User-Agent", "QQClient"); + conn.setRequestProperty("Content-Length", "" + fileSize); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.getOutputStream().write(img); diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt b/mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt index 788ec66a4..07402be7c 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt @@ -3,15 +3,20 @@ package net.mamoe.mirai.utils import net.mamoe.mirai.network.Protocol +import net.mamoe.mirai.network.packet.dataInputStream import java.awt.image.BufferedImage import java.io.ByteArrayOutputStream +import java.io.DataInputStream import java.io.DataOutputStream import java.io.File import java.lang.reflect.Field import java.util.* import java.util.zip.CRC32 +import java.util.zip.GZIPInputStream +import java.util.zip.GZIPOutputStream import javax.imageio.ImageIO + /** * @author Him188moe * @author NaturalHG @@ -76,6 +81,12 @@ open class ByteArrayDataOutputStream : DataOutputStream(ByteArrayOutputStream()) @JvmSynthetic fun lazyEncode(t: (ByteArrayDataOutputStream) -> Unit): ByteArray = ByteArrayDataOutputStream().also(t).toByteArray() +@JvmSynthetic +fun lazyDecode(byteArray: ByteArray, t: (DataInputStream) -> T): T = byteArray.dataInputStream().let(t) + +fun DataInputStream.skip(n: Number) { + this.skip(n.toLong()) +} fun getRandomByteArray(length: Int): ByteArray { val bytes = LinkedList() @@ -144,4 +155,15 @@ fun BufferedImage.toByteArray(formatName: String = "PNG"): ByteArray { return lazyEncode { ImageIO.write(this, formatName, it) } +} + +object GZip { + fun uncompress(bytes: ByteArray): ByteArray = lazyEncode { + GZIPInputStream(bytes.inputStream()).transferTo(it) + } + + fun compress(bytes: ByteArray): ByteArray = ByteArrayOutputStream().let { + GZIPOutputStream(it).write(bytes) + return it.toByteArray() + } } \ No newline at end of file diff --git a/mirai-core/src/test/java/HexComparator.java b/mirai-core/src/test/java/HexComparator.java index 66d73c2b5..674b274ff 100644 --- a/mirai-core/src/test/java/HexComparator.java +++ b/mirai-core/src/test/java/HexComparator.java @@ -58,6 +58,9 @@ public class HexComparator { private static final String _1040400290_ = "3E 03 3F A2"; private static final String _1994701021_ = "76 E4 B8 DD"; private static final String _jiahua_ = "B1 89 BE 09"; + private static final String _Him188moe_ = UtilsKt.toUHexString("Him188moe".getBytes(), " "); + private static final String 发图片 = UtilsKt.toUHexString("发图片".getBytes(), " "); + private static final String 群 = UtilsKt.toUHexString("发图片".getBytes(), " "); private static final String SINGLE_PLAIN_MESSAGE_HEAD = "00 00 01 00 09 01";