Bot factory

This commit is contained in:
Him188 2020-01-31 21:49:48 +08:00
parent 0c90b39c8d
commit f9cf47a19a
18 changed files with 106 additions and 49 deletions

View File

@ -0,0 +1,18 @@
package net.mamoe.mirai.qqandroid
import net.mamoe.mirai.Bot
import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.BotFactory
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.MiraiInternalAPI
/**
* QQ for Android
*/
actual object QQAndroid : BotFactory {
@UseExperimental(MiraiInternalAPI::class)
override fun Bot(context: Context, qq: Long, password: String, configuration: BotConfiguration): Bot {
return QQAndroidBot(context, BotAccount(qq, password), configuration)
}
}

View File

@ -1,8 +1,8 @@
package net.mamoe.mirai.qqandroid
import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.qqandroid.utils.Context
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
internal actual class QQAndroidBot actual constructor(
context: Context,

View File

@ -0,0 +1,8 @@
package net.mamoe.mirai.qqandroid
import net.mamoe.mirai.BotFactory
/**
* QQ for Android
*/
expect object QQAndroid : BotFactory

View File

@ -8,9 +8,9 @@ import net.mamoe.mirai.data.ImageLink
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.utils.Context
import net.mamoe.mirai.qqandroid.utils.ImageIdQQA
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.LockFreeLinkedList
import net.mamoe.mirai.utils.MiraiInternalAPI
import kotlin.coroutines.CoroutineContext

View File

@ -370,7 +370,9 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
}
override fun dispose(cause: Throwable?) {
channel.close()
if (::channel.isInitialized) {
channel.close()
}
super.dispose(cause)
}

View File

@ -11,7 +11,6 @@ import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketLogger
import net.mamoe.mirai.qqandroid.network.protocol.packet.Tlv
import net.mamoe.mirai.qqandroid.utils.Context
import net.mamoe.mirai.qqandroid.utils.DeviceInfo
import net.mamoe.mirai.qqandroid.utils.NetworkType
import net.mamoe.mirai.qqandroid.utils.SystemDeviceInfo

View File

@ -3,6 +3,7 @@ package net.mamoe.mirai.qqandroid.utils
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import net.mamoe.mirai.qqandroid.io.serialization.ProtoBufWithNullableSupport
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.cryptor.contentToString
import net.mamoe.mirai.utils.getValue
import net.mamoe.mirai.utils.unsafeWeakRef

View File

@ -1,5 +1,7 @@
package net.mamoe.mirai.qqandroid.utils
import net.mamoe.mirai.utils.Context
/**
* System default values
*/

View File

@ -0,0 +1,30 @@
@file:Suppress("FunctionName")
package net.mamoe.mirai.qqandroid
import net.mamoe.mirai.Bot
import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.BotFactory
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.MiraiInternalAPI
/**
* QQ for Android
*/
@UseExperimental(MiraiInternalAPI::class)
actual object QQAndroid : BotFactory {
override fun Bot(context: Context, qq: Long, password: String, configuration: BotConfiguration): Bot {
return QQAndroidBot(context, BotAccount(qq, password), configuration)
}
fun Bot(qq: Long, password: String, configuration: BotConfiguration = BotConfiguration.Default): Bot =
QQAndroidBot(BotAccount(qq, password), configuration)
}
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
inline fun QQAndroid.Bot(qq: Long, password: String, configuration: (BotConfiguration.() -> Unit)): Bot =
this.Bot(qq, password, BotConfiguration().apply(configuration))

View File

@ -1,13 +1,16 @@
package net.mamoe.mirai.qqandroid
import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.qqandroid.utils.Context
import net.mamoe.mirai.qqandroid.utils.ContextImpl
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.ContextImpl
import net.mamoe.mirai.utils.MiraiInternalAPI
@UseExperimental(MiraiInternalAPI::class)
@Suppress("FunctionName")
internal fun QQAndroidBot(account: BotAccount, configuration: BotConfiguration): QQAndroidBot = QQAndroidBot(ContextImpl(), account, configuration)
@UseExperimental(MiraiInternalAPI::class)
internal actual class QQAndroidBot actual constructor(
context: Context,
account: BotAccount,

View File

@ -1,6 +1,7 @@
package net.mamoe.mirai.qqandroid.utils
import kotlinx.io.core.toByteArray
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.localIpAddress
actual class SystemDeviceInfo actual constructor(context: Context) : DeviceInfo(context) {
@ -39,8 +40,4 @@ actual class SystemDeviceInfo actual constructor(context: Context) : DeviceInfo(
override val codename: ByteArray get() = "REL".toByteArray()
override val sdk: Int get() = 29
}
}
actual abstract class Context
open class ContextImpl : Context()
}

