说明:mirai
和YuQ
的过验证码都需要通过App
,对于小白来说还是太麻烦了。所以直接自动通过验证码,如果验证失败,再使用其自带的过验证码方式
好像出现盾牌行的验证码会有问题,懒得修了。又没人用
前提
引入我的工具类,只是用了HTTP请求的工具类而已,你也可以不需要引用,使用另外的方式来请求我的接口
// grade
implementation("me.kuku:utils:2.2.1.1")
// maven
<dependency>
<groupId>me.kuku</groupId>
<artifactId>utils</artifactId>
<version>2.2.1.1</version>
</dependency>
总的来说,就是把获取到的验证码url
传给我的api
,将会收到ticket
https://api.kukuqaq.com/captcha
POST
参数 url
-> 验证码url
YuQ-Art
使用YuHook
来实现
1、新建一个类,比如我的类是me.kuku.yuq.HookCaptchaUtils
,继承于HookRunnable
class HookCaptchaUtils : HookRunnable {
override fun init(info: HookInfo) {
}
private val log = LoggerFactory.getLogger(HookRunnable::class.java)
override fun preRun(method: HookMethod): Boolean {
log.info("验证码url: ${method.paras[1]}")
val url = method.paras[1]!! as String
val ticket = runBlocking {
var ticket: String? = null
for (i in 0..3) {
log.info("正在尝试第${i + 1}次自动过验证码~~~")
val jsonNode = OkHttpUtils.postJson("https://api.kukuqaq.com/captcha", mapOf("url" to url))
if (jsonNode.contains("ticket")) {
ticket = jsonNode["ticket"].asText()
log.info("自动过验证码成功")
break
}
}
ticket
}
if (ticket == null) {
log.info("自动识别验证码失败,转为手动验证验证码")
return com.icecreamqaq.yuq.artqq.HookCaptchaUtils().preRun(method)
}
// RainUI.webListener(url)
method.result = CommonResult(200, "Success!", mutableMapOf("ticket" to ticket))
return true
}
override fun postRun(method: HookMethod) {
println("result: ${method.result}")
}
override fun onError(method: HookMethod) = false
}
2、编写一个类替换掉YuQ-Art
原有的过滑块方式
class HookYuQArtQQModule: HookRunnable {
override fun preRun(method: HookMethod): Boolean {
val yuQArtQQModule = method.paras[0] as YuQArtQQModule
val context = yuQArtQQModule::class.java.declaredFields[0].also { it.isAccessible = true }
.get(yuQArtQQModule) as YuContext
context.putBean(YuQInternalFun::class.java, "", YuQInternalFunArtQQImpl())
AppClassloader.registerBackList(
arrayListOf(
"javafx.",
"org.w3c",
"jdk.internal.",
)
)
YuHook.put(
HookItem(
"org.artqq.util.TenCentCaptchaUtils",
"identifyByUrl",
"me.kuku.yuq.HookCaptchaUtils"
)
)
YuHook.put(
HookItem(
"org.artqq.Wtlogin._Login",
"onSuccessSendVC",
"com.icecreamqaq.yuq.artqq.HookPhoneCap"
)
)
YuHook.put(
HookItem(
"com.baidu.bjf.remoting.protobuf.utils.JDKCompilerHelper",
"getJdkCompiler",
"com.icecreamqaq.yuq.artqq.HookProto"
)
)
return true
}
}
3、在启动之前添加至Yu-Hook
fun main(args: Array<String>) {
YuHook.put(
HookItem(
"com.icecreamqaq.yuq.artqq.YuQArtQQModule",
"onLoad",
"me.kuku.yuq.HookYuQArtQQModule"
)
)
YuQArtQQStarter.start(args)
}
YuQ-Mirai
使用YuHook
来实现
1、新建一个类,比如我的类是me.kuku.yuq.config.HookSliderCaptcha
,继承于HookRunnable
public class HookSliderCaptcha implements HookRunnable {
private final Logger logger = LoggerFactory.getLogger(HookRunnable.class);
@Override
public void init(HookInfo info) {
}
@Override
public boolean preRun(HookMethod method) {
String url = (String) method.paras[2];
logger.info("验证码url:" + url);
String ticket = null;
try {
for (int i = 0; i < 3; i++) {
int num = i + 1;
logger.info("正在第" + num + "次尝试识别验证码中");
JsonNode jsonNode = OkHttpUtils.postJson("https://api.kukuqaq.com/captcha", Maps.of("url", url));
if (jsonNode.contains("ticket")) {
logger.info("自动识别验证码成功");
ticket = jsonObject.get("ticket").asText();
logger.info("ticket:" + ticket);
break;
}
}
} catch (Exception ignore) {
}
if (ticket == null) {
logger.info("识别验证码失败,转为yuq-mirai自带的识别方式");
return false;
} else {
method.result = ticket;
}
return true;
}
@Override
public void postRun(HookMethod method) {
}
@Override
public boolean onError(HookMethod method) {
return false;
}
}
2、在启动之前注入YuHook
fun main(args: Array<String>) {
YuHook.put(
HookItem(
"net.mamoe.mirai.utils.StandardCharImageLoginSolver",
"onSolveSliderCaptcha",
"me.kuku.yuq.config.HookSliderCaptcha"
)
)
YuQMiraiStart.start(args)
}
Mirai
自定义验证码实现
class KuKuLoginSolver: LoginSolver() {
private val standardCharImageLoginSolver = StandardCharImageLoginSolver()
override val isSliderCaptchaSupported: Boolean
get() = true
override suspend fun onSolvePicCaptcha(bot: Bot, data: ByteArray) =
standardCharImageLoginSolver.onSolvePicCaptcha(bot, data)
override suspend fun onSolveSliderCaptcha(bot: Bot, url: String): String? {
val logger = bot.logger
logger.info { "[SliderCaptcha] Captcha link: $url" }
for (i in 0..3) {
logger.info{ "[SliderCaptcha] Try to automatically recognize the verification code." }
val jsonNode = client.post("https://api.kukuqaq.com/captcha") {
setFormDataContent {
append("url", url)
}
}.body<JsonNode>()
if (jsonNode.contains("ticket")) {
val ticket = jsonNode["ticket"].asText()
logger.info { "[SliderCaptcha] Ticket: $ticket" }
return ticket
}
}
logger.error { "[SliderCaptcha] Recognition failure" }
return standardCharImageLoginSolver.onSolveSliderCaptcha(bot, url)
}
}
mirai原生
替换掉验证码实现
suspend fun main(args: Array<String>) {
// 让mirai强制走滑块验证码
System.setProperty("mirai.slider.captcha.supported", "true");
val newBot = BotFactory.newBot("qq号", "密码")
val configuration = newBot.configuration
// 把验证码实现更换为自己的
configuration.loginSolver = KuKuLoginSolver()
newBot.login()
}
simbot2
如果为simbot
+SpringBoot
,则实现MiraiBotConfigurationFactory
接口,并重写getMiraiBotConfiguration
方法
@Component
public class MiraiBot implements MiraiBotConfigurationFactory {
@NotNull
@Override
public BotConfiguration getMiraiBotConfiguration(@NotNull BotVerifyInfo botInfo, @NotNull MiraiConfiguration simbotMiraiConfig) {
BotConfiguration botConfiguration = simbotMiraiConfig.getBotConfiguration().invoke(botInfo.getCode());
System.setProperty("mirai.slider.captcha.supported", "true");
botConfiguration.setLoginSolver(new KuKuLoginSolver());
botConfiguration.fileBasedDeviceInfo();
return botConfiguration;
}
}
simbot3
1、监听MiraiBotRegisteredEvent
事件,替换掉验证码实现
@Service
class BotEvent {
@Listener
fun ss(e: MiraiBotRegisteredEvent) {
e.bot.originalBot.configuration.loginSolver = KuKuLoginSolver()
}
}
@Service
public class BotEvent {
@Listener
public void ss(MiraiBotRegisteredEvent e) {
e.getBot().getOriginalBot().getConfiguration().setLoginSolver(new KuKuLoginSolver());
}
}
2、启动之前设置环境变量
System.setProperty("mirai.slider.captcha.supported", "true")
2 条评论
MiraiBotConfigurationFactory这个类在simbot v3上是不是没了 我引入不到这个类
已更新simbot v3的方式