Commit 37745b83 authored by Him188's avatar Him188

Add docs

parent 69f1ee2c
......@@ -19,24 +19,40 @@ import kotlin.contracts.contract
*/
interface Contact : CoroutineScope {
/**
* 这个联系人所属 [Bot]
* 这个联系人所属 [Bot].
*/
@WeakRefProperty
val bot: Bot // weak ref
/**
* 可以是 QQ 号码或者群号码.
*
* 对于 QQ, `uin` 与 `id` 是相同的意思.
* 对于 Group, `groupCode` 与 `id` 是相同的意思.
*/
val id: Long
/**
* 向这个对象发送消息.
*
* 速度太快会被服务器屏蔽(无响应). 在测试中不延迟地发送 6 条消息就会被屏蔽之后的数据包 1 秒左右.
*/
suspend fun sendMessage(message: MessageChain)
/**
* 上传一个图片以备发送.
* TODO: 群图片与好友图片之间是否通用还不确定.
* TODO: 好友之间图片是否通用还不确定.
*/
suspend fun uploadImage(image: ExternalImage): Image
/**
* 判断 `this` 和 [other] 是否是相同的类型, 并且 [id] 相同.
*
* 注:
* [id] 相同的 [Member] 和 [QQ], 他们并不 [equals].
* 因为, [Member] 含义为群员, 必属于一个群.
* 而 [QQ] 含义为一个独立的人, 可以是好友, 也可以是陌生人.
*/
override fun equals(other: Any?): Boolean
}
suspend inline fun Contact.sendMessage(message: Message) = sendMessage(message.toChain())
......
......@@ -9,38 +9,38 @@ import kotlinx.coroutines.CoroutineScope
* 群. 在 QQ Android 中叫做 "Troop"
*/
interface Group : Contact, CoroutineScope {
/**
* ====以下字段在更新值的时候会自动异步上报服务器更改群信息====
*/
/**
* 群名称
* [可查可改已完成]
* 群名称.
*
* 在修改时将会异步上传至服务器.
*
* 注: 频繁修改可能会被服务器拒绝
*/
var name: String
/**
* 入群公告, 没有时为空字符串
* [可查可改已完成]
* 入群公告, 没有时为空字符串.
*
* 在修改时将会异步上传至服务器.
*/
var announcement: String
/**
* 全体禁言状态
* [可改已完成]
*/
* 全体禁言状态. `true` 为开启.
*
* 当前仅能修改状态.
*/// TODO: 2020/2/5 实现 muteAll 的查询
var muteAll: Boolean
/**
* 坦白说状态
* [可查可改已完成]
* 坦白说状态. `true` 为允许.
*
* 在修改时将会异步上传至服务器.
*/
var confessTalk: Boolean
/**
* 允许群员拉人状态
* [可查可改已完成]
* 允许群员邀请好友入群的状态. `true` 为允许
*/
var allowMemberInvite: Boolean
/**
* QQ中的自动加群审批
* [可查已完成]
* 自动加群审批
*/
val autoApprove: Boolean
/**
......
......@@ -11,18 +11,18 @@ import kotlin.time.ExperimentalTime
*/
interface Member : QQ, Contact {
/**
* 所在的群
* 所在的群.
*/
@WeakRefProperty
val group: Group
/**
* 权限
* 成员的权限, 动态更新.
*/
val permission: MemberPermission
/**
*
* 群名片 (如果有) 或个人昵称. 动态更新.
*/
var groupCard: String
......@@ -30,7 +30,7 @@ interface Member : QQ, Contact {
* 禁言
*
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
* @return 若机器人无权限禁言这个群成员, 返回 `false`
* @return 仅当机器人无权限禁言这个群成员时返回 `false`
*
* @see Int.minutesToSeconds
* @see Int.hoursToSeconds
......@@ -39,10 +39,14 @@ interface Member : QQ, Contact {
suspend fun mute(durationSeconds: Int): Boolean
/**
* 解除禁言
* 解除禁言. 在没有权限时会返回 `false`. 否则均返回 `true`.
*/
suspend fun unmute(): Boolean
/**
* 当且仅当 `[other] is [Member] && [other].id == this.id && [other].group == this.group` 时为 true
*/
override fun equals(other: Any?): Boolean
}
@ExperimentalTime
......
......@@ -3,6 +3,7 @@
package net.mamoe.mirai.message
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.IoBuffer
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.Group
......@@ -15,35 +16,47 @@ import net.mamoe.mirai.utils.*
import kotlin.jvm.JvmName
/**
* 平台相关扩展
* 一条从服务器接收到的消息事件.
* 请查看各平台的 `actual` 实现的说明.
*/
@UseExperimental(MiraiInternalAPI::class)
expect abstract class MessagePacket<TSender : QQ, TSubject : Contact>(bot: Bot) : MessagePacketBase<TSender, TSubject>
/**
* 仅内部使用, 请使用 [MessagePacket]
*/ // Tips: 在 IntelliJ 中 (左侧边栏) 打开 `Structure`, 可查看类结构
@Suppress("NOTHING_TO_INLINE")
@MiraiInternalAPI
abstract class MessagePacketBase<TSender : QQ, TSubject : Contact>(_bot: Bot) : EventPacket, BotEvent() {
/**
* 接受到这条消息的
*/
override val bot: Bot by _bot.unsafeWeakRef()
/**
* 消息事件主体.
*
* 对于好友消息, 这个属性为 [QQ] 的实例;
* 对于群消息, 这个属性为 [Group] 的实例
* 对于好友消息, 这个属性为 [QQ] 的实例, 与 [sender] 引用相同;
* 对于群消息, 这个属性为 [Group] 的实例, 与 [GroupMessage.group] 引用相同
*
* 在回复消息时, 可通过 [subject] 作为回复对象
*/
abstract val subject: TSubject
/**
* 发送人
* 发送人.
*
* 在好友消息时为 [QQ] 的实例, 在群消息时为 [Member] 的实例
*/
abstract val sender: TSender
/**
* 消息内容
*/
abstract val message: MessageChain
// region Send to subject
// region 发送 Message
/**
* 给这个消息事件的主体发送消息
......@@ -64,20 +77,41 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact>(_bot: Bot) :
@JvmName("reply1")
suspend inline fun MessageChain.reply() = reply(this)
suspend inline fun ExternalImage.send() = this.sendTo(subject)
// endregion
// region 上传图片
suspend inline fun ExternalImage.upload(): Image = this.upload(subject)
// endregion
// region 发送图片
suspend inline fun ExternalImage.send() = this.sendTo(subject)
suspend inline fun Image.send() = this.sendTo(subject)
suspend inline fun Message.send() = this.sendTo(subject)
suspend inline fun String.send() = this.toMessage().sendTo(subject)
// endregion
inline fun QQ.at(): At = At(this as Member)
/**
* 创建 @ 这个账号的消息. 当且仅当消息为群消息时可用. 否则将会抛出 [IllegalArgumentException]
*/
inline fun QQ.at(): At = At(this as? Member ?: error("`QQ.at` can only be used in GroupMessage"))
// endregion
// region Image download
/**
* 将图片下载到内存.
*
* 非常不推荐这样做.
*/
@Deprecated("内存使用效率十分低下", ReplaceWith("this.download()"), DeprecationLevel.WARNING)
suspend inline fun Image.downloadAsByteArray(): ByteArray = bot.run { downloadAsByteArray() }
// TODO: 2020/2/5 为下载图片添加文件系统的存储方式
/**
* 将图片下载到内存缓存中 (使用 [IoBuffer.Pool])
*/
suspend inline fun Image.download(): ByteReadPacket = bot.run { download() }
// endregion
......
......@@ -17,6 +17,8 @@ import kotlin.reflect.KProperty
* - 若两个 [MessageChain] 连接, 后一个将会被合并到第一个内.
* - 若一个 [MessageChain] 与一个其他 [Message] 连接, [Message] 将会被添加入 [MessageChain].
* - 若一个 [Message] 与一个 [MessageChain] 连接, [Message] 将会被添加入 [MessageChain].
*
* 要获取更多信息, 请查看 [Message]
*/
interface MessageChain : Message, MutableList<Message> {
// region Message override
......
......@@ -22,37 +22,52 @@ import java.net.URL
import javax.imageio.ImageIO
/**
* 一条从服务器接收到的消息事件.
* JVM 平台相关扩展
*/
@UseExperimental(MiraiInternalAPI::class)
actual abstract class MessagePacket<TSender : QQ, TSubject : Contact> actual constructor(bot: Bot) : MessagePacketBase<TSender, TSubject>(bot) {
// region 上传图片
suspend inline fun uploadImage(image: BufferedImage): Image = subject.uploadImage(image)
suspend inline fun uploadImage(image: URL): Image = subject.uploadImage(image)
suspend inline fun uploadImage(image: Input): Image = subject.uploadImage(image)
suspend inline fun uploadImage(image: InputStream): Image = subject.uploadImage(image)
suspend inline fun uploadImage(image: File): Image = subject.uploadImage(image)
// endregion
// region 发送图片
suspend inline fun sendImage(image: BufferedImage) = subject.sendImage(image)
suspend inline fun sendImage(image: URL) = subject.sendImage(image)
suspend inline fun sendImage(image: Input) = subject.sendImage(image)
suspend inline fun sendImage(image: InputStream) = subject.sendImage(image)
suspend inline fun sendImage(image: File) = subject.sendImage(image)
// endregion
// region 上传图片 (扩展)
suspend inline fun BufferedImage.upload(): Image = upload(subject)
suspend inline fun URL.uploadAsImage(): Image = uploadAsImage(subject)
suspend inline fun Input.uploadAsImage(): Image = uploadAsImage(subject)
suspend inline fun InputStream.uploadAsImage(): Image = uploadAsImage(subject)
suspend inline fun File.uploadAsImage(): Image = uploadAsImage(subject)
// endregion 上传图片 (扩展)
// region 发送图片 (扩展)
suspend inline fun BufferedImage.send() = sendTo(subject)
suspend inline fun URL.sendAsImage() = sendAsImageTo(subject)
suspend inline fun Input.sendAsImage() = sendAsImageTo(subject)
suspend inline fun InputStream.sendAsImage() = sendAsImageTo(subject)
suspend inline fun File.sendAsImage() = sendAsImageTo(subject)
// endregion 发送图片 (扩展)
// region 下载图片 (扩展)
suspend inline fun Image.downloadTo(file: File): Long = file.outputStream().use { downloadTo(it) }
/**
* 这个函数结束后不会关闭 [output]
* 这个函数结束后不会关闭 [output]. 请务必解决好 [OutputStream.close]
*/
suspend inline fun Image.downloadTo(output: OutputStream): Long =
download().inputStream().use { input -> withContext(Dispatchers.IO) { input.copyTo(output) } }
......@@ -60,4 +75,5 @@ actual abstract class MessagePacket<TSender : QQ, TSubject : Contact> actual con
suspend inline fun Image.downloadAsStream(): InputStream = download().inputStream()
suspend inline fun Image.downloadAsExternalImage(): ExternalImage = withContext(Dispatchers.IO) { download().toExternalImage() }
suspend inline fun Image.downloadAsBufferedImage(): BufferedImage = withContext(Dispatchers.IO) { ImageIO.read(downloadAsStream()) }
// endregion
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment