mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-26 20:20:14 +08:00
Merge remote-tracking branch 'origin/dev' into StageGuard_dev
# Conflicts: # mirai-core-api/src/jvmMain/kotlin/utils/LoginSolver.jvm.kt
This commit is contained in:
commit
44a3472b3e
@ -205,6 +205,9 @@ public class StandardCharImageLoginSolver @JvmOverloads constructor(
|
||||
logger.info { "[SliderCaptcha] @see https://docs.mirai.mamoe.net/mirai-login-solver-selenium/" }
|
||||
logger.info { "[SliderCaptcha] 或者输入 TxCaptchaHelper 来使用 TxCaptchaHelper 完成滑动验证码" }
|
||||
logger.info { "[SliderCaptcha] Or type `TxCaptchaHelper` to resolve slider captcha with TxCaptchaHelper.apk" }
|
||||
logger.warning { "[SliderCaptcha] TxCaptchaHelper 的在线服务疑似被屏蔽,可能无法使用。TxCaptchaHelper 现已无法满足登录QQ机器人,请在以下链接下载全新的验证器" }
|
||||
logger.warning { "[SliderCaptcha] The service of `TxCaptchaHelper` might be blocked. We recommend you to download the new login solver plugin in below link." }
|
||||
logger.warning { "[SliderCaptcha] @see https://github.com/KasukuSakura/mirai-login-solver-sakura" }
|
||||
logger.info { "[SliderCaptcha] Captcha link: $url" }
|
||||
|
||||
suspend fun runTxCaptchaHelper(): String {
|
||||
|
@ -11,9 +11,76 @@
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import kotlinx.atomicfu.locks.reentrantLock
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import kotlin.jvm.JvmName
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
public object Services {
|
||||
private val lock = reentrantLock()
|
||||
public fun <T : Any> qualifiedNameOrFail(clazz: KClass<out T>): String =
|
||||
clazz.qualifiedName ?: error("Could not find qualifiedName for $clazz")
|
||||
|
||||
internal class Implementation(
|
||||
val implementationClass: String,
|
||||
val instance: Lazy<Any>
|
||||
)
|
||||
|
||||
private val registered: MutableMap<String, MutableList<Implementation>> = mutableMapOf()
|
||||
private val overrided: MutableMap<String, Implementation> = mutableMapOf()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun <T : Any> getOverrideOrNull(clazz: KClass<out T>): T? {
|
||||
lock.withLock {
|
||||
return overrided[qualifiedNameOrFail(clazz)]?.instance?.value as T?
|
||||
}
|
||||
}
|
||||
|
||||
internal fun registerAsOverride(baseClass: String, implementationClass: String, implementation: () -> Any) {
|
||||
lock.withLock {
|
||||
overrided[baseClass] = Implementation(implementationClass, lazy(implementation))
|
||||
}
|
||||
}
|
||||
|
||||
public fun register(baseClass: String, implementationClass: String, implementation: () -> Any) {
|
||||
lock.withLock {
|
||||
registered.getOrPut(baseClass, ::mutableListOf)
|
||||
.add(Implementation(implementationClass, lazy(implementation)))
|
||||
}
|
||||
}
|
||||
|
||||
public fun firstImplementationOrNull(baseClass: String): Any? {
|
||||
lock.withLock {
|
||||
overrided[baseClass]?.let { return it.instance.value }
|
||||
return registered[baseClass]?.firstOrNull()?.instance?.value
|
||||
}
|
||||
}
|
||||
|
||||
public fun implementations(baseClass: String): Sequence<Lazy<Any>>? {
|
||||
lock.withLock {
|
||||
val implementations = registered[baseClass]
|
||||
val forced = overrided[baseClass]
|
||||
if (forced == null && implementations == null) return null
|
||||
|
||||
val implementationsSnapshot = implementations?.toList().orEmpty()
|
||||
|
||||
return sequence {
|
||||
if (forced != null) yield(forced.instance)
|
||||
|
||||
implementationsSnapshot.forEach { yield(it.instance) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun implementationsDirectly(baseClass: String) = lock.withLock { registered[baseClass]?.toList().orEmpty() }
|
||||
|
||||
public fun print(): String {
|
||||
lock.withLock {
|
||||
return registered.entries.joinToString { "${it.key}:${it.value}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public expect fun <T : Any> loadServiceOrNull(clazz: KClass<out T>, fallbackImplementation: String? = null): T?
|
||||
public expect fun <T : Any> loadService(clazz: KClass<out T>, fallbackImplementation: String? = null): T
|
||||
public expect fun <T : Any> loadServices(clazz: KClass<out T>): Sequence<T>
|
||||
|
@ -13,12 +13,48 @@ import java.util.*
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.createInstance
|
||||
|
||||
private enum class LoaderType {
|
||||
JDK,
|
||||
BOTH,
|
||||
FALLBACK,
|
||||
}
|
||||
|
||||
private val loaderType = when (systemProp("mirai.service.loader", "both")) {
|
||||
"jdk" -> LoaderType.JDK
|
||||
"both" -> LoaderType.BOTH
|
||||
"fallback" -> LoaderType.FALLBACK
|
||||
else -> throw IllegalStateException("cannot find a service loader, mirai.service.loader must be both, jdk or fallback (default by both)")
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public actual fun <T : Any> loadService(clazz: KClass<out T>, fallbackImplementation: String?): T {
|
||||
val fallbackService by lazy {
|
||||
Services.firstImplementationOrNull(Services.qualifiedNameOrFail(clazz)) as T?
|
||||
}
|
||||
|
||||
val jdkService by lazy {
|
||||
ServiceLoader.load(clazz.java).firstOrNull()?.let { return@lazy it }
|
||||
|
||||
ServiceLoader.load(clazz.java, clazz.java.classLoader).firstOrNull()
|
||||
}
|
||||
|
||||
var suppressed: Throwable? = null
|
||||
return ServiceLoader.load(clazz.java).firstOrNull()
|
||||
?: ServiceLoader.load(clazz.java, clazz.java.classLoader).firstOrNull()
|
||||
?: (if (fallbackImplementation == null) null
|
||||
else runCatching { findCreateInstance<T>(fallbackImplementation) }.onFailure { suppressed = it }.getOrNull())
|
||||
|
||||
val services by lazy {
|
||||
when (loaderType) {
|
||||
LoaderType.JDK -> jdkService
|
||||
LoaderType.BOTH -> jdkService ?: fallbackService
|
||||
LoaderType.FALLBACK -> fallbackService
|
||||
}?.let { return@lazy it }
|
||||
|
||||
if (fallbackImplementation != null) {
|
||||
runCatching {
|
||||
findCreateInstance<T>(fallbackImplementation)
|
||||
}.onFailure { suppressed = it }.getOrNull()
|
||||
} else null
|
||||
}
|
||||
|
||||
return Services.getOverrideOrNull(clazz) ?: services
|
||||
?: throw NoSuchElementException("Could not find an implementation for service class ${clazz.qualifiedName}").apply {
|
||||
if (suppressed != null) addSuppressed(suppressed)
|
||||
}
|
||||
@ -29,14 +65,17 @@ private fun <T : Any> findCreateInstance(fallbackImplementation: String): T {
|
||||
}
|
||||
|
||||
public actual fun <T : Any> loadServiceOrNull(clazz: KClass<out T>, fallbackImplementation: String?): T? {
|
||||
return ServiceLoader.load(clazz.java).firstOrNull()
|
||||
?: ServiceLoader.load(clazz.java, clazz.java.classLoader).firstOrNull()
|
||||
?: if (fallbackImplementation == null) return null
|
||||
else runCatching { findCreateInstance<T>(fallbackImplementation) }.getOrNull()
|
||||
return runCatching { loadService(clazz, fallbackImplementation) }.getOrNull()
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public actual fun <T : Any> loadServices(clazz: KClass<out T>): Sequence<T> {
|
||||
return sequence {
|
||||
fun fallBackServicesSeq(): Sequence<T> {
|
||||
return Services.implementations(Services.qualifiedNameOrFail(clazz)).orEmpty()
|
||||
.map { it.value as T }
|
||||
}
|
||||
|
||||
fun jdkServices(): Sequence<T> = sequence {
|
||||
val current = ServiceLoader.load(clazz.java).iterator()
|
||||
if (current.hasNext()) {
|
||||
yieldAll(current)
|
||||
@ -44,4 +83,30 @@ public actual fun <T : Any> loadServices(clazz: KClass<out T>): Sequence<T> {
|
||||
yieldAll(ServiceLoader.load(clazz.java, clazz.java.classLoader))
|
||||
}
|
||||
}
|
||||
|
||||
fun bothServices(): Sequence<T> = sequence {
|
||||
Services.getOverrideOrNull(clazz)?.let { yield(it) }
|
||||
|
||||
var jdkServices = ServiceLoader.load(clazz.java).toList()
|
||||
if (jdkServices.isEmpty()) {
|
||||
jdkServices = ServiceLoader.load(clazz.java, clazz.java.classLoader).toList()
|
||||
}
|
||||
yieldAll(jdkServices)
|
||||
|
||||
Services.implementationsDirectly(Services.qualifiedNameOrFail(clazz)).asSequence()
|
||||
.filter { impl ->
|
||||
// Drop duplicated
|
||||
jdkServices.none { it.javaClass.name == impl.implementationClass }
|
||||
}
|
||||
.forEach { yield(it.instance.value as T) }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return when (loaderType) {
|
||||
LoaderType.JDK -> jdkServices()
|
||||
LoaderType.BOTH -> bothServices()
|
||||
LoaderType.FALLBACK -> fallBackServicesSeq()
|
||||
}
|
||||
}
|
@ -11,47 +11,9 @@
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import kotlinx.atomicfu.locks.reentrantLock
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import net.mamoe.mirai.utils.Services.qualifiedNameOrFail
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
public object Services {
|
||||
private val lock = reentrantLock()
|
||||
|
||||
private class Implementation(
|
||||
val implementationClass: String,
|
||||
val instance: Lazy<Any>
|
||||
)
|
||||
|
||||
private val registered: MutableMap<String, MutableList<Implementation>> = mutableMapOf()
|
||||
|
||||
public fun register(baseClass: String, implementationClass: String, implementation: () -> Any) {
|
||||
lock.withLock {
|
||||
registered.getOrPut(baseClass, ::mutableListOf)
|
||||
.add(Implementation(implementationClass, lazy(implementation)))
|
||||
}
|
||||
}
|
||||
|
||||
public fun firstImplementationOrNull(baseClass: String): Any? {
|
||||
lock.withLock {
|
||||
return registered[baseClass]?.firstOrNull()?.instance?.value
|
||||
}
|
||||
}
|
||||
|
||||
public fun implementations(baseClass: String): List<Lazy<Any>>? {
|
||||
lock.withLock {
|
||||
return registered[baseClass]?.map { it.instance }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public fun print(): String {
|
||||
lock.withLock {
|
||||
return registered.entries.joinToString { "${it.key}:${it.value}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public actual fun <T : Any> loadServiceOrNull(
|
||||
clazz: KClass<out T>,
|
||||
@ -66,7 +28,4 @@ public actual fun <T : Any> loadService(
|
||||
?: error("Could not load service '${clazz.qualifiedName ?: clazz}'. Current services: ${Services.print()}")
|
||||
|
||||
public actual fun <T : Any> loadServices(clazz: KClass<out T>): Sequence<T> =
|
||||
Services.implementations(qualifiedNameOrFail(clazz))?.asSequence()?.map { it.value }.orEmpty().castUp()
|
||||
|
||||
private fun <T : Any> qualifiedNameOrFail(clazz: KClass<out T>) =
|
||||
clazz.qualifiedName ?: error("Could not find qualifiedName for $clazz")
|
||||
Services.implementations(qualifiedNameOrFail(clazz)).orEmpty().map { it.value }.castUp()
|
||||
|
@ -250,8 +250,8 @@ internal class WtLogin {
|
||||
}
|
||||
}
|
||||
|
||||
private fun dumpTlvMap(tlvMap: TlvMap) {
|
||||
tlvMap.entries.joinToString { "${it.key}=${it.value.toUHexString()}" }
|
||||
private fun dumpTlvMap(tlvMap: TlvMap): String {
|
||||
return tlvMap.entries.joinToString { "${it.key}=${it.value.toUHexString()}" }
|
||||
}
|
||||
|
||||
private fun onDevLockLogin(
|
||||
|
@ -16,12 +16,14 @@ import io.ktor.client.engine.okhttp.*
|
||||
import io.ktor.client.plugins.*
|
||||
import kotlinx.atomicfu.atomic
|
||||
import net.mamoe.mirai.internal.message.protocol.MessageProtocolFacade
|
||||
import net.mamoe.mirai.internal.utils.MiraiCoreServices
|
||||
|
||||
private val initialized = atomic(false)
|
||||
|
||||
@Suppress("FunctionName")
|
||||
internal actual fun _MiraiImpl_static_init() {
|
||||
if (!initialized.compareAndSet(expect = false, update = true)) return
|
||||
MiraiCoreServices.registerAll()
|
||||
MessageProtocolFacade.INSTANCE // register serializers
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user