This commit is contained in:
Him188 2020-05-03 22:25:35 +08:00
parent 35e39a7fba
commit c2fa014c78
13 changed files with 188 additions and 122 deletions

View File

@ -45,6 +45,8 @@ suspend inline fun <B : Bot> B.alsoLogin(): B = also { login() }
*
* @see Contact 联系人
* @see kotlinx.coroutines.isActive 判断 [Bot] 是否正常运行中. (在线, 且没有被 [close])
*
* @see BotFactory 构造 [Bot] 的工厂, [Bot] 唯一的构造方式.
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@OptIn(MiraiInternalAPI::class, LowLevelAPI::class)

View File

@ -16,13 +16,13 @@ import net.mamoe.mirai.utils.Context
import kotlin.jvm.JvmName
/**
* 构造 [Bot] 的工厂.
* 构造 [Bot] 的工厂. 这是 [Bot] 唯一的构造方式.
*
* 在协议模块中有各自的实现.
* - `mirai-core-timpc`: `TIMPC`
* - `mirai-core-qqandroid`: `QQAndroid`
* `mirai-core-qqandroid`: `QQAndroid`
*
* JVM, 请查看 `BotFactoryJvm`
*/
interface BotFactory {
expect interface BotFactory {
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/

View File

@ -32,11 +32,11 @@ import kotlin.jvm.JvmSynthetic
/**
* 联系. 虽然叫做联系人, 但他的子类有 [用户][User], [][Group].
* 联系对象, 即可以与 [Bot] 互动的对象. 包含 [用户][User], [][Group].
*/
abstract class Contact : CoroutineScope, ContactJavaFriendlyAPI(), ContactOrBot {
/**
* 这个联系所属 [Bot].
* 这个联系对象所属 [Bot].
*/
@WeakRefProperty
abstract val bot: Bot
@ -44,10 +44,7 @@ abstract class Contact : CoroutineScope, ContactJavaFriendlyAPI(), ContactOrBot
/**
* 可以是 QQ 号码或者群号码.
*
* 对于 [QQ], `uin` `id` 是相同的意思.
* 对于 [Group], `groupCode` `id` 是相同的意思.
*
* @see QQ.id
* @see User.id
* @see Group.id
*/
abstract override val id: Long

View File

@ -16,18 +16,20 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.EventCancelledException
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import net.mamoe.mirai.message.FriendMessage
import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.toMessage
import kotlin.jvm.JvmSynthetic
/**
* 好友 对象.
* 注意: 一个 [Friend] 实例并不是独立的, 它属于一个 [Bot].
* 它不能被直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
* 代表一位好友.
*
* 对于同一个 [Bot] 任何一个人的 [Friend] 实例都是单一的.
* 它不能被直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
* 一个 [Friend] 实例并不是独立的, 它属于一个 [Bot].
* 对于同一个 [Bot], 任何一个人的 [Friend] 实例都是单一的.
* [Friend] 无法通过任何方式直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
*
* @see FriendMessage
*/
@Suppress("DEPRECATION_ERROR")
abstract class Friend : User(), CoroutineScope {

View File

@ -80,7 +80,6 @@ abstract class Group : Contact(), CoroutineScope {
* 机器人在这个群里的权限
*
* @see Group.checkBotPermission 检查 [Bot] 在这个群里的权限
* @see Group.checkBotPermissionOperator 要求 [Bot] 在这个群里的权限为 [管理员或群主][MemberPermission.isOperator]
*
* @see BotGroupPermissionChangeEvent 机器人群员修改
*/

View File

@ -26,10 +26,13 @@ import kotlin.time.Duration
import kotlin.time.ExperimentalTime
/**
* 群成员.
* 代表一位群成员.
*
* 群成员可能也是好友, 但他们在对象类型上不同.
* 群成员可以通过 [asFriend] 得到相关好友对象.
*
* ## 与好友相关的操作
* [Member.isFriend] 判断此成员是否为好友
*/
@Suppress("INAPPLICABLE_JVM_NAME")
@OptIn(MiraiInternalAPI::class, JavaFriendlyAPI::class)
@ -93,12 +96,16 @@ abstract class Member : MemberJavaFriendlyAPI() {
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
* @return 机器人无权限时返回 `false`
*
* @see Member.isMuted 判断此成员是否正处于禁言状态中
* @see unmute 取消禁言此成员
*
* @see Int.minutesToSeconds
* @see Int.hoursToSeconds
* @see Int.daysToSeconds
*
* @see MemberMuteEvent 成员被禁言事件
* @throws PermissionDeniedException 无权限修改时
*
* @throws PermissionDeniedException 无权限修改时抛出
*/
@JvmSynthetic
abstract suspend fun mute(durationSeconds: Int)
@ -108,8 +115,11 @@ abstract class Member : MemberJavaFriendlyAPI() {
*
* 管理员可解除成员的禁言, 群主可解除管理员和群员的禁言.
*
* @see MemberUnmuteEvent 成员被取消禁言事件.
* @throws PermissionDeniedException 无权限修改时
* @see Member.isMuted 判断此成员是否正处于禁言状态中
*
* @see MemberUnmuteEvent 成员被取消禁言事件
*
* @throws PermissionDeniedException 无权限修改时抛出
*/
@JvmSynthetic
abstract suspend fun unmute()
@ -166,7 +176,7 @@ abstract class Member : MemberJavaFriendlyAPI() {
fun Member.asFriend(): Friend = this.bot.getFriendOrNull(this.id) ?: error("$this is not a friend")
/**
* 得到此成员作为好友的对象.
* 得到此成员作为好友的对象, 当此成员不是好友时返回 `null`
*/
@SinceMirai("0.39.0")
fun Member.asFriendOrNull(): Friend? = this.bot.getFriendOrNull(this.id)

View File

@ -617,6 +617,8 @@ data class MemberPermissionChangeEvent(
/**
* 群成员被禁言事件. 被禁言的成员都不可能是机器人本人
*
* @see BotMuteEvent 机器人被禁言的事件
*/
data class MemberMuteEvent(
override val member: Member,
@ -629,6 +631,8 @@ data class MemberMuteEvent(
/**
* 群成员被取消禁言事件. 被禁言的成员都不可能是机器人本人
*
* @see BotUnmuteEvent 机器人被取消禁言的事件
*/
data class MemberUnmuteEvent(
override val member: Member,

View File

@ -34,12 +34,14 @@ import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
* 一条消息事件.
* 一个消息事件.
*
* 它是一个 [BotEvent], 因此可以被 [监听][Bot.subscribe]
*
* 支持的消息类型:
* [GroupMessage]
* [FriendMessage]
* - [群消息事件][GroupMessage]
* - [好友消息事件][FriendMessage]
* - [临时会话消息事件][TempMessage]
*
* @see isContextIdenticalWith 判断语境是否相同
*/

View File

@ -22,7 +22,7 @@ import net.mamoe.mirai.utils.getValue
import net.mamoe.mirai.utils.unsafeWeakRef
/**
* 好友消息
* 好友消息事件
*/
class FriendMessage constructor(
sender: Friend,

View File

@ -18,6 +18,11 @@ import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.getValue
import net.mamoe.mirai.utils.unsafeWeakRef
/**
* 群消息事件
*
* @see ContactMessage
*/
@Suppress("unused", "NOTHING_TO_INLINE")
class GroupMessage(
override val senderName: String,

View File

@ -14,6 +14,7 @@
package net.mamoe.mirai.message.data
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.message.ContactMessage
import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Message.Key
import net.mamoe.mirai.utils.MiraiInternalAPI
@ -26,8 +27,6 @@ import kotlin.jvm.JvmSynthetic
/**
* 可发送的或从服务器接收的消息.
*
* 采用这样的消息模式是因为 QQ 的消息多元化, 一条消息中可包含 [纯文本][PlainText], [图片][Image] .
*
* [消息][Message] 分为
* - [SingleMessage]:
* - [MessageMetadata] 消息元数据, 包括: [消息来源][MessageSource], [引用回复][QuoteReply].
@ -63,6 +62,11 @@ import kotlin.jvm.JvmSynthetic
*
* , `appendable.append(message)` 相当于 `appendable.append(message.toString())`
*
* #### 发送消息
* - 通过 [Contact] 中的成员函数: [Contact.sendMessage]
* - 通过 [Message] 的扩展函数: [Message.sendTo]
* - [ContactMessage] 中使用 [ContactMessage.reply] 等捷径
*
* @see PlainText 纯文本
* @see Image 图片
* @see Face 原生表情

View File

@ -0,0 +1,135 @@
@file:Suppress("FunctionName", "INAPPLICABLE_JVM_NAME", "DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith")
@file:JvmName("BotFactoryJvm")
package net.mamoe.mirai
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.ContextImpl
/**
* 构造 [Bot] 的工厂. 这是 [Bot] 唯一的构造方式.
*
* 请添加模块依赖 `mirai-core-qqandroid` 以获取协议支持.
*
* mirai 通过 [Class.forName] 查找可用的协议实现, `net.mamoe.mirai.qqandroid.QQAndroid`
*/
actual interface BotFactory {
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmName("newBot")
actual fun Bot(
context: Context,
qq: Long,
password: String,
configuration: BotConfiguration
): Bot
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmName("newBot")
actual fun Bot(
context: Context,
qq: Long,
passwordMd5: ByteArray,
configuration: BotConfiguration
): Bot
}
// Do not use ServiceLoader. Probably not working on MPP
@PublishedApi
internal val factory: BotFactory = run {
runCatching {
Class.forName("net.mamoe.mirai.timpc.TIMPC").kotlin.objectInstance as BotFactory
}.getOrElse {
runCatching {
Class.forName("net.mamoe.mirai.qqandroid.QQAndroid").kotlin.objectInstance as BotFactory
}.getOrNull()
}
} ?: error(
"""
No BotFactory found. Please ensure that you've added dependency of protocol modules.
Available modules:
- net.mamoe:mirai-core-timpc (stays at 0.12.0)
- net.mamoe:mirai-core-qqandroid (recommended)
You should have at lease one protocol module installed.
-------------------------------------------------------
找不到 BotFactory. 请确保你依赖了至少一个协议模块.
可用的协议模块:
- net.mamoe:mirai-core-timpc (0.12.0 后停止更新)
- net.mamoe:mirai-core-qqandroid (推荐)
请添加上述任一模块的依赖( mirai-core 版本相同)
""".trimIndent()
)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmName("newBot")
@JvmOverloads
fun Bot(context: Context, qq: Long, password: String, configuration: BotConfiguration = BotConfiguration.Default): Bot =
factory.Bot(context, qq, password, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmSynthetic
inline fun Bot(context: Context, qq: Long, password: String, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(context, qq, password, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmName("newBot")
@JvmOverloads
fun Bot(qq: Long, password: String, configuration: BotConfiguration = BotConfiguration.Default): Bot =
factory.Bot(ContextImpl(), qq, password, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmSynthetic
inline fun Bot(qq: Long, password: String, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(ContextImpl(), qq, password, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmName("newBot")
@JvmOverloads
fun Bot(
context: Context,
qq: Long,
passwordMd5: ByteArray,
configuration: BotConfiguration = BotConfiguration.Default
): Bot =
factory.Bot(context, qq, passwordMd5, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmSynthetic
inline fun Bot(context: Context, qq: Long, passwordMd5: ByteArray, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(context, qq, passwordMd5, BotConfiguration().apply(configuration))
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmName("newBot")
@JvmOverloads
fun Bot(qq: Long, passwordMd5: ByteArray, configuration: BotConfiguration = BotConfiguration.Default): Bot =
factory.Bot(ContextImpl(), qq, passwordMd5, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmSynthetic
inline fun Bot(qq: Long, passwordMd5: ByteArray, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(ContextImpl(), qq, passwordMd5, BotConfiguration().apply(configuration))

View File

@ -15,97 +15,3 @@ package net.mamoe.mirai
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.ContextImpl
// Do not use ServiceLoader. Probably not working on MPP
@PublishedApi
internal val factory: BotFactory = run {
runCatching {
Class.forName("net.mamoe.mirai.timpc.TIMPC").kotlin.objectInstance as BotFactory
}.getOrElse {
runCatching {
Class.forName("net.mamoe.mirai.qqandroid.QQAndroid").kotlin.objectInstance as BotFactory
}.getOrNull()
}
} ?: error(
"""
No BotFactory found. Please ensure that you've added dependency of protocol modules.
Available modules:
- net.mamoe:mirai-core-timpc (stays at 0.12.0)
- net.mamoe:mirai-core-qqandroid (recommended)
You should have at lease one protocol module installed.
-------------------------------------------------------
找不到 BotFactory. 请确保你依赖了至少一个协议模块.
可用的协议模块:
- net.mamoe:mirai-core-timpc (0.12.0 后停止更新)
- net.mamoe:mirai-core-qqandroid (推荐)
请添加上述任一模块的依赖( mirai-core 版本相同)
""".trimIndent()
)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmName("newBot")
@JvmOverloads
fun Bot(context: Context, qq: Long, password: String, configuration: BotConfiguration = BotConfiguration.Default): Bot =
factory.Bot(context, qq, password, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmSynthetic
inline fun Bot(context: Context, qq: Long, password: String, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(context, qq, password, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmName("newBot")
@JvmOverloads
fun Bot(qq: Long, password: String, configuration: BotConfiguration = BotConfiguration.Default): Bot =
factory.Bot(ContextImpl(), qq, password, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmSynthetic
inline fun Bot(qq: Long, password: String, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(ContextImpl(), qq, password, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmName("newBot")
@JvmOverloads
fun Bot(
context: Context,
qq: Long,
passwordMd5: ByteArray,
configuration: BotConfiguration = BotConfiguration.Default
): Bot =
factory.Bot(context, qq, passwordMd5, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmSynthetic
inline fun Bot(context: Context, qq: Long, passwordMd5: ByteArray, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(context, qq, passwordMd5, BotConfiguration().apply(configuration))
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmName("newBot")
@JvmOverloads
fun Bot(qq: Long, passwordMd5: ByteArray, configuration: BotConfiguration = BotConfiguration.Default): Bot =
factory.Bot(ContextImpl(), qq, passwordMd5, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
@JvmSynthetic
inline fun Bot(qq: Long, passwordMd5: ByteArray, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(ContextImpl(), qq, passwordMd5, BotConfiguration().apply(configuration))