diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/friend/GetFriendListRequest.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/friend/FriendListPacket.kt similarity index 79% rename from mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/friend/GetFriendListRequest.kt rename to mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/friend/FriendListPacket.kt index b1dc79014..27c58c81c 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/friend/GetFriendListRequest.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/friend/FriendListPacket.kt @@ -6,8 +6,8 @@ import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory -internal object GetFriendListRequest : - PacketFactory("friendlist.GetFriendListReq") { +internal object FriendListPacket : + PacketFactory("friendlist.GetFriendListReq") { class GetFriendListResponse() : Packet diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/friend/data/GetFriendListRequest.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/friend/data/GetFriendListRequest.kt new file mode 100644 index 000000000..f4776cbdd --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/friend/data/GetFriendListRequest.kt @@ -0,0 +1,30 @@ +package net.mamoe.mirai.qqandroid.network.protocol.packet.friend.data + +import kotlinx.serialization.SerialId +import kotlinx.serialization.Serializable +import net.mamoe.mirai.qqandroid.io.JceStruct + +@Serializable +internal class GetFriendListReq( + @SerialId(0) val reqtype: Int? = null, + @SerialId(1) val ifReflush: Byte? = null, + @SerialId(2) val uin: Long? = null, + @SerialId(3) val startIndex: Short? = null, + @SerialId(4) val getfriendCount: Short? = null, + @SerialId(5) val groupid: Byte? = null, + @SerialId(6) val ifGetGroupInfo: Byte? = null, + @SerialId(7) val groupstartIndex: Byte? = null, + @SerialId(8) val getgroupCount: Byte? = null, + @SerialId(9) val ifGetMSFGroup: Byte? = null, + @SerialId(10) val ifShowTermType: Byte? = null, + @SerialId(11) val version: Long? = null, + @SerialId(12) val uinList: List? = null, + @SerialId(13) val eAppType: Int = 0, + @SerialId(14) val ifGetDOVId: Byte? = null, + @SerialId(15) val ifGetBothFlag: Byte? = null, + @SerialId(16) val vec0xd50Req: ByteArray? = null, + @SerialId(17) val vec0xd6bReq: ByteArray? = null, + @SerialId(18) val vecSnsTypelist: List? = null +) : JceStruct + + diff --git a/mirai-core-qqandroid/src/jvmTest/kotlin/test/DataClassGenerator.kt b/mirai-core-qqandroid/src/jvmTest/kotlin/test/DataClassGenerator.kt new file mode 100644 index 000000000..99ae9328a --- /dev/null +++ b/mirai-core-qqandroid/src/jvmTest/kotlin/test/DataClassGenerator.kt @@ -0,0 +1,83 @@ +package test + +import kotlinx.coroutines.channels.Channel +import java.lang.StringBuilder +import java.util.* +import java.util.concurrent.BlockingQueue +import kotlin.concurrent.thread + + +fun main(){ + val inputs = LinkedList() + thread { + while (true){ + val x = readLine() + if(x!=null) inputs.offer(x) + } + } + + tailrec fun getNext():String{ + val x = inputs.poll() + if(x == null){ + Thread.sleep(100) + return getNext() + } + return x; + } + + fun getAll():String{ + val b = StringBuilder(getNext()) + Thread.sleep(500) + while(true){ + val c = inputs.poll(); + if(c===null)break; + b.append("\n").append(c) + } + return b.toString(); + } + + while (true){ + println("-proto || -jce") + val x = getNext() + + if(x.contains("proto",true)){ + //proto + println("..Copy file content below, after each file is submited, click enter, after all file are in, input \'end'\'") + val y = mutableListOf() + while (true){ + val z = getAll() + if(z.toLowerCase() == "end" || z.toLowerCase() == "end\n"){ + println("received file content: " + y.size + ", start generating ProtoBuf" ) + break; + } + y.add(z) + println("received, ") + } + println("======================>protoBuf output<===========================") + println() + println() + println(y.map { it.generateProtoBufDataClass() }.toMutableList().arrangeClasses().joinToString("\n\n")); + println() + println() + println("======================>protoBuf output<===========================") + } + + if(x.contains("jce",true)){ + println("..Copy the WHOLE file below") + while (true){ + val z = getAll() + println("======================>JCE output<===========================") + println() + println() + println(toJCEInfo(z).toString()) + println() + println() + println("======================>JCE output<===========================") + break; + } + } + } +} + + + diff --git a/mirai-core-qqandroid/src/jvmTest/kotlin/test/JceDataClassGenerator.kt b/mirai-core-qqandroid/src/jvmTest/kotlin/test/JceDataClassGenerator.kt new file mode 100644 index 000000000..9b0243314 --- /dev/null +++ b/mirai-core-qqandroid/src/jvmTest/kotlin/test/JceDataClassGenerator.kt @@ -0,0 +1,140 @@ +package test; + +import net.mamoe.mirai.utils.cryptor.contentToString +import java.io.File +import java.lang.StringBuilder + +fun main(){ + val var9 = toJCEInfo(File("/Users/jiahua.liu/Desktop/mirai/mirai-core-qqandroid/src/jvmTest/kotlin/test/GetFriendListReq").readText()) + println("import kotlinx.serialization.SerialId\n" + + "import kotlinx.serialization.Serializable\n" + + "import net.mamoe.mirai.qqandroid.io.JceStruct\n") + println(var9.toString()) +} + + +/** + * 不支持叠加中 + */ +class JCEInfo( +){ + lateinit var className: String + var parents: List? = null//seems useless + lateinit var properties: List + + override fun toString(): String { + properties = properties.sortedBy { it->it.jceID } + /** + * + @Serializable + class RequestDataVersion2( + @SerialId(0) val map: Map> + ) : JceStruct + */ + val max = (properties.size - 1).toString().length + val builder:StringBuilder = StringBuilder("@Serializable") + builder.append("\n").append("internal class ").append(className).append("(") + properties.forEach { + builder.append(",").append("\n").append(it.toStringWithSpacing(max)) + } + builder.append("\n").append("): JceStruct") + return builder.toString().replace("(,","(") + } + + +} + +class Property( + val name:String, + var type:String, + var defaultValue:String? = null +){ + var jceID:Int = -1 + //convert type/default value to kotlin format + init { + type = type + .replace("byte[]", "ByteArray") + .replace("ArrayList", "List") + .replace("byte", "Byte") + .replace("int", "Int") + .replace("short", "Short") + .replace("long", "Long") + } + //@SerialId(1) val iVersion: Short = 3, + override fun toString(): String { + if (defaultValue != null) { + return "@SerialId(" + jceID + ") val " + name + ":" + type + " = " + defaultValue + } + return "@SerialId(" + jceID + ") val " + name + ":" + type+"? = null" + } + + fun toStringWithSpacing(maxIDLength:Int): String { + val space = " ".repeat(maxIDLength - (jceID.toString().length)) + if (defaultValue != null) { + return " @SerialId(" + jceID + ") " + space + "val " + name + ":" + type + " = " + defaultValue + } + return " @SerialId(" + jceID + ") "+ space +"val " + name + ":" + type+"? = null" + } + +} + + +fun toJCEInfo(source:String):JCEInfo{ + val info = JCEInfo() + val allProperties = mutableMapOf() + var inputStreamVariableRegix:String? = null + println(source) + source.split("\n").forEach{ + when{ + it.contains("class") -> { + var var0 = it.substringBetween("class","{").trim() + if(var0.contains("extends")){ + info.parents = var0.substringAfter("extends").split(",").map { it.trim() }.toList() + var0 = var0.substringBefore(" extends") + } + //println("class name: $var0" ) + info.className = var0 + } + + (it.contains("public") && it.contains(";")) -> { + val var1 = it.trim().split(" ") + if(var1.size == 5){ + allProperties.put(var1[2], + Property( + var1[2], + var1[1], + var1[4].replace(";","") + ) + ) + }else{ + allProperties.put( + var1[2].replace(";",""), + Property( + var1[2].replace(";",""), + var1[1] + ) + ) + } + } + + (inputStreamVariableRegix==null && it.contains("public void readFrom")) -> { + // public void readFrom(JceInputStream var1) { + inputStreamVariableRegix = it.trim().substringBetween("(JceInputStream ",")") + ".read" + //println("inputStreamVariableRegix: " + inputStreamVariableRegix ) + } + + (inputStreamVariableRegix!=null && it.contains(inputStreamVariableRegix!!)) -> { + val key = it.substringBetween("this.", " = ") + if(!allProperties.containsKey(key)){ + println(key + " is found in readFrom but not in properties") + } + val id = it + .substringBetween(".read(",");") + .split(",")[1].trim().toInt() + allProperties.get(key)?.jceID = id; + } + } + } + info.properties = allProperties.values.toList(); + return info; +} \ No newline at end of file