diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt index b070224bb..47ae5a1c3 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -9,7 +9,10 @@ import net.mamoe.mirai.Bot.ContactSystem import net.mamoe.mirai.contact.* import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler +import net.mamoe.mirai.network.protocol.tim.packet.action.CanAddFriendPacket +import net.mamoe.mirai.network.protocol.tim.packet.action.CanAddFriendResponse import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult +import net.mamoe.mirai.network.sessionKey import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.DefaultLogger import net.mamoe.mirai.utils.MiraiLogger @@ -90,6 +93,8 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) { * @see Bot.contacts */ inner class ContactSystem internal constructor() { + inline val bot: Bot get() = this@Bot + private val _groups = ContactList() private lateinit var groupsUpdater: Job val groups = ContactList() @@ -108,7 +113,7 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) { suspend fun getQQ(id: UInt): QQ = if (qqs.containsKey(id)) qqs[id]!! else qqsLock.withLock { - qqs.getOrPut(id) { QQ(this@Bot, id) } + qqs.getOrPut(id) { QQ(bot, id) } } /** @@ -126,7 +131,7 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) { suspend fun getGroup(id: GroupId): Group = id.value.let { if (groups.containsKey(it)) groups[it]!! else groupsLock.withLock { - groups.getOrPut(it) { Group(this@Bot, id) } + groups.getOrPut(it) { Group(bot, id) } } } @@ -153,7 +158,19 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) { } } +suspend fun ContactSystem.canAddFriend(id: UInt): CanAddFriendResponse = + bot.withSession { + CanAddFriendPacket(bot.qqAccount, id, bot.sessionKey).sendAndExpect().await() + } + /** * 添加一个好友 + * + * @param lazyMessage 若需要验证请求时的验证消息. */ -suspend fun ContactSystem.addFriend(id: UInt): Nothing = TODO() \ No newline at end of file +suspend fun ContactSystem.addFriend(id: UInt, lazyMessage: () -> String = { "" }): Boolean = when (this.canAddFriend(id)) { + is CanAddFriendResponse.AlreadyAdded -> false + is CanAddFriendResponse.Rejected -> false + is CanAddFriendResponse.RequireVerification -> TODO() + is CanAddFriendResponse.ReadyToAdd -> TODO() +} diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt index 7be94d166..c6f4936f1 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt @@ -6,11 +6,13 @@ import net.mamoe.mirai.contact.* import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.BotSession import net.mamoe.mirai.network.protocol.tim.packet.OutgoingPacket +import net.mamoe.mirai.network.protocol.tim.packet.action.CanAddFriendResponse import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult import net.mamoe.mirai.network.session import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.internal.PositiveNumbers import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail +import kotlin.jvm.JvmOverloads /* * 在 [Bot] 中的方法的捷径 @@ -18,6 +20,7 @@ import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail //Contacts suspend inline fun Bot.getQQ(@PositiveNumbers number: Long): QQ = this.contacts.getQQ(number.coerceAtLeastOrFail(0).toUInt()) + suspend inline fun Bot.getQQ(number: UInt): QQ = this.contacts.getQQ(number) suspend inline fun Bot.getGroup(id: UInt): Group = this.contacts.getGroup(GroupId(id)) @@ -59,6 +62,17 @@ suspend inline fun Bot.login(noinline configuration: BotConfiguration.() -> Unit */ suspend inline fun Bot.login(): LoginResult = this.network.login(BotConfiguration.Default) +/** + * 得到可否添加这个人为好友 + */ +suspend inline fun Bot.canAddFriend(id: UInt): CanAddFriendResponse = this.contacts.canAddFriend(id) + +/** + * 添加好友 + */ +@JvmOverloads +suspend inline fun Bot.addFriend(id: UInt, noinline lazyMessage: () -> String = { "" }) = this.contacts.addFriend(id, lazyMessage) + /** * 取得机器人的 QQ 号 */ diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt index 962aed329..f90b2230c 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt @@ -6,6 +6,12 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import net.mamoe.mirai.Bot +import net.mamoe.mirai.contact.Group +import net.mamoe.mirai.contact.GroupId +import net.mamoe.mirai.contact.GroupInternalId +import net.mamoe.mirai.contact.QQ +import net.mamoe.mirai.getGroup +import net.mamoe.mirai.getQQ import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler import net.mamoe.mirai.network.protocol.tim.handler.ActionPacketHandler import net.mamoe.mirai.network.protocol.tim.handler.DataPacketSocketAdapter @@ -13,7 +19,10 @@ import net.mamoe.mirai.network.protocol.tim.handler.TemporaryPacketHandler import net.mamoe.mirai.network.protocol.tim.packet.OutgoingPacket import net.mamoe.mirai.network.protocol.tim.packet.Packet import net.mamoe.mirai.network.protocol.tim.packet.SessionKey +import net.mamoe.mirai.sendPacket import net.mamoe.mirai.utils.getGTK +import net.mamoe.mirai.utils.internal.PositiveNumbers +import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail import kotlin.coroutines.coroutineContext /** @@ -100,6 +109,17 @@ class BotSession( sendAndExpect(checkSequence) { it } suspend inline fun OutgoingPacket.send() = socket.sendPacket(this) + + + suspend inline fun Int.qq(): QQ = bot.getQQ(this.coerceAtLeastOrFail(0).toUInt()) + suspend inline fun Long.qq(): QQ = bot.getQQ(this.coerceAtLeastOrFail(0)) + suspend inline fun UInt.qq(): QQ = bot.getQQ(this) + + suspend inline fun Int.group(): Group = bot.getGroup(this.coerceAtLeastOrFail(0).toUInt()) + suspend inline fun Long.group(): Group = bot.getGroup(this.coerceAtLeastOrFail(0)) + suspend inline fun UInt.group(): Group = bot.getGroup(GroupId(this)) + suspend inline fun GroupId.group(): Group = bot.getGroup(this) + suspend inline fun GroupInternalId.group(): Group = bot.getGroup(this) } @@ -128,4 +148,20 @@ inline val Bot.session: BotSession get() = this.network.session * 取得 [Bot] 的 `sessionKey`. * 实际上是一个捷径. */ -inline val Bot.sessionKey: SessionKey get() = this.session.sessionKey \ No newline at end of file +inline val Bot.sessionKey: SessionKey get() = this.session.sessionKey + + +/** + * 发送数据包 + * @throws IllegalStateException 当 [BotNetworkHandler.socket] 未开启时 + */ +suspend inline fun BotSession.sendPacket(packet: OutgoingPacket) = this.bot.sendPacket(packet) + + +suspend inline fun BotSession.getQQ(@PositiveNumbers number: Long): QQ = this.bot.getQQ(number) +suspend inline fun BotSession.getQQ(number: UInt): QQ = this.bot.getQQ(number) + +suspend inline fun BotSession.getGroup(id: UInt): Group = this.bot.getGroup(id) +suspend inline fun BotSession.getGroup(@PositiveNumbers id: Long): Group = this.bot.getGroup(id) +suspend inline fun BotSession.getGroup(id: GroupId): Group = this.bot.getGroup(id) +suspend inline fun BotSession.getGroup(internalId: GroupInternalId): Group = this.bot.getGroup(internalId) \ No newline at end of file