diff --git a/mirai-core-qqandroid/build.gradle.kts b/mirai-core-qqandroid/build.gradle.kts index 8179cd718..644956ee7 100644 --- a/mirai-core-qqandroid/build.gradle.kts +++ b/mirai-core-qqandroid/build.gradle.kts @@ -72,6 +72,11 @@ kotlin { api(kotlinx("io", kotlinXIoVersion)) api(kotlinx("coroutines-io", coroutinesIoVersion)) api(kotlinx("coroutines-core", coroutinesVersion)) + + api(ktor("client-core", ktorVersion)) + + implementation(ktor("client-json",ktorVersion)) + implementation(ktor("client-serialization",ktorVersion)) } } commonMain { @@ -110,6 +115,7 @@ kotlin { runtimeOnly(files("build/classes/kotlin/jvm/main")) // classpath is not properly set by IDE api(kotlinx("serialization-runtime", serializationVersion)) //api(kotlinx("serialization-protobuf", serializationVersion)) + } } 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 d67a04053..55dc4f0ba 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 @@ -9,6 +9,12 @@ package net.mamoe.mirai.qqandroid +import io.ktor.client.HttpClient +import io.ktor.client.features.json.JsonFeature +import io.ktor.client.features.json.serializer.KotlinxSerializer +import io.ktor.client.request.* +import io.ktor.client.request.forms.formData +import kotlinx.coroutines.async import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeoutOrNull import kotlinx.io.core.Closeable @@ -35,6 +41,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.LongConn import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc import net.mamoe.mirai.qqandroid.utils.toIpV4AddressString import net.mamoe.mirai.utils.* +import net.mamoe.mirai.utils.io.encodeToString import net.mamoe.mirai.utils.io.toUHexString import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract @@ -559,6 +566,29 @@ internal class GroupImpl( TODO("not implemented") } + @MiraiExperimentalAPI + override suspend fun getAnnouncements(page: Int, amount: Int): GroupAnnouncementList { + val data = bot.network.async { + HttpClient { install(JsonFeature) { serializer = KotlinxSerializer() } }.post { + url("https://web.qun.qq.com/cgi-bin/announce/list_announce") + formData { + append("qid", id) + append("bkn", getBkn()) + append("ft", 23) //好像是一个用来识别应用的参数 + append("s", -page) // 第一页这里的参数应该是-1 + append("n", amount) + append("format", "json") + } + header( + "cookie", + "uin=o${bot.selfQQ.id}; skey=${bot.client.wLoginSigInfo.sKey.data.encodeToString()}; p_uin=o${bot.selfQQ.id};" + ) + } + } + return data.await() + } + + @OptIn(MiraiExperimentalAPI::class) override fun Member(memberInfo: MemberInfo): Member { return MemberImpl( @@ -719,4 +749,16 @@ internal class GroupImpl( if (this::class != other::class) return false return this.id == other.id && this.bot == other.bot } + + /* + * 获取 获取群公告 所需的bkn参数 + * */ + fun getBkn(): Int { + val str = bot.client.wLoginSigInfo.sKey.data.encodeToString() + var magic = 5381 + for (i in str) { + magic += magic.shl(5) + i.toInt() + } + return Int.MAX_VALUE.and(magic) + } } \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt index 5b7365394..d15683d68 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/WtLogin.kt @@ -602,6 +602,7 @@ internal class WtLogin { userA5 = UserA5(tlvMap119.getOrEmpty(0x10b), creationTime), userA8 = UserA8(tlvMap119.getOrEmpty(0x102), creationTime, expireTime) ) + //bot.network.logger.error(client.wLoginSigInfo.sKey.data.encodeToString()) } } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt index 15c7e97d7..88e05cbd6 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt @@ -12,7 +12,11 @@ package net.mamoe.mirai.contact import kotlinx.coroutines.CoroutineScope +import kotlinx.serialization.SerialInfo +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable import net.mamoe.mirai.Bot +import net.mamoe.mirai.data.GroupAnnouncementList import net.mamoe.mirai.data.MemberInfo import net.mamoe.mirai.event.events.* import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent @@ -148,6 +152,13 @@ expect abstract class Group() : Contact, CoroutineScope { */ abstract operator fun contains(id: Long): Boolean + /** + * 获取群公告列表 + * + * */ + @MiraiExperimentalAPI + abstract suspend fun getAnnouncements(page: Int = 1, amount: Int = 10):GroupAnnouncementList + /** * 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败 */ diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/GroupAnnouncement.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/GroupAnnouncement.kt new file mode 100644 index 000000000..9bd272d37 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/GroupAnnouncement.kt @@ -0,0 +1,36 @@ +package net.mamoe.mirai.data + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * 群公告数据类 + * + * + */ +@Serializable +data class GroupAnnouncementList( + val feeds: List +) + +@Serializable +data class GroupAnnouncement( + @SerialName("u") val sender: Long, + val msg: GroupAnnouncementMsg, + val settings: GroupAnnouncementSettings +) + +@Serializable +data class GroupAnnouncementMsg( + val text: String, + val text_face: String, + val title: String +) + +@Serializable +data class GroupAnnouncementSettings( + @SerialName("is_show_edit_card") val isShowEditCard: Int, + @SerialName("remind_ts") val remindTs: Int, + @SerialName("tip_window_type") val tipWindowType: Int, + @SerialName("confirm_required") val confirmRequired: Int +) \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Group.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Group.kt index c1a6d1c21..025754431 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Group.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/Group.kt @@ -11,6 +11,7 @@ package net.mamoe.mirai.contact import kotlinx.coroutines.CoroutineScope import net.mamoe.mirai.Bot +import net.mamoe.mirai.data.GroupAnnouncementList import net.mamoe.mirai.data.MemberInfo import net.mamoe.mirai.event.events.* import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent @@ -146,6 +147,14 @@ actual abstract class Group : Contact(), CoroutineScope { */ actual abstract fun getOrNull(id: Long): Member? + + /** + * 获取群公告列表 + * + * */ + @MiraiExperimentalAPI + actual suspend abstract fun getAnnouncements(page: Int, amount: Int ):GroupAnnouncementList + /** * 检查此 id 的群成员是否存在 */