Commit b488bee0 authored by Him188moe's avatar Him188moe

updated

parent ff0acc87
......@@ -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")) {
......
......@@ -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);
......
......@@ -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
......
......@@ -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;
}
}
......@@ -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;
}
}
......@@ -166,7 +166,7 @@ public enum FaceID {
return value;
}
}
return null;
return FaceID.unknown;
}
......
......@@ -74,7 +74,7 @@ abstract class Message {
/**
* 比较两个 Message 的内容是否相等. 如:
* - [PlainText] 比较 [PlainText.text]
* - [Image] 比较 [Image.imageID]
* - [Image] 比较 [Image.imageId]
*/
abstract infix fun valueEquals(another: Message): Boolean
......
......@@ -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
......@@ -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)
}
}
}
......@@ -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
......@@ -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())
}
}
}
......@@ -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<Unit> {
return session.expectPacket<ServerTryUploadGroupImageResponsePacket> {
toSend { ClientTryGetImageIDPacket(session.bot.account.qqNumber, session.sessionKey, session.bot.account.qqNumber, image) }
return session.expectPacket<ServerTryGetImageIDResponsePacket> {
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
......@@ -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<Int, ByteArray> = mutableMapOf()
......
......@@ -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 -> {
......
......@@ -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
......@@ -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<Int, ByteArray> {
val map = mutableMapOf<Int, ByteArray>()
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<Int, ByteArray>.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
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
......@@ -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())
......
......@@ -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)
......
......@@ -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
......@@ -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);
......
......@@ -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 <T> 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<Byte>()
......@@ -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
......@@ -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";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment