Commit bc71475f authored by Him188's avatar Him188

Add event broadcasting

parent 96db7a60
...@@ -64,7 +64,7 @@ fun Application.groupManageModule() { ...@@ -64,7 +64,7 @@ fun Application.groupManageModule() {
val group = dto.session.bot.getGroup(dto.target) val group = dto.session.bot.getGroup(dto.target)
with(dto.config) { with(dto.config) {
name?.let { group.name = it } name?.let { group.name = it }
announcement?.let { group.announcement = it } announcement?.let { group.entranceAnnouncement = it }
confessTalk?.let { group.confessTalk = it } confessTalk?.let { group.confessTalk = it }
allowMemberInvite?.let { group.allowMemberInvite = it } allowMemberInvite?.let { group.allowMemberInvite = it }
// TODO: 待core接口实现设置可改 // TODO: 待core接口实现设置可改
...@@ -128,7 +128,7 @@ private data class GroupDetailDTO( ...@@ -128,7 +128,7 @@ private data class GroupDetailDTO(
val anonymousChat: Boolean? = null val anonymousChat: Boolean? = null
) : DTO { ) : DTO {
constructor(group: Group) : this( constructor(group: Group) : this(
group.name, group.announcement, group.confessTalk, group.allowMemberInvite, group.name, group.entranceAnnouncement, group.confessTalk, group.allowMemberInvite,
group.autoApprove, group.anonymousChat group.autoApprove, group.anonymousChat
) )
} }
......
...@@ -15,7 +15,9 @@ import net.mamoe.mirai.data.FriendNameRemark ...@@ -15,7 +15,9 @@ import net.mamoe.mirai.data.FriendNameRemark
import net.mamoe.mirai.data.PreviousNameList import net.mamoe.mirai.data.PreviousNameList
import net.mamoe.mirai.data.Profile import net.mamoe.mirai.data.Profile
import net.mamoe.mirai.event.broadcast import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.MemberCardChangeEvent import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import net.mamoe.mirai.message.data.CustomFaceFromFile import net.mamoe.mirai.message.data.CustomFaceFromFile
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
...@@ -53,18 +55,25 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin ...@@ -53,18 +55,25 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin
override lateinit var nick: String override lateinit var nick: String
override suspend fun sendMessage(message: MessageChain) { override suspend fun sendMessage(message: MessageChain) {
val event = FriendMessageSendEvent(this, message).broadcast()
if (event.isCancelled) {
throw EventCancelledException("cancelled by FriendMessageSendEvent")
}
bot.network.run { bot.network.run {
check( check(
MessageSvc.PbSendMsg.ToFriend( MessageSvc.PbSendMsg.ToFriend(
bot.client, bot.client,
id, id,
message event.message
).sendAndExpect<MessageSvc.PbSendMsg.Response>() is MessageSvc.PbSendMsg.Response.SUCCESS ).sendAndExpect<MessageSvc.PbSendMsg.Response>() is MessageSvc.PbSendMsg.Response.SUCCESS
) { "send message failed" } ) { "send message failed" }
} }
} }
override suspend fun uploadImage(image: ExternalImage): Image = try { override suspend fun uploadImage(image: ExternalImage): Image = try {
if (BeforeImageUploadEvent(this, image).broadcast().isCancelled) {
throw EventCancelledException("cancelled by BeforeImageUploadEvent.ToGroup")
}
bot.network.run { bot.network.run {
val response = LongConn.OffPicUp( val response = LongConn.OffPicUp(
bot.client, Cmd0x352.TryUpImgReq( bot.client, Cmd0x352.TryUpImgReq(
...@@ -89,7 +98,9 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin ...@@ -89,7 +98,9 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin
height = response.imageInfo.fileHeight, height = response.imageInfo.fileHeight,
width = response.imageInfo.fileWidth, width = response.imageInfo.fileWidth,
resourceId = response.resourceId resourceId = response.resourceId
) ).also {
ImageUploadEvent.Succeed(this@QQImpl, image, it).broadcast()
}
is LongConn.OffPicUp.Response.RequireUpload -> { is LongConn.OffPicUp.Response.RequireUpload -> {
Http.postImage("0x6ff0070", bot.uin, null, imageInput = image.input, inputSize = image.inputSize, uKeyHex = response.uKey.toUHexString("")) Http.postImage("0x6ff0070", bot.uin, null, imageInput = image.input, inputSize = image.inputSize, uKeyHex = response.uKey.toUHexString(""))
// HighwayHelper.uploadImage( // HighwayHelper.uploadImage(
...@@ -110,9 +121,14 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin ...@@ -110,9 +121,14 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin
height = image.height, height = image.height,
width = image.width, width = image.width,
resourceId = response.resourceId resourceId = response.resourceId
) ).also {
ImageUploadEvent.Succeed(this@QQImpl, image, it).broadcast()
}
}
is LongConn.OffPicUp.Response.Failed -> {
ImageUploadEvent.Failed(this@QQImpl, image, -1, response.message).broadcast()
error(response.message)
} }
is LongConn.OffPicUp.Response.Failed -> error(response.message)
} }
} }
} finally { } finally {
...@@ -159,7 +175,6 @@ internal class MemberImpl( ...@@ -159,7 +175,6 @@ internal class MemberImpl(
val oldValue = _groupCard val oldValue = _groupCard
_groupCard = newValue _groupCard = newValue
launch { launch {
MemberCardChangeEvent.ByBot(oldValue, newValue, this@MemberImpl).broadcast()
bot.network.run { bot.network.run {
TroopManagement.EditGroupNametag( TroopManagement.EditGroupNametag(
bot.client, bot.client,
...@@ -167,6 +182,7 @@ internal class MemberImpl( ...@@ -167,6 +182,7 @@ internal class MemberImpl(
newValue newValue
).sendWithoutExpect() ).sendWithoutExpect()
} }
MemberCardChangeEvent.ByBot(oldValue, newValue, this@MemberImpl).broadcast()
} }
} }
} }
...@@ -176,6 +192,7 @@ internal class MemberImpl( ...@@ -176,6 +192,7 @@ internal class MemberImpl(
set(newValue) { set(newValue) {
group.checkBotPermissionOperator() group.checkBotPermissionOperator()
if (_specialTitle != newValue) { if (_specialTitle != newValue) {
val oldValue = _specialTitle
_specialTitle = newValue _specialTitle = newValue
launch { launch {
bot.network.run { bot.network.run {
...@@ -185,6 +202,7 @@ internal class MemberImpl( ...@@ -185,6 +202,7 @@ internal class MemberImpl(
newValue newValue
).sendWithoutExpect() ).sendWithoutExpect()
} }
MemberSpecialTitleChangeEvent(oldValue, newValue, this@MemberImpl).broadcast()
} }
} }
} }
...@@ -204,6 +222,8 @@ internal class MemberImpl( ...@@ -204,6 +222,8 @@ internal class MemberImpl(
timeInSecond = durationSeconds timeInSecond = durationSeconds
).sendAndExpect<TroopManagement.Mute.Response>() ).sendAndExpect<TroopManagement.Mute.Response>()
} }
MemberMuteEvent.ByBot(this@MemberImpl, durationSeconds).broadcast()
return true return true
} }
...@@ -220,6 +240,8 @@ internal class MemberImpl( ...@@ -220,6 +240,8 @@ internal class MemberImpl(
timeInSecond = 0 timeInSecond = 0
).sendAndExpect<TroopManagement.Mute.Response>() ).sendAndExpect<TroopManagement.Mute.Response>()
} }
MemberUnmuteEvent.ByBot(this@MemberImpl).broadcast()
return true return true
} }
...@@ -233,7 +255,9 @@ internal class MemberImpl( ...@@ -233,7 +255,9 @@ internal class MemberImpl(
client = bot.client, client = bot.client,
member = this@MemberImpl, member = this@MemberImpl,
message = message message = message
).sendAndExpect<TroopManagement.Kick.Response>().success ).sendAndExpect<TroopManagement.Kick.Response>().success.also {
MemberLeaveEvent.Kick.ByBot(this@MemberImpl).broadcast()
}
} }
} }
...@@ -270,6 +294,7 @@ internal class GroupImpl( ...@@ -270,6 +294,7 @@ internal class GroupImpl(
set(newValue) { set(newValue) {
this.checkBotPermissionOperator() this.checkBotPermissionOperator()
if (_name != newValue) { if (_name != newValue) {
val oldValue = _name
_name = newValue _name = newValue
launch { launch {
bot.network.run { bot.network.run {
...@@ -279,15 +304,17 @@ internal class GroupImpl( ...@@ -279,15 +304,17 @@ internal class GroupImpl(
newName = newValue newName = newValue
).sendWithoutExpect() ).sendWithoutExpect()
} }
GroupNameChangeEvent.ByBot(oldValue, newValue, this@GroupImpl).broadcast()
} }
} }
} }
override var announcement: String override var entranceAnnouncement: String
get() = _announcement get() = _announcement
set(newValue) { set(newValue) {
this.checkBotPermissionOperator() this.checkBotPermissionOperator()
if (_announcement != newValue) { if (_announcement != newValue) {
val oldValue = _announcement
_announcement = newValue _announcement = newValue
launch { launch {
bot.network.run { bot.network.run {
...@@ -297,6 +324,7 @@ internal class GroupImpl( ...@@ -297,6 +324,7 @@ internal class GroupImpl(
newMemo = newValue newMemo = newValue
).sendWithoutExpect() ).sendWithoutExpect()
} }
GroupEntranceAnnouncementChangeEvent.ByBot(oldValue, newValue, this@GroupImpl).broadcast()
} }
} }
} }
...@@ -307,6 +335,7 @@ internal class GroupImpl( ...@@ -307,6 +335,7 @@ internal class GroupImpl(
set(newValue) { set(newValue) {
this.checkBotPermissionOperator() this.checkBotPermissionOperator()
if (_allowMemberInvite != newValue) { if (_allowMemberInvite != newValue) {
val oldValue = _allowMemberInvite
_allowMemberInvite = newValue _allowMemberInvite = newValue
launch { launch {
bot.network.run { bot.network.run {
...@@ -316,6 +345,7 @@ internal class GroupImpl( ...@@ -316,6 +345,7 @@ internal class GroupImpl(
switch = newValue switch = newValue
).sendWithoutExpect() ).sendWithoutExpect()
} }
GroupAllowMemberInviteEvent.ByBot(oldValue, newValue, this@GroupImpl).broadcast()
} }
} }
} }
...@@ -337,6 +367,7 @@ internal class GroupImpl( ...@@ -337,6 +367,7 @@ internal class GroupImpl(
set(newValue) { set(newValue) {
this.checkBotPermissionOperator() this.checkBotPermissionOperator()
if (_confessTalk != newValue) { if (_confessTalk != newValue) {
val oldValue = _confessTalk
_confessTalk = newValue _confessTalk = newValue
launch { launch {
bot.network.run { bot.network.run {
...@@ -346,6 +377,7 @@ internal class GroupImpl( ...@@ -346,6 +377,7 @@ internal class GroupImpl(
switch = newValue switch = newValue
).sendWithoutExpect() ).sendWithoutExpect()
} }
GroupAllowConfessTalkEvent.ByBot(oldValue, newValue, this@GroupImpl).broadcast()
} }
} }
} }
...@@ -356,6 +388,7 @@ internal class GroupImpl( ...@@ -356,6 +388,7 @@ internal class GroupImpl(
set(newValue) { set(newValue) {
this.checkBotPermissionOperator() this.checkBotPermissionOperator()
if (_muteAll != newValue) { if (_muteAll != newValue) {
val oldValue = _muteAll
_muteAll = newValue _muteAll = newValue
launch { launch {
bot.network.run { bot.network.run {
...@@ -365,6 +398,7 @@ internal class GroupImpl( ...@@ -365,6 +398,7 @@ internal class GroupImpl(
switch = newValue switch = newValue
).sendWithoutExpect() ).sendWithoutExpect()
} }
GroupMuteAllEvent.ByBot(oldValue, newValue, this@GroupImpl).broadcast()
} }
} }
} }
...@@ -376,7 +410,7 @@ internal class GroupImpl( ...@@ -376,7 +410,7 @@ internal class GroupImpl(
override suspend fun quit(): Boolean { override suspend fun quit(): Boolean {
check(botPermission != MemberPermission.OWNER) { "An owner cannot quit from a owning group" } check(botPermission != MemberPermission.OWNER) { "An owner cannot quit from a owning group" }
TODO("not implemented") //To change body of created functions use File | Settings | File Templates. TODO("not implemented")
} }
...@@ -395,11 +429,15 @@ internal class GroupImpl( ...@@ -395,11 +429,15 @@ internal class GroupImpl(
override val bot: QQAndroidBot by bot.unsafeWeakRef() override val bot: QQAndroidBot by bot.unsafeWeakRef()
override suspend fun sendMessage(message: MessageChain) { override suspend fun sendMessage(message: MessageChain) {
val event = GroupMessageSendEvent(this, message).broadcast()
if (event.isCancelled) {
throw EventCancelledException("cancelled by FriendMessageSendEvent")
}
bot.network.run { bot.network.run {
val response = MessageSvc.PbSendMsg.ToGroup( val response = MessageSvc.PbSendMsg.ToGroup(
bot.client, bot.client,
id, id,
message event.message
).sendAndExpect<MessageSvc.PbSendMsg.Response>() ).sendAndExpect<MessageSvc.PbSendMsg.Response>()
check( check(
response is MessageSvc.PbSendMsg.Response.SUCCESS response is MessageSvc.PbSendMsg.Response.SUCCESS
...@@ -408,6 +446,9 @@ internal class GroupImpl( ...@@ -408,6 +446,9 @@ internal class GroupImpl(
} }
override suspend fun uploadImage(image: ExternalImage): Image = try { override suspend fun uploadImage(image: ExternalImage): Image = try {
if (BeforeImageUploadEvent(this, image).broadcast().isCancelled) {
throw EventCancelledException("cancelled by BeforeImageUploadEvent.ToGroup")
}
bot.network.run { bot.network.run {
val response: ImgStore.GroupPicUp.Response = ImgStore.GroupPicUp( val response: ImgStore.GroupPicUp.Response = ImgStore.GroupPicUp(
bot.client, bot.client,
...@@ -422,7 +463,10 @@ internal class GroupImpl( ...@@ -422,7 +463,10 @@ internal class GroupImpl(
).sendAndExpect() ).sendAndExpect()
when (response) { when (response) {
is ImgStore.GroupPicUp.Response.Failed -> error("upload group image failed with reason ${response.message}") is ImgStore.GroupPicUp.Response.Failed -> {
ImageUploadEvent.Failed(this@GroupImpl, image, response.resultCode, response.message).broadcast()
error("upload group image failed with reason ${response.message}")
}
is ImgStore.GroupPicUp.Response.FileExists -> { is ImgStore.GroupPicUp.Response.FileExists -> {
val resourceId = image.calculateImageResourceId() val resourceId = image.calculateImageResourceId()
// return NotOnlineImageFromFile( // return NotOnlineImageFromFile(
...@@ -439,10 +483,9 @@ internal class GroupImpl( ...@@ -439,10 +483,9 @@ internal class GroupImpl(
return CustomFaceFromFile( return CustomFaceFromFile(
md5 = image.md5, md5 = image.md5,
filepath = resourceId filepath = resourceId
) ).also { ImageUploadEvent.Succeed(this@GroupImpl, image, it).broadcast() }
} }
is ImgStore.GroupPicUp.Response.RequireUpload -> { is ImgStore.GroupPicUp.Response.RequireUpload -> {
HighwayHelper.uploadImage( HighwayHelper.uploadImage(
client = bot.client, client = bot.client,
serverIp = response.uploadIpList.first().toIpV4AddressString(), serverIp = response.uploadIpList.first().toIpV4AddressString(),
...@@ -467,7 +510,7 @@ internal class GroupImpl( ...@@ -467,7 +510,7 @@ internal class GroupImpl(
return CustomFaceFromFile( return CustomFaceFromFile(
md5 = image.md5, md5 = image.md5,
filepath = resourceId filepath = resourceId
) ).also { ImageUploadEvent.Succeed(this@GroupImpl, image, it).broadcast() }
/* /*
fileId = response.fileId.toInt(), fileId = response.fileId.toInt(),
fileType = 0, // ? fileType = 0, // ?
......
...@@ -27,7 +27,6 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY ...@@ -27,7 +27,6 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement.GetGroupOperationInfo.decode
import net.mamoe.mirai.utils.daysToSeconds import net.mamoe.mirai.utils.daysToSeconds
import net.mamoe.mirai.utils.io.encodeToString import net.mamoe.mirai.utils.io.encodeToString
...@@ -66,9 +65,7 @@ internal class TroopManagement { ...@@ -66,9 +65,7 @@ internal class TroopManagement {
} }
object Response : Packet { object Response : Packet {
override fun toString(): String { override fun toString(): String = "Response(Mute)"
return "Response(Mute)"
}
} }
} }
...@@ -80,9 +77,7 @@ internal class TroopManagement { ...@@ -80,9 +77,7 @@ internal class TroopManagement {
val autoApprove: Boolean, val autoApprove: Boolean,
val confessTalk: Boolean val confessTalk: Boolean
) : Packet { ) : Packet {
override fun toString(): String { override fun toString(): String = "Response(GroupInfo)"
return "Response(GroupInfo)"
}
} }
operator fun invoke( operator fun invoke(
...@@ -146,9 +141,7 @@ internal class TroopManagement { ...@@ -146,9 +141,7 @@ internal class TroopManagement {
class Response( class Response(
val success: Boolean val success: Boolean
) : Packet { ) : Packet {
override fun toString(): String { override fun toString(): String = "Response(Kick Member)"
return "Response(Kick Member)"
}
} }
operator fun invoke( operator fun invoke(
...@@ -424,13 +417,4 @@ internal class TroopManagement { ...@@ -424,13 +417,4 @@ internal class TroopManagement {
} }
} }
/*
internal object Recall: OutgoingPacketFactory<WtLogin.Login.LoginPacketResponse>("wtlogin.login"){
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): WtLogin.Login.LoginPacketResponse {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
*/
} }
\ No newline at end of file
...@@ -13,6 +13,10 @@ package net.mamoe.mirai.contact ...@@ -13,6 +13,10 @@ package net.mamoe.mirai.contact
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.BeforeImageUploadEvent
import net.mamoe.mirai.event.events.ImageUploadEvent
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.ExternalImage import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.WeakRefProperty import net.mamoe.mirai.utils.WeakRefProperty
...@@ -40,6 +44,9 @@ interface Contact : CoroutineScope { ...@@ -40,6 +44,9 @@ interface Contact : CoroutineScope {
/** /**
* 向这个对象发送消息. * 向这个对象发送消息.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
*/ */
suspend fun sendMessage(message: MessageChain) suspend fun sendMessage(message: MessageChain)
...@@ -47,6 +54,9 @@ interface Contact : CoroutineScope { ...@@ -47,6 +54,9 @@ interface Contact : CoroutineScope {
* 上传一个图片以备发送. * 上传一个图片以备发送.
* TODO: 群图片与好友图片之间是否通用还不确定. * TODO: 群图片与好友图片之间是否通用还不确定.
* TODO: 好友之间图片是否通用还不确定. * TODO: 好友之间图片是否通用还不确定.
*
* @see BeforeImageUploadEvent 图片发送前事件, cancellable
* @see ImageUploadEvent 图片发送完成事件
*/ */
suspend fun uploadImage(image: ExternalImage): Image suspend fun uploadImage(image: ExternalImage): Image
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
package net.mamoe.mirai.contact package net.mamoe.mirai.contact
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiExperimentalAPI
/** /**
...@@ -22,32 +23,41 @@ interface Group : Contact, CoroutineScope { ...@@ -22,32 +23,41 @@ interface Group : Contact, CoroutineScope {
* 群名称. * 群名称.
* *
* 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException] * 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException]
* 频繁修改可能会被服务器拒绝.
* *
* 注: 频繁修改可能会被服务器拒绝. * @see MemberPermissionChangeEvent
*/ */
var name: String var name: String
/** /**
* 入群公告, 没有时为空字符串. * 入群公告, 没有时为空字符串.
* *
* 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException] * 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException]
*
* @see GroupEntranceAnnouncementChangeEvent
*/ */
var announcement: String var entranceAnnouncement: String
/** /**
* 全体禁言状态. `true` 为开启. * 全体禁言状态. `true` 为开启.
* *
* 当前仅能修改状态. * 当前仅能修改状态.
*
* @see GroupMuteAllEvent
*/// TODO: 2020/2/5 实现 muteAll 的查询 */// TODO: 2020/2/5 实现 muteAll 的查询
var muteAll: Boolean var muteAll: Boolean
/** /**
* 坦白说状态. `true` 为允许. * 坦白说状态. `true` 为允许.
* *
* 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException] * 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException]
* @see GroupAllowConfessTalkEvent
*/ */
var confessTalk: Boolean var confessTalk: Boolean
/** /**
* 允许群员邀请好友入群的状态. `true` 为允许 * 允许群员邀请好友入群的状态. `true` 为允许
* *
* 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException] * 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException]
*
* @see GroupAllowMemberInviteEvent
*/ */
var allowMemberInvite: Boolean var allowMemberInvite: Boolean
/** /**
...@@ -74,6 +84,8 @@ interface Group : Contact, CoroutineScope { ...@@ -74,6 +84,8 @@ interface Group : Contact, CoroutineScope {
* 机器人在这个群里的权限 * 机器人在这个群里的权限
* *
* **MiraiExperimentalAPI**: 在未来可能会被修改 * **MiraiExperimentalAPI**: 在未来可能会被修改
*
* @see BotGroupPermissionChangeEvent
*/ */
@MiraiExperimentalAPI @MiraiExperimentalAPI
val botPermission: MemberPermission val botPermission: MemberPermission
......
...@@ -13,6 +13,9 @@ package net.mamoe.mirai.contact ...@@ -13,6 +13,9 @@ package net.mamoe.mirai.contact
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.MemberCardChangeEvent import net.mamoe.mirai.event.events.MemberCardChangeEvent
import net.mamoe.mirai.event.events.MemberLeaveEvent
import net.mamoe.mirai.event.events.MemberMuteEvent
import net.mamoe.mirai.event.events.MemberSpecialTitleChangeEvent
import net.mamoe.mirai.utils.WeakRefProperty import net.mamoe.mirai.utils.WeakRefProperty
import kotlin.time.Duration import kotlin.time.Duration
import kotlin.time.ExperimentalTime import kotlin.time.ExperimentalTime
...@@ -38,6 +41,7 @@ interface Member : QQ, Contact { ...@@ -38,6 +41,7 @@ interface Member : QQ, Contact {
* 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException] * 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException]
* *
* @see [groupCardOrNick] 获取非空群名片或昵称 * @see [groupCardOrNick] 获取非空群名片或昵称
*
* @see MemberCardChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件 * @see MemberCardChangeEvent 群名片被管理员, 自己或 [Bot] 改动事件
*/ */
var nameCard: String var nameCard: String
...@@ -55,7 +59,7 @@ interface Member : QQ, Contact { ...@@ -55,7 +59,7 @@ interface Member : QQ, Contact {
* 禁言 * 禁言
* *
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常. * @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
* @return 当机器人无权限禁言这个群成员时返回 `false` * @return 机器人无权限时返回 `false`
* *
* @see Int.minutesToSeconds * @see Int.minutesToSeconds
* @see Int.hoursToSeconds * @see Int.hoursToSeconds
...@@ -64,12 +68,16 @@ interface Member : QQ, Contact { ...@@ -64,12 +68,16 @@ interface Member : QQ, Contact {
suspend fun mute(durationSeconds: Int): Boolean suspend fun mute(durationSeconds: Int): Boolean
/** /**
* 解除禁言. 在没有权限时会返回 `false`. * 解除禁言. 机器人无权限时返回 `false`.
*
* @see MemberMuteEvent 成员被禁言事件.
*/ */
suspend fun unmute(): Boolean suspend fun unmute(): Boolean
/** /**
* 踢出该成员. 机器人无权限时返回 `false` * 踢出该成员. 机器人无权限时返回 `false`.
*
* @see MemberLeaveEvent.Kick 成员被踢出事件.
*/ */
suspend fun kick(message: String = ""): Boolean suspend fun kick(message: String = ""): Boolean
......
...@@ -16,6 +16,7 @@ import net.mamoe.mirai.Bot ...@@ -16,6 +16,7 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.data.FriendNameRemark import net.mamoe.mirai.data.FriendNameRemark
import net.mamoe.mirai.data.PreviousNameList import net.mamoe.mirai.data.PreviousNameList
import net.mamoe.mirai.data.Profile import net.mamoe.mirai.data.Profile
import net.mamoe.mirai.utils.MiraiExperimentalAPI
/** /**
* QQ 对象. * QQ 对象.
...@@ -49,6 +50,7 @@ interface QQ : Contact, CoroutineScope { ...@@ -49,6 +50,7 @@ interface QQ : Contact, CoroutineScope {
/** /**
* 查询用户资料 * 查询用户资料
*/ */
@MiraiExperimentalAPI("还未支持")
suspend fun queryProfile(): Profile suspend fun queryProfile(): Profile
/** /**
...@@ -58,10 +60,12 @@ interface QQ : Contact, CoroutineScope { ...@@ -58,10 +60,12 @@ interface QQ : Contact, CoroutineScope {
* - 昵称 * - 昵称
* - 共同群内的群名片 * - 共同群内的群名片
*/ */
@MiraiExperimentalAPI("还未支持")
suspend fun queryPreviousNameList(): PreviousNameList suspend fun queryPreviousNameList(): PreviousNameList
/** /**
* 查询机器人账号给这个人设置的备注 * 查询机器人账号给这个人设置的备注
*/ */
@MiraiExperimentalAPI("还未支持")
suspend fun queryRemark(): FriendNameRemark suspend fun queryRemark(): FriendNameRemark
} }
\ No newline at end of file
...@@ -70,6 +70,9 @@ abstract class AbstractCancellableEvent : Event, CancellableEvent { ...@@ -70,6 +70,9 @@ abstract class AbstractCancellableEvent : Event, CancellableEvent {
*/ */
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
suspend fun <E : Event> E.broadcast(): E = apply { suspend fun <E : Event> E.broadcast(): E = apply {
if (this is BroadcastControllable && !this.shouldBroadcast) {
return@apply
}
if (this is BotEvent && !(this.bot as BotImpl<*>).onEvent(this)) { if (this is BotEvent && !(this.bot as BotImpl<*>).onEvent(this)) {
return@apply return@apply
} }
......
...@@ -10,9 +10,21 @@ ...@@ -10,9 +10,21 @@
package net.mamoe.mirai.event.events package net.mamoe.mirai.event.events
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.*
import net.mamoe.mirai.contact.Member import net.mamoe.mirai.event.AbstractCancellableEvent
import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.event.CancellableEvent
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.utils.ExternalImage
@Suppress("unused")
class EventCancelledException : RuntimeException {
constructor() : super()
constructor(message: String?) : super(message)
constructor(message: String?, cause: Throwable?) : super(message, cause)
constructor(cause: Throwable?) : super(cause)
}
// region Bot 状态 // region Bot 状态
...@@ -40,6 +52,64 @@ sealed class BotOfflineEvent : BotActiveEvent { ...@@ -40,6 +52,64 @@ sealed class BotOfflineEvent : BotActiveEvent {
// endregion // endregion
// region 消息
sealed class MessageSendEvent : BotEvent, BotActiveEvent, AbstractCancellableEvent() {
abstract val target: Contact
final override val bot: Bot
get() = target.bot
data class GroupMessageSendEvent(
override val target: Group,
var message: MessageChain
) : MessageSendEvent(), CancellableEvent
data class FriendMessageSendEvent(
override val target: QQ,
var message: MessageChain
) : MessageSendEvent(), CancellableEvent
}
// endregion
// region 图片
/**
* 图片上传前. 可以阻止上传
*/
data class BeforeImageUploadEvent(
val target: Contact,
val source: ExternalImage
) : BotEvent, BotActiveEvent, AbstractCancellableEvent() {
override val bot: Bot
get() = target.bot
}
/**
* 图片上传完成
*/
sealed class ImageUploadEvent : BotEvent, BotActiveEvent, AbstractCancellableEvent() {
abstract val target: Contact
abstract val source: ExternalImage
override val bot: Bot
get() = target.bot
data class Succeed(
override val target: Contact,
override val source: ExternalImage,
val image: Image
) : ImageUploadEvent(), CancellableEvent
data class Failed(
override val target: Contact,
override val source: ExternalImage,
val errno: Int,
val message: String
) : ImageUploadEvent(), CancellableEvent
}
// endregion
// region 群 // region 群
/** /**
...@@ -64,8 +134,7 @@ interface GroupSettingChangeEvent<T> : GroupEvent, BotPassiveEvent { ...@@ -64,8 +134,7 @@ interface GroupSettingChangeEvent<T> : GroupEvent, BotPassiveEvent {
/** /**
* 群名改变. 此事件广播前修改就已经完成. * 群名改变. 此事件广播前修改就已经完成.
*/ */
sealed class GroupNameChangeEvent( sealed class GroupNameChangeEvent : GroupSettingChangeEvent<String>, BotPassiveEvent {
) : GroupSettingChangeEvent<String>, BotPassiveEvent {
/** /**
* 由管理员操作 * 由管理员操作
...@@ -89,6 +158,34 @@ sealed class GroupNameChangeEvent( ...@@ -89,6 +158,34 @@ sealed class GroupNameChangeEvent(
) : GroupNameChangeEvent() ) : GroupNameChangeEvent()
} }
/**
* 入群公告改变. 此事件广播前修改就已经完成.
*/
sealed class GroupEntranceAnnouncementChangeEvent : GroupSettingChangeEvent<String>, BotPassiveEvent {
/**
* 由管理员操作
*/
data class ByOperator(
override val origin: String,
override val new: String,
val operator: Member
) : GroupEntranceAnnouncementChangeEvent() {
override val group: Group
get() = operator.group
}
/**
* 由机器人操作
*/
data class ByBot(
override val origin: String,
override val new: String,
override val group: Group
) : GroupEntranceAnnouncementChangeEvent()
}
/** /**
* 群 "全员禁言" 功能状态改变. 此事件广播前修改就已经完成. * 群 "全员禁言" 功能状态改变. 此事件广播前修改就已经完成.
*/ */
...@@ -118,8 +215,33 @@ sealed class GroupMuteAllEvent : GroupSettingChangeEvent<Boolean>, BotPassiveEve ...@@ -118,8 +215,33 @@ sealed class GroupMuteAllEvent : GroupSettingChangeEvent<Boolean>, BotPassiveEve
/** /**
* 群 "坦白说" 功能状态改变. 此事件广播前修改就已经完成. * 群 "坦白说" 功能状态改变. 此事件广播前修改就已经完成.
*/ */
sealed class GroupConfessTalkEvent : GroupSettingChangeEvent<Boolean>, BotPassiveEvent { sealed class GroupAllowConfessTalkEvent : GroupSettingChangeEvent<Boolean>, BotPassiveEvent {
/**
* 由管理员操作
*/
data class ByOperator(
override val origin: Boolean,
override val new: Boolean,
val operator: Member
) : GroupAllowConfessTalkEvent() {
override val group: Group
get() = operator.group
}
/**
* 由机器人操作
*/
data class ByBot(
override val origin: Boolean,
override val new: Boolean,
override val group: Group
) : GroupAllowConfessTalkEvent()
}
/**
* 群 "允许群员邀请好友加群" 功能状态改变. 此事件广播前修改就已经完成.
*/
sealed class GroupAllowMemberInviteEvent : GroupSettingChangeEvent<Boolean>, BotPassiveEvent {
/** /**
* 由管理员操作 * 由管理员操作
*/ */
...@@ -127,7 +249,7 @@ sealed class GroupConfessTalkEvent : GroupSettingChangeEvent<Boolean>, BotPassiv ...@@ -127,7 +249,7 @@ sealed class GroupConfessTalkEvent : GroupSettingChangeEvent<Boolean>, BotPassiv
override val origin: Boolean, override val origin: Boolean,
override val new: Boolean, override val new: Boolean,
val operator: Member val operator: Member
) : GroupConfessTalkEvent() { ) : GroupAllowMemberInviteEvent() {
override val group: Group override val group: Group
get() = operator.group get() = operator.group
} }
...@@ -139,7 +261,7 @@ sealed class GroupConfessTalkEvent : GroupSettingChangeEvent<Boolean>, BotPassiv ...@@ -139,7 +261,7 @@ sealed class GroupConfessTalkEvent : GroupSettingChangeEvent<Boolean>, BotPassiv
override val origin: Boolean, override val origin: Boolean,
override val new: Boolean, override val new: Boolean,
override val group: Group override val group: Group
) : GroupConfessTalkEvent() ) : GroupAllowMemberInviteEvent()
} }
// endregion // endregion
...@@ -157,11 +279,11 @@ data class MemberJoinEvent(override val member: Member) : GroupMemberEvent, BotP ...@@ -157,11 +279,11 @@ data class MemberJoinEvent(override val member: Member) : GroupMemberEvent, BotP
/** /**
* 成员离开群的事件 * 成员离开群的事件
*/ */
sealed class MemberLeftEvent : GroupMemberEvent { sealed class MemberLeaveEvent : GroupMemberEvent {
/** /**
* 成员被踢出群. 成员不可能是机器人自己. * 成员被踢出群. 成员不可能是机器人自己.
*/ */
sealed class Kick : MemberLeftEvent() { sealed class Kick : MemberLeaveEvent() {
/** /**
* 被管理员踢出 * 被管理员踢出
*/ */
...@@ -181,7 +303,7 @@ sealed class MemberLeftEvent : GroupMemberEvent { ...@@ -181,7 +303,7 @@ sealed class MemberLeftEvent : GroupMemberEvent {
/** /**
* 成员主动离开 * 成员主动离开
*/ */
data class Quit(override val member: Member) : MemberLeftEvent() data class Quit(override val member: Member) : MemberLeaveEvent()
} }
// endregion // endregion
......
...@@ -81,14 +81,6 @@ suspend fun main() { ...@@ -81,14 +81,6 @@ suspend fun main() {
"你好" reply "你好!" "你好" reply "你好!"
startsWith("profile", removePrefix = true) {
val account = it.trim()
if (account.isNotEmpty()) {
bot.getFriend(account.toLong())
} else {
sender
}.queryProfile().toString().reply()
}
"grouplist" reply { "grouplist" reply {
//"https://ssl.ptlogin2.qq.com/jump?pt_clientver=5509&pt_src=1&keyindex=9&clientuin=" + bot.qqAccount + "&clientkey=" + com.tick_tock.pctim.utils.Util.byte2HexString( //"https://ssl.ptlogin2.qq.com/jump?pt_clientver=5509&pt_src=1&keyindex=9&clientuin=" + bot.qqAccount + "&clientkey=" + com.tick_tock.pctim.utils.Util.byte2HexString(
......
...@@ -52,7 +52,7 @@ internal class BlockingGroupImpl(private val delegate: Group) : BlockingGroup { ...@@ -52,7 +52,7 @@ internal class BlockingGroupImpl(private val delegate: Group) : BlockingGroup {
override fun toFullString(): String = delegate.toFullString() override fun toFullString(): String = delegate.toFullString()
override fun getMember(id: Long): BlockingMember = delegate[id].blocking() override fun getMember(id: Long): BlockingMember = delegate[id].blocking()
override fun getBot(): BlockingBot = delegate.bot.blocking() override fun getBot(): BlockingBot = delegate.bot.blocking()
override fun getAnnouncement(): String = delegate.announcement override fun getAnnouncement(): String = delegate.entranceAnnouncement
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
override fun getMembers(): Map<Long, BlockingMember> = override fun getMembers(): Map<Long, BlockingMember> =
delegate.members.delegate.toList().associateBy { it.id }.mapValues { it.value.blocking() } delegate.members.delegate.toList().associateBy { it.id }.mapValues { it.value.blocking() }
......
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