mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-31 11:30:16 +08:00
Disable SliderCaptcha. #745
This commit is contained in:
parent
dffade2a92
commit
5db71cd299
@ -61,6 +61,11 @@ public class NoStandardInputForCaptchaException @MiraiInternalApi constructor(
|
|||||||
@MiraiExperimentalApi("Will be removed when SMS login is supported")
|
@MiraiExperimentalApi("Will be removed when SMS login is supported")
|
||||||
public class UnsupportedSMSLoginException(message: String?) : LoginFailedException(true, message)
|
public class UnsupportedSMSLoginException(message: String?) : LoginFailedException(true, message)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 无法完成滑块验证
|
||||||
|
*/
|
||||||
|
public class NotSupportedSliderCaptchaException(message: String?) : LoginFailedException(true, message)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 非 mirai 实现的异常
|
* 非 mirai 实现的异常
|
||||||
*/
|
*/
|
||||||
|
@ -45,6 +45,10 @@ public abstract class LoginSolver {
|
|||||||
*/
|
*/
|
||||||
public abstract suspend fun onSolvePicCaptcha(bot: Bot, data: ByteArray): String?
|
public abstract suspend fun onSolvePicCaptcha(bot: Bot, data: ByteArray): String?
|
||||||
|
|
||||||
|
// TODO: 2020-12-24 滑动验证码支持
|
||||||
|
@MiraiInternalApi
|
||||||
|
public open val isSliderCaptchaSupport: Boolean get() = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理滑动验证码.
|
* 处理滑动验证码.
|
||||||
* 返回 null 以表示无法处理验证码, 将会刷新验证码或重试登录.
|
* 返回 null 以表示无法处理验证码, 将会刷新验证码或重试登录.
|
||||||
@ -89,6 +93,7 @@ public abstract class LoginSolver {
|
|||||||
public fun getDefault(): LoginSolver = Default
|
public fun getDefault(): LoginSolver = Default
|
||||||
?: error("LoginSolver is not provided by default on your platform. Please specify by BotConfiguration.loginSolver")
|
?: error("LoginSolver is not provided by default on your platform. Please specify by BotConfiguration.loginSolver")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,7 +93,7 @@ internal class QQAndroidBot constructor(
|
|||||||
@Throws(LoginFailedException::class) // only
|
@Throws(LoginFailedException::class) // only
|
||||||
override suspend fun relogin(cause: Throwable?) {
|
override suspend fun relogin(cause: Throwable?) {
|
||||||
client.useNextServers { host, port ->
|
client.useNextServers { host, port ->
|
||||||
network.closeEverythingAndRelogin(host, port, cause)
|
network.closeEverythingAndRelogin(host, port, cause, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ internal abstract class BotNetworkHandler : CoroutineScope {
|
|||||||
*/
|
*/
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
@MiraiInternalApi
|
@MiraiInternalApi
|
||||||
abstract suspend fun closeEverythingAndRelogin(host: String, port: Int, cause: Throwable? = null)
|
abstract suspend fun closeEverythingAndRelogin(host: String, port: Int, cause: Throwable? = null, step: Int)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化获取好友列表等值.
|
* 初始化获取好友列表等值.
|
||||||
|
@ -40,10 +40,7 @@ import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
|||||||
import net.mamoe.mirai.internal.network.protocol.packet.login.WtLogin
|
import net.mamoe.mirai.internal.network.protocol.packet.login.WtLogin
|
||||||
import net.mamoe.mirai.internal.utils.*
|
import net.mamoe.mirai.internal.utils.*
|
||||||
import net.mamoe.mirai.internal.utils.io.readPacketExact
|
import net.mamoe.mirai.internal.utils.io.readPacketExact
|
||||||
import net.mamoe.mirai.network.ForceOfflineException
|
import net.mamoe.mirai.network.*
|
||||||
import net.mamoe.mirai.network.RetryLaterException
|
|
||||||
import net.mamoe.mirai.network.UnsupportedSMSLoginException
|
|
||||||
import net.mamoe.mirai.network.WrongPasswordException
|
|
||||||
import net.mamoe.mirai.utils.*
|
import net.mamoe.mirai.utils.*
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
@ -114,10 +111,14 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
|
|||||||
}.also { heartbeatJob = it }
|
}.also { heartbeatJob = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @param step
|
||||||
override suspend fun closeEverythingAndRelogin(host: String, port: Int, cause: Throwable?) {
|
// 0 -> 初始状态, 其他函数调用应永远传入 0
|
||||||
|
// 1 -> 代表滑块验证已禁用
|
||||||
|
override suspend fun closeEverythingAndRelogin(host: String, port: Int, cause: Throwable?, step: Int) {
|
||||||
heartbeatJob?.cancel(CancellationException("relogin", cause))
|
heartbeatJob?.cancel(CancellationException("relogin", cause))
|
||||||
heartbeatJob?.join()
|
heartbeatJob?.join()
|
||||||
|
_packetReceiverJob?.cancel(CancellationException("relogin", cause))
|
||||||
|
_packetReceiverJob?.join()
|
||||||
if (::channel.isInitialized) {
|
if (::channel.isInitialized) {
|
||||||
// if (channel.isOpen) {
|
// if (channel.isOpen) {
|
||||||
// kotlin.runCatching {
|
// kotlin.runCatching {
|
||||||
@ -161,14 +162,20 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isSliderCaptchaSupport = bot.configuration.loginSolver?.isSliderCaptchaSupport ?: false
|
||||||
|
val allowSlider = isSliderCaptchaSupport
|
||||||
|
|| bot.configuration.protocol == BotConfiguration.MiraiProtocol.ANDROID_PHONE
|
||||||
|
|| step == 0
|
||||||
|
|
||||||
fun loginSolverNotNull() = bot.configuration.loginSolver.notnull()
|
fun loginSolverNotNull() = bot.configuration.loginSolver.notnull()
|
||||||
|
|
||||||
var response: WtLogin.Login.LoginPacketResponse = WtLogin.Login.SubCommand9(bot.client).sendAndExpect()
|
var response: WtLogin.Login.LoginPacketResponse =
|
||||||
|
WtLogin.Login.SubCommand9(bot.client, allowSlider).sendAndExpect()
|
||||||
mainloop@ while (true) {
|
mainloop@ while (true) {
|
||||||
when (response) {
|
when (response) {
|
||||||
is WtLogin.Login.LoginPacketResponse.UnsafeLogin -> {
|
is WtLogin.Login.LoginPacketResponse.UnsafeLogin -> {
|
||||||
loginSolverNotNull().onSolveUnsafeDeviceLoginVerify(bot, response.url)
|
loginSolverNotNull().onSolveUnsafeDeviceLoginVerify(bot, response.url)
|
||||||
response = WtLogin.Login.SubCommand9(bot.client).sendAndExpect()
|
response = WtLogin.Login.SubCommand9(bot.client, allowSlider).sendAndExpect()
|
||||||
}
|
}
|
||||||
|
|
||||||
is WtLogin.Login.LoginPacketResponse.Captcha -> when (response) {
|
is WtLogin.Login.LoginPacketResponse.Captcha -> when (response) {
|
||||||
@ -183,6 +190,21 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
|
|||||||
continue@mainloop
|
continue@mainloop
|
||||||
}
|
}
|
||||||
is WtLogin.Login.LoginPacketResponse.Captcha.Slider -> {
|
is WtLogin.Login.LoginPacketResponse.Captcha.Slider -> {
|
||||||
|
if (!isSliderCaptchaSupport) {
|
||||||
|
if (step == 0) {
|
||||||
|
return closeEverythingAndRelogin(host, port, cause, 1)
|
||||||
|
}
|
||||||
|
throw NotSupportedSliderCaptchaException(
|
||||||
|
buildString {
|
||||||
|
append("Mirai 无法完成滑块验证.")
|
||||||
|
if (allowSlider) {
|
||||||
|
append(" 使用协议 ")
|
||||||
|
append(bot.configuration.protocol)
|
||||||
|
append(" 强制要求滑块验证, 请更换协议后重试")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
val ticket = loginSolverNotNull().onSolveSliderCaptcha(bot, response.url).orEmpty()
|
val ticket = loginSolverNotNull().onSolveSliderCaptcha(bot, response.url).orEmpty()
|
||||||
response = WtLogin.Login.SubCommand2.SubmitSliderCaptcha(bot.client, ticket).sendAndExpect()
|
response = WtLogin.Login.SubCommand2.SubmitSliderCaptcha(bot.client, ticket).sendAndExpect()
|
||||||
continue@mainloop
|
continue@mainloop
|
||||||
@ -193,7 +215,13 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
|
|||||||
if (response.message.contains("0x9a")) { //Error(title=登录失败, message=请你稍后重试。(0x9a), errorInfo=)
|
if (response.message.contains("0x9a")) { //Error(title=登录失败, message=请你稍后重试。(0x9a), errorInfo=)
|
||||||
throw RetryLaterException()
|
throw RetryLaterException()
|
||||||
}
|
}
|
||||||
throw WrongPasswordException(response.toString())
|
val msg = response.toString()
|
||||||
|
throw WrongPasswordException(buildString(capacity = msg.length) {
|
||||||
|
append(msg)
|
||||||
|
if (msg.contains("当前上网环境异常")) { // Error(title=禁止登录, message=当前上网环境异常,请更换网络环境或在常用设备上登录或稍后再试。, errorInfo=)
|
||||||
|
append(", tips=若频繁出现, 请尝试开启设备锁")
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
is WtLogin.Login.LoginPacketResponse.DeviceLockLogin -> {
|
is WtLogin.Login.LoginPacketResponse.DeviceLockLogin -> {
|
||||||
|
@ -123,12 +123,13 @@ internal class WtLogin {
|
|||||||
private const val appId = 16L
|
private const val appId = 16L
|
||||||
|
|
||||||
operator fun invoke(
|
operator fun invoke(
|
||||||
client: QQAndroidClient
|
client: QQAndroidClient,
|
||||||
|
allowSlider: Boolean
|
||||||
): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { sequenceId ->
|
): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { sequenceId ->
|
||||||
writeSsoPacket(client, client.subAppId, commandName, sequenceId = sequenceId) {
|
writeSsoPacket(client, client.subAppId, commandName, sequenceId = sequenceId) {
|
||||||
writeOicqRequestPacket(client, EncryptMethodECDH(client.ecdh), 0x0810) {
|
writeOicqRequestPacket(client, EncryptMethodECDH(client.ecdh), 0x0810) {
|
||||||
writeShort(9) // subCommand
|
writeShort(9) // subCommand
|
||||||
writeShort(0x18) // count of TLVs, probably ignored by server?
|
writeShort(if (allowSlider) 0x18 else 0x17) // count of TLVs, probably ignored by server?
|
||||||
//writeShort(LoginType.PASSWORD.value.toShort())
|
//writeShort(LoginType.PASSWORD.value.toShort())
|
||||||
|
|
||||||
t18(appId, client.appClientVersion, client.uin)
|
t18(appId, client.appClientVersion, client.uin)
|
||||||
@ -231,7 +232,9 @@ internal class WtLogin {
|
|||||||
t187(client.device.macAddress)
|
t187(client.device.macAddress)
|
||||||
t188(client.device.androidId)
|
t188(client.device.androidId)
|
||||||
t194(client.device.imsiMd5)
|
t194(client.device.imsiMd5)
|
||||||
|
if (allowSlider) {
|
||||||
t191()
|
t191()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
t201(N = byteArrayOf())*/
|
t201(N = byteArrayOf())*/
|
||||||
|
Loading…
Reference in New Issue
Block a user