Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: essence message setting #2314

Merged
merged 19 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions mirai-core-api/compatibility-validation/android/api/android.api
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutin
public abstract fun getBotAsMember ()Lnet/mamoe/mirai/contact/NormalMember;
public fun getBotMuteRemaining ()I
public fun getBotPermission ()Lnet/mamoe/mirai/contact/MemberPermission;
public abstract fun getEssences ()Lnet/mamoe/mirai/contact/essence/Essences;
public abstract fun getId ()J
public abstract fun getMembers ()Lnet/mamoe/mirai/contact/ContactList;
public abstract fun getName ()Ljava/lang/String;
Expand All @@ -387,6 +388,8 @@ public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutin
public abstract fun getSettings ()Lnet/mamoe/mirai/contact/GroupSettings;
public fun quit ()Z
public abstract fun quit (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun removeEssenceMessage (Lnet/mamoe/mirai/message/data/MessageSource;)Z
public abstract fun removeEssenceMessage (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendMessage (Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public fun sendMessage (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendMessage (Lnet/mamoe/mirai/message/data/Message;)Lnet/mamoe/mirai/message/MessageReceipt;
Expand Down Expand Up @@ -900,6 +903,30 @@ public final class net/mamoe/mirai/contact/announcement/OnlineAnnouncementKt {
public static final fun getBot (Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;)Lnet/mamoe/mirai/Bot;
}

public final class net/mamoe/mirai/contact/essence/EssenceMessageRecord {
public fun <init> (Lnet/mamoe/mirai/contact/Group;Lnet/mamoe/mirai/contact/NormalMember;JLjava/lang/String;ILnet/mamoe/mirai/contact/NormalMember;JLjava/lang/String;ILnet/mamoe/mirai/message/data/MessageSource;)V
public final fun getGroup ()Lnet/mamoe/mirai/contact/Group;
public final fun getOperator ()Lnet/mamoe/mirai/contact/NormalMember;
public final fun getOperatorId ()J
public final fun getOperatorNick ()Ljava/lang/String;
public final fun getOperatorTime ()I
public final fun getSender ()Lnet/mamoe/mirai/contact/NormalMember;
public final fun getSenderId ()J
public final fun getSenderNick ()Ljava/lang/String;
public final fun getSenderTime ()I
public final fun getSource ()Lnet/mamoe/mirai/message/data/MessageSource;
public fun toString ()Ljava/lang/String;
}

public abstract interface class net/mamoe/mirai/contact/essence/Essences : net/mamoe/mirai/utils/Streamable {
public fun getPage (II)Ljava/util/List;
public abstract fun getPage (IILkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun remove (Lnet/mamoe/mirai/message/data/MessageSource;)V
public abstract fun remove (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun share (Lnet/mamoe/mirai/message/data/MessageSource;)Ljava/lang/String;
public abstract fun share (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class net/mamoe/mirai/contact/file/AbsoluteFile : net/mamoe/mirai/contact/file/AbsoluteFileFolder {
public abstract fun getExpiryTime ()J
public abstract fun getMd5 ()[B
Expand Down
27 changes: 27 additions & 0 deletions mirai-core-api/compatibility-validation/jvm/api/jvm.api
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutin
public abstract fun getBotAsMember ()Lnet/mamoe/mirai/contact/NormalMember;
public fun getBotMuteRemaining ()I
public fun getBotPermission ()Lnet/mamoe/mirai/contact/MemberPermission;
public abstract fun getEssences ()Lnet/mamoe/mirai/contact/essence/Essences;
public abstract fun getId ()J
public abstract fun getMembers ()Lnet/mamoe/mirai/contact/ContactList;
public abstract fun getName ()Ljava/lang/String;
Expand All @@ -387,6 +388,8 @@ public abstract interface class net/mamoe/mirai/contact/Group : kotlinx/coroutin
public abstract fun getSettings ()Lnet/mamoe/mirai/contact/GroupSettings;
public fun quit ()Z
public abstract fun quit (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun removeEssenceMessage (Lnet/mamoe/mirai/message/data/MessageSource;)Z
public abstract fun removeEssenceMessage (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendMessage (Ljava/lang/String;)Lnet/mamoe/mirai/message/MessageReceipt;
public fun sendMessage (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun sendMessage (Lnet/mamoe/mirai/message/data/Message;)Lnet/mamoe/mirai/message/MessageReceipt;
Expand Down Expand Up @@ -900,6 +903,30 @@ public final class net/mamoe/mirai/contact/announcement/OnlineAnnouncementKt {
public static final fun getBot (Lnet/mamoe/mirai/contact/announcement/OnlineAnnouncement;)Lnet/mamoe/mirai/Bot;
}

public final class net/mamoe/mirai/contact/essence/EssenceMessageRecord {
public fun <init> (Lnet/mamoe/mirai/contact/Group;Lnet/mamoe/mirai/contact/NormalMember;JLjava/lang/String;ILnet/mamoe/mirai/contact/NormalMember;JLjava/lang/String;ILnet/mamoe/mirai/message/data/MessageSource;)V
public final fun getGroup ()Lnet/mamoe/mirai/contact/Group;
public final fun getOperator ()Lnet/mamoe/mirai/contact/NormalMember;
public final fun getOperatorId ()J
public final fun getOperatorNick ()Ljava/lang/String;
public final fun getOperatorTime ()I
public final fun getSender ()Lnet/mamoe/mirai/contact/NormalMember;
public final fun getSenderId ()J
public final fun getSenderNick ()Ljava/lang/String;
public final fun getSenderTime ()I
public final fun getSource ()Lnet/mamoe/mirai/message/data/MessageSource;
public fun toString ()Ljava/lang/String;
}

public abstract interface class net/mamoe/mirai/contact/essence/Essences : net/mamoe/mirai/utils/Streamable {
public fun getPage (II)Ljava/util/List;
public abstract fun getPage (IILkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun remove (Lnet/mamoe/mirai/message/data/MessageSource;)V
public abstract fun remove (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun share (Lnet/mamoe/mirai/message/data/MessageSource;)Ljava/lang/String;
public abstract fun share (Lnet/mamoe/mirai/message/data/MessageSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class net/mamoe/mirai/contact/file/AbsoluteFile : net/mamoe/mirai/contact/file/AbsoluteFileFolder {
public abstract fun getExpiryTime ()J
public abstract fun getMd5 ()[B
Expand Down
18 changes: 18 additions & 0 deletions mirai-core-api/src/commonMain/kotlin/contact/Group.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.active.GroupActive
import net.mamoe.mirai.contact.announcement.Announcements
import net.mamoe.mirai.contact.essence.Essences
import net.mamoe.mirai.contact.file.RemoteFiles
import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.message.MessageReceipt
Expand Down Expand Up @@ -228,6 +229,23 @@ public interface Group : Contact, CoroutineScope, FileSupported, AudioSupported
*/
public suspend fun setEssenceMessage(source: MessageSource): Boolean

/**
* 取消一条群精华消息, 需要管理员或群主权限.
* 操作成功返回 `true`.
*
* @throws PermissionDeniedException 没有权限时抛出
*
* @since 2.14
*/
public suspend fun removeEssenceMessage(source: MessageSource): Boolean

/**
* 群精华消息相关功能接口
*
* @since 2.14
*/
public val essences: Essences

public companion object {
/**
* 将一条消息设置为群精华消息, 需要管理员或群主权限.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/

package net.mamoe.mirai.contact.essence

import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.NormalMember
import net.mamoe.mirai.message.data.MessageSource

/**
* 精华消息记录
* @since 2.14
* @param group 记录的群聊
* @param sender 消息的发送者
* @param senderId 消息的发送者的ID
* @param senderNick 消息的发送者的Nick
* @param senderTime 消息的发送的时间 *
* @param operator 设置精华的操作者
* @param operatorId 设置精华的操作者的ID
* @param operatorNick 设置精华的操作者的Nick
* @param operatorTime 设置精华的时间
* @param source 消息源
*/
public class EssenceMessageRecord(
public val group: Group,
public val sender: NormalMember?,
public val senderId: Long,
public val senderNick: String,
public val senderTime: Int,
public val operator: NormalMember?,
public val operatorId: Long,
public val operatorNick: String,
public val operatorTime: Int,
public val source: MessageSource
) {
override fun toString(): String {
return "EssenceMessageRecord(group=${group}, sender=${senderNick}(${senderId}), senderTime=${senderTime}, operator=${operatorNick}(${operatorId}), operatorTime=${operatorTime})"
}
}
68 changes: 68 additions & 0 deletions mirai-core-api/src/commonMain/kotlin/contact/essence/Essences.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/

package net.mamoe.mirai.contact.essence

import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
import net.mamoe.mirai.message.data.MessageSource
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.utils.NotStableForInheritance
import net.mamoe.mirai.utils.Streamable

/**
* 表示一个群精华消息管理.
*
* ## 获取 [Essences] 实例
*
* 只可以通过 [Group.essences] 获取一个群的精华消息管理, 即 [Essences] 实例.
*
* ### 获取精华消息列表
*
* 通过 [asFlow] 或 `asStream` 可以获取到*惰性*流, 在从流中收集数据时才会请求服务器获取数据. 通常建议在 Kotlin 使用协程的 [asFlow], 在 Java 使用 `asStream`.
*
* 若要获取全部精华消息列表, 可使用 [toList].
*
* ### 获取精华消息分享链接
*
* 通过 [share] 可以获得一个精华消息的分享链接
*
* ### 移除精华消息
*
* 通过 [remove] 可以从列表中移除指定精华消息 (WEB API)
*
* @since 2.14
*/
@NotStableForInheritance
public interface Essences : Streamable<EssenceMessageRecord> {

/**
* 按页获取精华消息记录
* @param start 起始索引
* @param limit 页大小
*/
@JvmBlockingBridge
public suspend fun getPage(start: Int, limit: Int): List<EssenceMessageRecord>

/**
* 分享精华消息
* @param source 要分享的消息源
* @throws IllegalStateException [source] 不为精华消息时将会触发异常
* @return 分享 URL
*/
@JvmBlockingBridge
public suspend fun share(source: MessageSource): String

/**
* 移除精华消息
* @throws IllegalStateException [source] 不为精华消息或权限不足时将会触发异常
* @param source 要移除的消息源
*/
@JvmBlockingBridge
public suspend fun remove(source: MessageSource)
}
24 changes: 24 additions & 0 deletions mirai-core-mock/src/contact/essence/MockEssences.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/

package net.mamoe.mirai.mock.contact.essence

import net.mamoe.mirai.contact.NormalMember
import net.mamoe.mirai.contact.essence.Essences
import net.mamoe.mirai.message.data.MessageSource
import net.mamoe.mirai.mock.MockBotDSL

public interface MockEssences : Essences {

/**
* 直接以 [actor] 的身份设置一条精华消息
*/
@MockBotDSL
public fun mockSetEssences(source: MessageSource, actor: NormalMember)
}
12 changes: 12 additions & 0 deletions mirai-core-mock/src/internal/contact/MockGroupImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ import net.mamoe.mirai.mock.contact.MockGroup
import net.mamoe.mirai.mock.contact.MockGroupControlPane
import net.mamoe.mirai.mock.contact.MockNormalMember
import net.mamoe.mirai.mock.contact.active.MockGroupActive
import net.mamoe.mirai.mock.contact.essence.MockEssences
import net.mamoe.mirai.mock.internal.contact.active.MockGroupActiveImpl
import net.mamoe.mirai.mock.internal.contact.essence.MockEssencesImpl
import net.mamoe.mirai.mock.internal.msgsrc.OnlineMsgSrcToGroup
import net.mamoe.mirai.mock.internal.msgsrc.newMsgSrc
import net.mamoe.mirai.mock.utils.broadcastBlocking
Expand Down Expand Up @@ -334,9 +336,19 @@ internal class MockGroupImpl(
resource.mockUploadVoice(bot)

override suspend fun setEssenceMessage(source: MessageSource): Boolean {
checkBotPermission(MemberPermission.ADMINISTRATOR)
essences.mockSetEssences(source, this.botAsMember)
return true
}

override suspend fun removeEssenceMessage(source: MessageSource): Boolean {
checkBotPermission(MemberPermission.ADMINISTRATOR)
essences.remove(source)
return true
}

override val essences: MockEssences = MockEssencesImpl(this)

@Deprecated("Please use files instead.", replaceWith = ReplaceWith("files.root"))
@Suppress("OverridingDeprecatedMember", "DEPRECATION", "DEPRECATION_ERROR")
override val filesRoot: RemoteFile by lazy {
Expand Down
59 changes: 59 additions & 0 deletions mirai-core-mock/src/internal/contact/essence/MockEssences.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/

package net.mamoe.mirai.mock.internal.contact.essence

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
import net.mamoe.mirai.contact.NormalMember
import net.mamoe.mirai.contact.essence.EssenceMessageRecord
import net.mamoe.mirai.message.data.MessageSource
import net.mamoe.mirai.mock.contact.essence.MockEssences
import net.mamoe.mirai.mock.internal.contact.MockGroupImpl
import net.mamoe.mirai.utils.ConcurrentHashMap
import net.mamoe.mirai.utils.currentTimeSeconds

internal class MockEssencesImpl(
private val group: MockGroupImpl
) : MockEssences {

private val cache: MutableMap<MessageSource, EssenceMessageRecord> = ConcurrentHashMap()

override fun mockSetEssences(source: MessageSource, actor: NormalMember) {
val record = EssenceMessageRecord(
group = group,
sender = group[source.fromId],
senderId = source.fromId,
senderNick = group[source.fromId]?.nick.orEmpty(),
senderTime = source.time,
operator = actor,
operatorId = actor.id,
operatorNick = actor.nick,
operatorTime = currentTimeSeconds().toInt(),
source = source
)
cache[source] = record
}

override suspend fun getPage(start: Int, limit: Int): List<EssenceMessageRecord> {
return cache.values.toList().subList(start, start + limit)
}

override suspend fun share(source: MessageSource): String {
return "https://qun.qq.com/essence/share?_wv=3&_wwv=128&_wvx=2&sharekey="
}

override suspend fun remove(source: MessageSource) {
cache.remove(source)
}

override fun asFlow(): Flow<EssenceMessageRecord> {
return cache.values.asFlow()
}
}
Loading