From a8aded9bf974488dfb06302f7d6a323847e08250 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Fri, 7 Feb 2020 21:41:08 +0800
Subject: [PATCH 1/5] Fix error message

---
 .../commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
index 5e0225119..ef6263804 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
@@ -340,7 +340,7 @@ internal class GroupImpl(
 
 
     override operator fun get(id: Long): Member {
-        return members.delegate.filteringGetOrNull { it.id == id } ?: throw NoSuchElementException("for group id $id")
+        return members.delegate.filteringGetOrNull { it.id == id } ?: throw NoSuchElementException("member $id not found in group $uin")
     }
 
     override fun contains(id: Long): Boolean {

From 2e3e7bee2bd7067b285f703f8e81d7001e8c5134 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Fri, 7 Feb 2020 23:18:01 +0800
Subject: [PATCH 2/5] Fix ambiguous function name

---
 .../mirai/qqandroid/io/serialization/Jce.kt   | 108 ++++++------------
 1 file changed, 34 insertions(+), 74 deletions(-)

diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt
index 7104575f0..6b9603584 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/Jce.kt
@@ -390,10 +390,10 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
         }
 
         override fun decodeTaggedNotNullMark(tag: Int): Boolean {
-            return !isTagOptional(tag)
+            return !isTagMissing(tag)
         }
 
-        fun isTagOptional(tag: Int): Boolean {
+        fun isTagMissing(tag: Int): Boolean {
             val head = input.peakHeadOrNull()
             return input.isEndOfInput || head == null || head.tag > tag
         }
@@ -405,10 +405,15 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
             if (deserializer is NullReader) {
                 return null
             }
+            currentTagOrNull?.let {
+                if (this.isTagMissing(it)) {
+                    return null
+                }
+            }
             when (deserializer.descriptor) {
                 ByteArraySerializer.descriptor -> {
                     val tag = popTag()
-                    return if (isTagOptional(tag)) input.readByteArrayOrNull(tag) as? T
+                    return if (isTagMissing(tag)) input.readByteArrayOrNull(tag) as? T
                     else input.readByteArray(tag) as T
                 }
                 is ListLikeDescriptor -> {
@@ -417,14 +422,14 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
                         && (deserializer as ListLikeSerializer<Any?, T, Any?>).typeParams[0] is ByteSerializer
                     ) {
                         val tag = popTag()
-                        return if (isTagOptional(tag)) input.readByteArrayOrNull(tag)?.toTypedArray() as? T
+                        return if (isTagMissing(tag)) input.readByteArrayOrNull(tag)?.toTypedArray() as? T
                         else input.readByteArray(tag).toTypedArray() as T
                     } else if (deserializer is ArrayListSerializer<*>
                         && (deserializer as ArrayListSerializer<*>).typeParams.isNotEmpty()
                         && (deserializer as ArrayListSerializer<*>).typeParams[0] is ByteSerializer
                     ) {
                         val tag = popTag()
-                        return if (isTagOptional(tag)) input.readByteArrayOrNull(tag)?.toMutableList() as? T
+                        return if (isTagMissing(tag)) input.readByteArrayOrNull(tag)?.toMutableList() as? T
                         else input.readByteArray(tag).toMutableList() as T
                     }
                     val tag = currentTag
@@ -433,7 +438,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
                     if (input.skipToTagOrNull(tag) {
                             return deserializer.deserialize(JceListReader(input.readInt(0), input))
                         } == null) {
-                        if (isTagOptional(tag)) {
+                        if (isTagMissing(tag)) {
                             return null
                         } else error("property is notnull but cannot find tag $tag")
                     }
@@ -442,15 +447,15 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
                 is MapLikeDescriptor -> {
                     val tag = popTag()
                     @Suppress("SENSELESS_COMPARISON")
-                    if (input.skipToTagOrNull(tag) {
-                            check(it.type == MAP) { "type mismatch: ${it.type}" }
+                    if (input.skipToTagOrNull(tag) { head ->
+                            check(head.type == MAP) { "type mismatch: ${head.type}" }
                             // 将 mapOf(k1 to v1, k2 to v2, ...) 转换为 listOf(k1, v1, k2, v2, ...) 以便于写入.
                             val serializer = (deserializer as MapLikeSerializer<Any?, Any?, T, *>)
                             val mapEntrySerial = MapEntrySerializer(serializer.keySerializer, serializer.valueSerializer)
                             val setOfEntries = HashSetSerializer(mapEntrySerial).deserialize(JceMapReader(input.readInt(0), input))
                             return setOfEntries.associateBy({ it.key }, { it.value }) as T
                         } == null) {
-                        if (isTagOptional(tag)) {
+                        if (isTagMissing(tag)) {
                             return null
                         } else error("property is notnull but cannot find tag $tag")
                     }
@@ -471,7 +476,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
                                 }
                                 input.readHeadOrNull()
                             }
-                        } == null && isTagOptional(tag)) {
+                        } == null && isTagMissing(tag)) {
                         return null
                     } else error("cannot find tag $tag")
                 }
@@ -480,8 +485,13 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
             }
 
             val tag = currentTagOrNull ?: return deserializer.deserialize(JceDecoder(this.input))
-            return if (this.decodeTaggedNotNullMark(tag)) {
-                deserializer.deserialize(this)
+            return if (!this.isTagMissing(tag)) {
+                try {
+                    deserializer.deserialize(this)
+                } catch (e: Exception) {
+                    println("exception when tag=$tag")
+                    throw e
+                }
             } else {
                 // popTag()
                 null
@@ -502,7 +512,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
         internal val input: ByteReadPacket,
         maxReadSize: Long = input.remaining
     ) : Closeable {
-        internal val leastRemaining = input.remaining - maxReadSize
+        private val leastRemaining = input.remaining - maxReadSize
         internal val isEndOfInput: Boolean get() = input.remaining <= leastRemaining
 
         internal var currentJceHead: JceHead? = input.doReadHead()
@@ -510,7 +520,6 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
         override fun close() = input.close()
 
         internal fun peakHeadOrNull(): JceHead? = currentJceHead ?: readHeadOrNull()
-        internal fun peakHead(): JceHead = peakHeadOrNull() ?: error("no enough data to read head")
 
         @PublishedApi
         internal fun readHead(): JceHead = readHeadOrNull() ?: error("no enough data to read head")
@@ -554,43 +563,6 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
         fun readString(tag: Int): String = readStringOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
 
         fun readByteArray(tag: Int): ByteArray = readByteArrayOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
-        fun readShortArray(tag: Int): ShortArray = readShortArrayOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
-        fun readLongArray(tag: Int): LongArray = readLongArrayOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
-        fun readFloatArray(tag: Int): FloatArray = readFloatArrayOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
-        fun readDoubleArray(tag: Int): DoubleArray = readDoubleArrayOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
-        fun readIntArray(tag: Int): IntArray = readIntArrayOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
-        fun readBooleanArray(tag: Int): BooleanArray = readBooleanArrayOrNull(tag) ?: error("cannot find tag $tag, currentJceHead=$currentJceHead")
-
-
-        fun readShortArrayOrNull(tag: Int): ShortArray? = skipToTagOrNull(tag) {
-            require(it.type.toInt() == 9) { "type mismatch, expected=9(List), got=${it.type}" }
-            ShortArray(readInt(0)) { readShort(0) }
-        }
-
-        fun readDoubleArrayOrNull(tag: Int): DoubleArray? = skipToTagOrNull(tag) {
-            require(it.type.toInt() == 9) { "type mismatch, expected=9(List), got=${it.type}" }
-            DoubleArray(readInt(0)) { readDouble(0) }
-        }
-
-        fun readFloatArrayOrNull(tag: Int): FloatArray? = skipToTagOrNull(tag) {
-            require(it.type.toInt() == 9) { "type mismatch, expected=9(List), got=${it.type}" }
-            FloatArray(readInt(0)) { readFloat(0) }
-        }
-
-        fun readIntArrayOrNull(tag: Int): IntArray? = skipToTagOrNull(tag) {
-            require(it.type.toInt() == 9) { "type mismatch, expected=9(List), got=${it.type}" }
-            IntArray(readInt(0)) { readInt(0) }
-        }
-
-        fun readLongArrayOrNull(tag: Int): LongArray? = skipToTagOrNull(tag) {
-            require(it.type.toInt() == 9) { "type mismatch, expected=9(List), got=${it.type}" }
-            LongArray(readInt(0)) { readLong(0) }
-        }
-
-        fun readBooleanArrayOrNull(tag: Int): BooleanArray? = skipToTagOrNull(tag) {
-            require(it.type.toInt() == 9) { "type mismatch, expected=9(List), got=${it.type}" }
-            BooleanArray(readInt(0)) { readBoolean(0) }
-        }
 
         fun readByteArrayOrNull(tag: Int): ByteArray? = skipToTagOrNull(tag) {
             when (it.type) {
@@ -605,20 +577,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
             }
         }
 
-        @Suppress("IMPLICIT_CAST_TO_ANY", "UNCHECKED_CAST")
-        fun <T> readObject(default: T, tag: Int): T = when (default) {
-            is Byte -> readByte(tag)
-            is Boolean -> readBoolean(tag)
-            is Short -> readShort(tag)
-            is Int -> readInt(tag)
-            is Long -> readLong(tag)
-            is Float -> readFloat(tag)
-            is Double -> readDouble(tag)
-            is String -> readString(tag)
-            else -> error("unsupported type: ${default.getClassName()}")
-        } as T
-
-        fun readStringOrNull(tag: Int): String? = skipToTagOrNull(tag) { head ->
+        private fun readStringOrNull(tag: Int): String? = skipToTagOrNull(tag) { head ->
             return when (head.type) {
                 STRING1 -> input.readString(input.readUByte().toInt(), charset = charset.kotlinCharset)
                 STRING4 -> input.readString(
@@ -629,7 +588,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
             }
         }
 
-        fun readLongOrNull(tag: Int): Long? = skipToTagOrNull(tag) {
+        private fun readLongOrNull(tag: Int): Long? = skipToTagOrNull(tag) {
             return when (it.type) {
                 ZERO_TYPE -> 0
                 BYTE -> input.readByte().toLong()
@@ -640,7 +599,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
             }
         }
 
-        fun readShortOrNull(tag: Int): Short? = skipToTagOrNull(tag) {
+        private fun readShortOrNull(tag: Int): Short? = skipToTagOrNull(tag) {
             return when (it.type.toInt()) {
                 12 -> 0
                 0 -> input.readByte().toShort()
@@ -649,7 +608,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
             }
         }
 
-        fun readIntOrNull(tag: Int): Int? = skipToTagOrNull(tag) {
+        private fun readIntOrNull(tag: Int): Int? = skipToTagOrNull(tag) {
             return when (it.type.toInt()) {
                 12 -> 0
                 0 -> input.readByte().toInt()
@@ -659,7 +618,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
             }
         }
 
-        fun readByteOrNull(tag: Int): Byte? = skipToTagOrNull(tag) {
+        private fun readByteOrNull(tag: Int): Byte? = skipToTagOrNull(tag) {
             return when (it.type.toInt()) {
                 12 -> 0
                 0 -> input.readByte()
@@ -667,7 +626,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
             }
         }
 
-        fun readFloatOrNull(tag: Int): Float? = skipToTagOrNull(tag) {
+        private fun readFloatOrNull(tag: Int): Float? = skipToTagOrNull(tag) {
             return when (it.type.toInt()) {
                 12 -> 0f
                 4 -> input.readFloat()
@@ -675,7 +634,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
             }
         }
 
-        fun readDoubleOrNull(tag: Int): Double? = skipToTagOrNull(tag) {
+        private fun readDoubleOrNull(tag: Int): Double? = skipToTagOrNull(tag) {
             return when (it.type.toInt()) {
                 12 -> 0.0
                 4 -> input.readFloat().toDouble()
@@ -684,7 +643,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
             }
         }
 
-        fun readBooleanOrNull(tag: Int): Boolean? = this.readByteOrNull(tag)?.let { it.toInt() != 0 }
+        private fun readBooleanOrNull(tag: Int): Boolean? = this.readByteOrNull(tag)?.let { it.toInt() != 0 }
 
 
         private fun skipField() {
@@ -734,6 +693,7 @@ class Jce private constructor(private val charset: JceCharset, context: SerialMo
 
     }
 
+    @Suppress("MemberVisibilityCanBePrivate")
     companion object {
         val UTF8 = Jce(JceCharset.UTF8)
         val GBK = Jce(JceCharset.GBK)
@@ -816,9 +776,9 @@ internal inline fun <R> Jce.JceInput.skipToTagOrNull(tag: Int, block: (JceHead)
             currentJceHead = null
             // println("skipping to $tag: run block")
             return block(head)
-        } else {
-            // println("skipping to $tag: tag not matching")
         }
+
+        // println("skipping to $tag: tag not matching")
         // println("skipping to $tag: skipField")
         this.skipField(head.type)
         currentJceHead = readHeadOrNull()

From ca43cf689c11774a9af674282a03ed95f7515cd4 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Fri, 7 Feb 2020 23:18:12 +0800
Subject: [PATCH 3/5] Remove data modifier

---
 .../mirai/qqandroid/network/protocol/data/jce/PushNotifyPack.kt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/PushNotifyPack.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/PushNotifyPack.kt
index f54a42d94..2ed9f013a 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/PushNotifyPack.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/jce/PushNotifyPack.kt
@@ -27,7 +27,7 @@ internal data class RequestPushNotify(
 
 @Suppress("ArrayInDataClass")
 @Serializable
-internal data class MsgInfo(
+internal class MsgInfo(
     @SerialId(0) val lFromUin: Long? = 0L,
     @SerialId(1) val uMsgTime: Long? = 0L,
     @SerialId(2) val shMsgType: Short,

From 68d86a924f5f3a364ce1aa818e01939a4bb9479a Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Fri, 7 Feb 2020 23:18:32 +0800
Subject: [PATCH 4/5] Introduce _ vars

---
 .../net/mamoe/mirai/qqandroid/ContactImpl.kt  | 213 ++++++++++--------
 1 file changed, 118 insertions(+), 95 deletions(-)

diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
index ef6263804..63bf59248 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
@@ -20,7 +20,6 @@ import net.mamoe.mirai.qqandroid.utils.toIpV4AddressString
 import net.mamoe.mirai.utils.*
 import net.mamoe.mirai.utils.io.toUHexString
 import kotlin.coroutines.CoroutineContext
-import kotlin.properties.Delegates
 
 internal abstract class ContactImpl : Contact {
     override fun hashCode(): Int {
@@ -51,6 +50,7 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin
             ) { "send message failed" }
         }
     }
+
     override suspend fun uploadImage(image: ExternalImage): Image = try {
         bot.network.run {
             val response = LongConn.OffPicUp(
@@ -129,8 +129,8 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin
 
 internal class MemberImpl(
     qq: QQImpl,
-    initGroupCard: String,
-    initSpecialTitle: String,
+    var _groupCard: String,
+    var _specialTitle: String,
     group: GroupImpl,
     override val coroutineContext: CoroutineContext,
     override val permission: MemberPermission
@@ -138,37 +138,41 @@ internal class MemberImpl(
     override val group: GroupImpl by group.unsafeWeakRef()
     val qq: QQImpl by qq.unsafeWeakRef()
 
-
-    override var groupCard: String by Delegates.observable(initGroupCard) { _, old, new ->
-        group.checkBotPermissionOperator()
-        if (new != old) {
-
-            launch {
-                bot.network.run {
-                    TroopManagement.EditGroupNametag(
-                        bot.client,
-                        this@MemberImpl,
-                        new
-                    ).sendWithoutExpect()
+    override var groupCard: String
+        get() = _groupCard
+        set(newValue) {
+            group.checkBotPermissionOperator()
+            if (_groupCard != newValue) {
+                _groupCard = newValue
+                launch {
+                    bot.network.run {
+                        TroopManagement.EditGroupNametag(
+                            bot.client,
+                            this@MemberImpl,
+                            newValue
+                        ).sendWithoutExpect()
+                    }
                 }
             }
         }
-    }
 
-    override var specialTitle: String by Delegates.observable(initSpecialTitle) { _, old, new ->
-        group.checkBotPermissionOperator()
-        if (new != old) {
-            launch {
-                bot.network.run {
-                    TroopManagement.EditSpecialTitle(
-                        bot.client,
-                        this@MemberImpl,
-                        new
-                    ).sendWithoutExpect()
+    override var specialTitle: String
+        get() = _specialTitle
+        set(newValue) {
+            group.checkBotPermissionOperator()
+            if (_specialTitle != newValue) {
+                _specialTitle = newValue
+                launch {
+                    bot.network.run {
+                        TroopManagement.EditSpecialTitle(
+                            bot.client,
+                            this@MemberImpl,
+                            newValue
+                        ).sendWithoutExpect()
+                    }
                 }
             }
         }
-    }
 
     override val bot: QQAndroidBot get() = qq.bot
 
@@ -233,100 +237,119 @@ internal class GroupImpl(
     bot: QQAndroidBot, override val coroutineContext: CoroutineContext,
     override val id: Long,
     val uin: Long,
-    initName: String,
-    initAnnouncement: String,
-    initAllowMemberInvite: Boolean,
-    initConfessTalk: Boolean,
-    initMuteAll: Boolean,
-    initAutoApprove: Boolean,
-    initAnonymousChat: Boolean,
+    var _name: String,
+    var _announcement: String,
+    var _allowMemberInvite: Boolean,
+    var _confessTalk: Boolean,
+    var _muteAll: Boolean,
+    var _autoApprove: Boolean,
+    var _anonymousChat: Boolean,
     override val members: ContactList<Member>
 ) : ContactImpl(), Group {
 
-    override var name by Delegates.observable(initName) { _, oldValue, newValue ->
-        this.checkBotPermissionOperator()
-        if (oldValue != newValue) {
-            launch {
-                bot.network.run {
-                    TroopManagement.GroupOperation.name(
-                        client = bot.client,
-                        groupCode = id,
-                        newName = newValue
-                    ).sendWithoutExpect()
+    override var name: String
+        get() = _name
+        set(newValue) {
+            this.checkBotPermissionOperator()
+            if (_name != newValue) {
+                _name = newValue
+                launch {
+                    bot.network.run {
+                        TroopManagement.GroupOperation.name(
+                            client = bot.client,
+                            groupCode = id,
+                            newName = newValue
+                        ).sendWithoutExpect()
+                    }
                 }
             }
         }
-    }
 
-    override var announcement: String by Delegates.observable(initAnnouncement) { _, oldValue, newValue ->
-        this.checkBotPermissionOperator()
-        if (oldValue != newValue) {
-            launch {
-                bot.network.run {
-                    TroopManagement.GroupOperation.memo(
-                        client = bot.client,
-                        groupCode = id,
-                        newMemo = newValue
-                    ).sendWithoutExpect()
+    override var announcement: String
+        get() = _announcement
+        set(newValue) {
+            this.checkBotPermissionOperator()
+            if (_announcement != newValue) {
+                _announcement = newValue
+                launch {
+                    bot.network.run {
+                        TroopManagement.GroupOperation.memo(
+                            client = bot.client,
+                            groupCode = id,
+                            newMemo = newValue
+                        ).sendWithoutExpect()
+                    }
                 }
             }
         }
-    }
 
 
-    override var allowMemberInvite: Boolean by Delegates.observable(initAllowMemberInvite) { _, oldValue, newValue ->
-        this.checkBotPermissionOperator()
-        if (oldValue != newValue) {
-            launch {
-                bot.network.run {
-                    TroopManagement.GroupOperation.allowMemberInvite(
-                        client = bot.client,
-                        groupCode = id,
-                        switch = newValue
-                    ).sendWithoutExpect()
+    override var allowMemberInvite: Boolean
+        get() = _allowMemberInvite
+        set(newValue) {
+            this.checkBotPermissionOperator()
+            if (_allowMemberInvite != newValue) {
+                _allowMemberInvite = newValue
+                launch {
+                    bot.network.run {
+                        TroopManagement.GroupOperation.allowMemberInvite(
+                            client = bot.client,
+                            groupCode = id,
+                            switch = newValue
+                        ).sendWithoutExpect()
+                    }
                 }
             }
         }
-    }
 
-    override var autoApprove: Boolean by Delegates.observable(initAutoApprove) { _, oldValue, newValue ->
-        TODO("Group.autoApprove implementation")
-    }
+    override var autoApprove: Boolean
+        get() = _autoApprove
+        set(newValue) {
+            TODO()
+        }
 
-    override val anonymousChat: Boolean by Delegates.observable(initAnonymousChat) { _, oldValue, newValue ->
-        TODO("Group.anonymousChat implementation")
-    }
+    override var anonymousChat: Boolean
+        get() = _anonymousChat
+        set(newValue) {
+            TODO()
+        }
 
-    override var confessTalk: Boolean by Delegates.observable(initConfessTalk) { _, oldValue, newValue ->
-        this.checkBotPermissionOperator()
-        if (oldValue != newValue) {
-            launch {
-                bot.network.run {
-                    TroopManagement.GroupOperation.confessTalk(
-                        client = bot.client,
-                        groupCode = id,
-                        switch = newValue
-                    ).sendWithoutExpect()
+    override var confessTalk: Boolean
+        get() = _confessTalk
+        set(newValue) {
+            this.checkBotPermissionOperator()
+            if (_confessTalk != newValue) {
+                _confessTalk = newValue
+                launch {
+                    bot.network.run {
+                        TroopManagement.GroupOperation.confessTalk(
+                            client = bot.client,
+                            groupCode = id,
+                            switch = newValue
+                        ).sendWithoutExpect()
+                    }
                 }
             }
         }
-    }
 
 
-    override var muteAll: Boolean by Delegates.observable(initMuteAll) { _, oldValue, newValue ->
-        this.checkBotPermissionOperator()
-        if (oldValue != newValue) {
-            launch {
-                bot.network.run {
-                    TroopManagement.GroupOperation.muteAll(
-                        client = bot.client,
-                        groupCode = id,
-                        switch = newValue
-                    ).sendWithoutExpect()
+    override var muteAll: Boolean
+        get() = _muteAll
+        set(newValue) {
+            this.checkBotPermissionOperator()
+            if (_muteAll != newValue) {
+                _muteAll = newValue
+                launch {
+                    bot.network.run {
+                        TroopManagement.GroupOperation.muteAll(
+                            client = bot.client,
+                            groupCode = id,
+                            switch = newValue
+                        ).sendWithoutExpect()
+                    }
                 }
             }
         }
-    }
 
 
     override lateinit var owner: Member

From 13d6bd29d4d1f7987a517c49bd28906ecdf61fd8 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Fri, 7 Feb 2020 23:35:07 +0800
Subject: [PATCH 5/5] Fix build

---
 .../network/QQAndroidBotNetworkHandler.kt      | 18 +++++++++---------
 .../main/kotlin/demo/gentleman/GentleImage.kt  |  2 +-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
index c04e46fca..9a7a8b0ec 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
@@ -185,13 +185,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
                             coroutineContext = bot.coroutineContext,
                             id = troopNum.groupCode,
                             uin = troopNum.groupUin,
-                            initName = troopNum.groupName,
-                            initAnnouncement = troopNum.groupMemo,
-                            initAllowMemberInvite = groupInfoResponse.allowMemberInvite,
-                            initConfessTalk = groupInfoResponse.confessTalk,
-                            initMuteAll = troopNum.dwShutUpTimestamp != 0L,
-                            initAutoApprove = groupInfoResponse.autoApprove,
-                            initAnonymousChat = groupInfoResponse.allowAnonymousChat,
+                            _name = troopNum.groupName,
+                            _announcement = troopNum.groupMemo,
+                            _allowMemberInvite = groupInfoResponse.allowMemberInvite,
+                            _confessTalk = groupInfoResponse.confessTalk,
+                            _muteAll = troopNum.dwShutUpTimestamp != 0L,
+                            _autoApprove = groupInfoResponse.autoApprove,
+                            _anonymousChat = groupInfoResponse.allowAnonymousChat,
                             members = contactList
                         )
                     toGet[group] = contactList
@@ -260,8 +260,8 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
             data.members.forEach {
                 val member = MemberImpl(
                     qq = bot.QQ(it.memberUin) as QQImpl,
-                    initGroupCard = it.autoRemark ?: it.nick,
-                    initSpecialTitle = it.sSpecialTitle ?: "",
+                    _groupCard = it.autoRemark ?: it.nick,
+                    _specialTitle = it.sSpecialTitle ?: "",
                     group = group,
                     coroutineContext = group.coroutineContext,
                     permission = when {
diff --git a/mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/GentleImage.kt b/mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/GentleImage.kt
index 159faa52f..ca9d056dc 100644
--- a/mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/GentleImage.kt
+++ b/mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/GentleImage.kt
@@ -33,7 +33,7 @@ class GentleImage(val contact: Contact, val keyword: String) {
                     )
 
                     val result =
-                        Json.plain.parse(
+                        Json.nonstrict.parse(
                             Result.serializer(),
                             Jsoup.connect("https://api.lolicon.app/setu/?r18=$r18" + if (keyword.isNotBlank()) "&keyword=$keyword&num=10" else "")
                                 .ignoreContentType(true)