View File

@ -7,13 +7,21 @@ import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.BotFactory
import net.mamoe.mirai.timpc.TIMPC.Bot
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.MiraiInternalAPI
/**
* TIM PC 协议的 [Bot] 构造器.
*/
@UseExperimental(MiraiInternalAPI::class)
object TIMPC : BotFactory {
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
override fun Bot(account: BotAccount, configuration: BotConfiguration): Bot = TIMPCBot(account, configuration)
override fun Bot(context: Context, qq: Long, password: String, configuration: BotConfiguration): Bot = TIMPCBot(BotAccount(qq, password), configuration)
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
fun Bot(qq: Long, password: String, configuration: BotConfiguration): Bot = TIMPCBot(BotAccount(qq, password), configuration)
}

View File

@ -1,3 +1,3 @@
package net.mamoe.mirai.qqandroid.utils
package net.mamoe.mirai.utils
actual typealias Context = android.content.Context

View File

@ -3,9 +3,11 @@
package net.mamoe.mirai
import kotlinx.io.core.toByteArray
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.md5
import kotlin.annotation.AnnotationTarget.*
@MiraiInternalAPI
data class BotAccount(
/**
* **注意**: Android 协议, 总是使用 `QQAndroidClient.uin` [Bot.uin], 而不要使用 [BotAccount.id]. 将来 [BotAccount.id] 可能会变为 [String]
@ -23,4 +25,4 @@ data class BotAccount(
@Retention(AnnotationRetention.SOURCE)
@Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR)
@Experimental(level = Experimental.Level.WARNING)
annotation class RawAccountIdUse
internal annotation class RawAccountIdUse

View File

@ -3,6 +3,9 @@
package net.mamoe.mirai
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
/**
* 构造 [Bot] 的工厂.
@ -15,23 +18,11 @@ interface BotFactory {
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
fun Bot(account: BotAccount, configuration: BotConfiguration = BotConfiguration.Default): Bot
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
fun Bot(qq: Long, password: String, configuration: BotConfiguration = BotConfiguration.Default): Bot =
this.Bot(BotAccount(qq, password), configuration)
fun Bot(context: Context, qq: Long, password: String, configuration: BotConfiguration = BotConfiguration.Default): Bot
}
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
inline fun BotFactory.Bot(account: BotAccount, configuration: (BotConfiguration.() -> Unit)): Bot=
this.Bot(account, BotConfiguration().apply(configuration))
/**
* 使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
inline fun BotFactory.Bot(qq: Long, password: String, configuration: (BotConfiguration.() -> Unit)): Bot =
this.Bot(qq, password, BotConfiguration().apply(configuration))
inline fun BotFactory.Bot(context: Context, qq: Long, password: String, configuration: (BotConfiguration.() -> Unit)): Bot =
this.Bot(context, qq, password, BotConfiguration().apply(configuration))

View File

@ -1,4 +1,4 @@
package net.mamoe.mirai.qqandroid.utils
package net.mamoe.mirai.utils
/**
* On Android, typealias to `android.content.Context`

View File

@ -3,14 +3,17 @@
package net.mamoe.mirai
import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context
// Do not use ServiceLoader. Probably not working on MPP
@PublishedApi
internal val factory: BotFactory = run {
try {
runCatching {
Class.forName("net.mamoe.mirai.timpc.TIMPC").kotlin.objectInstance as BotFactory
} catch (ignored: Exception) {
null
}.getOrElse {
runCatching {
Class.forName("net.mamoe.mirai.qqandroid.QQAndroid").kotlin.objectInstance as BotFactory
}.getOrNull()
}
} ?: error(
"""
@ -24,23 +27,11 @@ internal val factory: BotFactory = run {
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
fun Bot(account: BotAccount, configuration: BotConfiguration = BotConfiguration.Default): Bot =
factory.Bot(account, configuration)
fun Bot(context: Context, qq: Long, password: String, configuration: BotConfiguration = BotConfiguration.Default): Bot =
factory.Bot(context, qq, password, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
fun Bot(qq: Long, password: String, configuration: BotConfiguration = BotConfiguration.Default): Bot =
factory.Bot(qq, password, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
inline fun Bot(account: BotAccount, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(account, configuration)
/**
* 加载现有协议的 [BotFactory], 并使用指定的 [配置][configuration] 构造 [Bot] 实例
*/
inline fun Bot(qq: Long, password: String, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(qq, password, configuration)
inline fun Bot(context: Context, qq: Long, password: String, configuration: (BotConfiguration.() -> Unit)): Bot =
factory.Bot(context, qq, password, configuration)

View File

@ -0,0 +1,5 @@
package net.mamoe.mirai.utils
actual abstract class Context
open class ContextImpl : Context()