mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-26 20:20:14 +08:00
[core] feat: Announcement confirmed member api (#2255)
* feat: Announcement confirmed * add: native * add: todo * fix: dump
This commit is contained in:
parent
a77c4e2adf
commit
1c79da0f38
@ -844,8 +844,10 @@ public abstract interface class net/mamoe/mirai/contact/announcement/Announcemen
|
||||
public abstract fun delete (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun get (Ljava/lang/String;)Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;
|
||||
public abstract fun get (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun members (Ljava/lang/String;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun publish (Lnet/mamoe/mirai/contact/announcement/Announcement;)Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;
|
||||
public abstract fun publish (Lnet/mamoe/mirai/contact/announcement/Announcement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun remind (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/contact/announcement/AnnouncementImage;
|
||||
public abstract fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
}
|
||||
@ -886,6 +888,12 @@ public abstract interface class net/mamoe/mirai/contact/announcement/OnlineAnnou
|
||||
public abstract fun getPublicationTime ()J
|
||||
public abstract fun getSender ()Lnet/mamoe/mirai/contact/NormalMember;
|
||||
public abstract fun getSenderId ()J
|
||||
public fun members (Z)Ljava/util/List;
|
||||
public fun members (ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun members$suspendImpl (Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun remind ()V
|
||||
public fun remind (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun remind$suspendImpl (Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/contact/announcement/OnlineAnnouncementKt {
|
||||
|
@ -844,8 +844,10 @@ public abstract interface class net/mamoe/mirai/contact/announcement/Announcemen
|
||||
public abstract fun delete (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun get (Ljava/lang/String;)Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;
|
||||
public abstract fun get (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun members (Ljava/lang/String;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun publish (Lnet/mamoe/mirai/contact/announcement/Announcement;)Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;
|
||||
public abstract fun publish (Lnet/mamoe/mirai/contact/announcement/Announcement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public abstract fun remind (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;)Lnet/mamoe/mirai/contact/announcement/AnnouncementImage;
|
||||
public abstract fun uploadImage (Lnet/mamoe/mirai/utils/ExternalResource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
}
|
||||
@ -886,6 +888,12 @@ public abstract interface class net/mamoe/mirai/contact/announcement/OnlineAnnou
|
||||
public abstract fun getPublicationTime ()J
|
||||
public abstract fun getSender ()Lnet/mamoe/mirai/contact/NormalMember;
|
||||
public abstract fun getSenderId ()J
|
||||
public fun members (Z)Ljava/util/List;
|
||||
public fun members (ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun members$suspendImpl (Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public fun remind ()V
|
||||
public fun remind (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static synthetic fun remind$suspendImpl (Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class net/mamoe/mirai/contact/announcement/OnlineAnnouncementKt {
|
||||
|
@ -12,6 +12,7 @@ package net.mamoe.mirai.contact.announcement
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.NormalMember
|
||||
import net.mamoe.mirai.contact.PermissionDeniedException
|
||||
import net.mamoe.mirai.utils.DeprecatedSinceMirai
|
||||
import net.mamoe.mirai.utils.ExternalResource
|
||||
@ -84,6 +85,31 @@ public interface Announcements : Streamable<OnlineAnnouncement> {
|
||||
@JvmBlockingBridge
|
||||
public suspend fun uploadImage(resource: ExternalResource): AnnouncementImage
|
||||
|
||||
/**
|
||||
* 获取 已确认/未确认 的群成员
|
||||
*
|
||||
* @param fid 公告的 [OnlineAnnouncement.fid]
|
||||
* @param confirmed 是否确认
|
||||
* @return 群成员列表
|
||||
*
|
||||
* @throws PermissionDeniedException 当没有权限时抛出
|
||||
* @throws IllegalStateException 当协议异常时抛出
|
||||
*
|
||||
* @see OnlineAnnouncement.members
|
||||
*/
|
||||
public suspend fun members(fid: String, confirmed: Boolean): List<NormalMember>
|
||||
|
||||
/**
|
||||
* 提醒 未确认 的群成员
|
||||
*
|
||||
* @param fid 公告的 [OnlineAnnouncement.fid]
|
||||
*
|
||||
* @throws PermissionDeniedException 当没有权限时抛出
|
||||
* @throws IllegalStateException 当协议异常时抛出
|
||||
*
|
||||
* @see OnlineAnnouncement.remind
|
||||
*/
|
||||
public suspend fun remind(fid: String)
|
||||
|
||||
// no blocking bridge for this method
|
||||
@Suppress("INAPPLICABLE_JVM_NAME")
|
||||
|
@ -77,6 +77,29 @@ public interface OnlineAnnouncement : Announcement {
|
||||
* @see Announcements.delete
|
||||
*/
|
||||
public suspend fun delete(): Boolean = group.announcements.delete(fid)
|
||||
|
||||
/**
|
||||
* 获取 已确认/未确认 的群成员
|
||||
*
|
||||
* @param confirmed 是否确认
|
||||
* @return 群成员列表
|
||||
*
|
||||
* @throws PermissionDeniedException 当没有权限时抛出
|
||||
* @throws IllegalStateException 当协议异常时抛出
|
||||
*
|
||||
* @see Announcements.members
|
||||
*/
|
||||
public suspend fun members(confirmed: Boolean): List<NormalMember> = group.announcements.members(fid, confirmed)
|
||||
|
||||
/**
|
||||
* 提醒 未确认 的群成员
|
||||
*
|
||||
* @throws PermissionDeniedException 当没有权限时抛出
|
||||
* @throws IllegalStateException 当协议异常时抛出
|
||||
*
|
||||
* @see Announcements.remind
|
||||
*/
|
||||
public suspend fun remind(): Unit = group.announcements.remind(fid)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,4 +92,18 @@ internal class MockAnnouncementsImpl(
|
||||
override suspend fun uploadImage(resource: ExternalResource): AnnouncementImage = resource.inResource {
|
||||
AnnouncementImage.create(generateImageId(resource.md5), 500, 500)
|
||||
}
|
||||
|
||||
override suspend fun members(fid: String, confirmed: Boolean): List<NormalMember> {
|
||||
if (!group.botPermission.isOperator()) {
|
||||
throw PermissionDeniedException("Only administrator have permission see announcement confirmed detail")
|
||||
}
|
||||
// TODO: 设置用户可读状态,而不返回全部
|
||||
return group.members.toList()
|
||||
}
|
||||
|
||||
override suspend fun remind(fid: String) {
|
||||
if (!group.botPermission.isOperator()) {
|
||||
throw PermissionDeniedException("Only administrator have permission send announcement remind")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,20 +14,25 @@ import io.ktor.client.request.forms.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.contact.NormalMember
|
||||
import net.mamoe.mirai.contact.announcement.*
|
||||
import net.mamoe.mirai.contact.checkBotPermission
|
||||
import net.mamoe.mirai.internal.AbstractBot
|
||||
import net.mamoe.mirai.internal.QQAndroidBot
|
||||
import net.mamoe.mirai.internal.contact.GroupImpl
|
||||
import net.mamoe.mirai.internal.contact.OnlineAnnouncementImpl
|
||||
import net.mamoe.mirai.internal.contact.active.defaultJson
|
||||
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.deleteGroupAnnouncement
|
||||
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.getGroupAnnouncement
|
||||
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.getRawGroupAnnouncements
|
||||
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.getReadDetail
|
||||
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.sendGroupAnnouncement
|
||||
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.sendRemind
|
||||
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.toAnnouncement
|
||||
import net.mamoe.mirai.internal.contact.announcement.AnnouncementProtocol.toGroupAnnouncement
|
||||
import net.mamoe.mirai.internal.message.contextualBugReportException
|
||||
@ -140,6 +145,17 @@ internal abstract class CommonAnnouncementsImpl(
|
||||
AnnouncementProtocol.uploadGroupAnnouncementImage(bot, resource)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun members(fid: String, confirmed: Boolean): List<NormalMember> {
|
||||
group.checkBotPermission(MemberPermission.ADMINISTRATOR) { "Only administrator have permission see announcement confirmed detail" }
|
||||
val detail = bot.getReadDetail(groupId = group.id, fid = fid, read = confirmed)
|
||||
return detail.users.mapNotNull { user -> group[user.uin] }
|
||||
}
|
||||
|
||||
override suspend fun remind(fid: String) {
|
||||
group.checkBotPermission(MemberPermission.ADMINISTRATOR) { "Only administrator have permission send announcement remind" }
|
||||
bot.sendRemind(groupId = group.id, fid = fid)
|
||||
}
|
||||
}
|
||||
|
||||
private val serversStub = listOf("web.qun.qq.com" to 80)
|
||||
@ -296,6 +312,50 @@ internal object AnnouncementProtocol {
|
||||
append("format", "json")
|
||||
})
|
||||
|
||||
private fun <T> CgiData.loadData(serializer: KSerializer<T>): T =
|
||||
defaultJson.decodeFromJsonElement(serializer, this.data)
|
||||
|
||||
suspend fun QQAndroidBot.getReadDetail(groupId: Long, fid: String, read: Boolean): GroupAnnouncementReadDetail {
|
||||
val cgi = bot.components[HttpClientProvider].getHttpClient().post {
|
||||
url("https://qun.qq.com/cgi-bin/qunapp/announce_unread")
|
||||
parameter("gc", groupId)
|
||||
parameter("start", 0)
|
||||
parameter("num", 3000)
|
||||
parameter("feed_id", fid)
|
||||
parameter("type", if (read) 1 else 0)
|
||||
parameter("bkn", client.wLoginSigInfo.bkn)
|
||||
headers {
|
||||
// ktor bug
|
||||
append(
|
||||
"cookie",
|
||||
"uin=o${id}; skey=${sKey}; p_uin=o${id}; p_skey=${psKey("qun.qq.com")};"
|
||||
)
|
||||
}
|
||||
}.bodyAsText().loadAs(CgiData.serializer())
|
||||
check(cgi.cgicode == 0) { cgi.errorMessage }
|
||||
return cgi.loadData(GroupAnnouncementReadDetail.serializer())
|
||||
}
|
||||
|
||||
suspend fun QQAndroidBot.sendRemind(groupId: Long, fid: String) {
|
||||
val cgi = bot.components[HttpClientProvider].getHttpClient().post {
|
||||
url("https://qun.qq.com/cgi-bin/qunapp/announce_remindread")
|
||||
parameter("gc", groupId)
|
||||
parameter("feed_id", fid)
|
||||
parameter("bkn", client.wLoginSigInfo.bkn)
|
||||
headers {
|
||||
// ktor bug
|
||||
append(
|
||||
"cookie",
|
||||
"uin=o${id}; skey=${sKey}; p_uin=o${id}; p_skey=${psKey("qun.qq.com")};"
|
||||
)
|
||||
}
|
||||
}.bodyAsText().loadAs(CgiData.serializer())
|
||||
// 14 "该公告不存在"
|
||||
// 54016 "该公告已提醒多次,不可再提醒。"
|
||||
// 54010 "提醒太频繁,请稍后再试"
|
||||
check(cgi.cgicode == 0) { cgi.errorMessage }
|
||||
}
|
||||
|
||||
fun Announcement.toGroupAnnouncement(senderId: Long): GroupAnnouncement {
|
||||
return GroupAnnouncement(
|
||||
sender = senderId,
|
||||
|
@ -13,6 +13,7 @@ package net.mamoe.mirai.internal.contact.announcement
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import net.mamoe.mirai.contact.announcement.AnnouncementImage
|
||||
import net.mamoe.mirai.utils.CheckableResponseA
|
||||
import net.mamoe.mirai.utils.JsonStruct
|
||||
@ -78,3 +79,26 @@ internal data class GroupAnnouncementSettings(
|
||||
val DEFAULT = GroupAnnouncementSettings()
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
internal data class CgiData(
|
||||
@SerialName("cgicode") val cgicode: Int,
|
||||
@SerialName("data") val `data`: JsonElement,
|
||||
@SerialName("msg") override val errorMessage: String,
|
||||
@SerialName("retcode") override val errorCode: Int
|
||||
) : CheckableResponseA(), JsonStruct
|
||||
|
||||
@Serializable
|
||||
internal data class GroupAnnouncementReadDetail(
|
||||
@SerialName("read_total") val readTotal: Int = 0,
|
||||
@SerialName("unread_total") val unreadTotal: Int = 0,
|
||||
@SerialName("users") val users: List<User> = emptyList()
|
||||
) {
|
||||
@Serializable
|
||||
data class User(
|
||||
@SerialName("avatar") val avatar: String,
|
||||
@SerialName("display_name") val displayName: String,
|
||||
@SerialName("face_flag") val faceFlag: Int,
|
||||
@SerialName("uin") val uin: Long
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user