@2446694 在 Spring Boot maven工程如何实现扫码登录? 中说:
@guizaipiao
我使用的依赖是 mirai-core 这一个
以下是你提到的配置
QQSission
package com.session;
import net.mamoe.mirai.Bot;
import net.mamoe.mirai.BotFactory;
import net.mamoe.mirai.auth.BotAuthorization;
import net.mamoe.mirai.contact.*;
import net.mamoe.mirai.event.EventChannel;
import net.mamoe.mirai.event.events.BotEvent;
import net.mamoe.mirai.utils.BotConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.function.Consumer;
/**
* ContactOrBot Contact 和 Bot 的公共接口 2.0
* OtherClient Bot 的其他客户端,如 “我的 iPad”,”我的电脑” 2.0
* Bot 机器人对象 2.0
* Contact 联系人对象,即所有的群,好友,陌生人,群成员等 2.0
* Group 群对象 2.0
* User 用户对象,即 “个人”. 包含好友,陌生人,群成员,临时会话用户 2.0
* Friend 好友对象 2.0
* Stranger 陌生人对象 2.0
* Member 群成员对象,属于一个 Group. 2.0
* NormalMember 普通群成员对象. 2.0
* AnonymousMember 匿名群成员对象. 2.0
*/
public class QqSession {
private static final Logger logger = LoggerFactory.getLogger(QqSession.class);
private final Bot bot;
private final Consumer<Object> doRequest;
private Consumer<Object> doResponse;
public QqSession(Long qq, String password, Consumer<Object> doRequest) {
// 使用自定义配置
BotConfiguration botConfiguration = new QqBotConfiguration(qq);
// 定义属性
this.bot = BotFactory.INSTANCE.newBot(qq, password, botConfiguration);
// 验证信息处理
this.doRequest = doRequest;
}
public QqSession(Long qq, BotAuthorization credential, Consumer<Object> doRequest) {
// 使用自定义配置
BotConfiguration botConfiguration = new QqBotConfiguration(qq);
// 二维码登录
this.bot = BotFactory.INSTANCE.newBot(qq, credential, botConfiguration);
// 验证信息处理
this.doRequest = doRequest;
}
public Bot getBot() {
return this.bot;
}
public boolean login() {
this.bot.login();
boolean isOnline = this.bot.isOnline();
if (isOnline) logger.info(this.bot.getId() + " 登录成功");
else logger.info(this.bot.getId() + " 登录失败");
return isOnline;
}
public boolean isOnline() {
return this.bot.isOnline();
}
public void close() {
this.bot.close();
}
public Long getQq() {
return this.bot.getId();
}
public ContactList<Friend> getFriends() {
// 获取好友列表
return this.bot.getFriends();
}
public ContactList<Group> getGroups() {
// 获取群列表
return this.bot.getGroups();
}
public Friend getFriend(Long id) {
// 获取指定qq号好友
return this.bot.getFriend(id);
}
public Group getGroup(Long id) {
// 根据群号获取群
return this.bot.getGroup(id);
}
public Stranger getStranger(Long id) {
// 获取指定qq号陌生人
return this.bot.getStranger(id);
}
public ContactList<OtherClient> getOtherClients() {
// 联系其他客户端
return this.bot.getOtherClients();
}
public EventChannel<BotEvent> getEventChannel() {
return this.bot.getEventChannel();
}
public void sendRequest(Object request, Consumer<Object> doResponse) {
this.doResponse = doResponse;
// 发送验证请求
this.doRequest.accept(request);
}
public void sendResponse(String response) {
// 响应验证码
doResponse.accept(response);
}
}
QqSessionManager
package com.session;
import net.mamoe.mirai.auth.BotAuthorization;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
public class QqSessionManager {
private static final Map<Long, QqSession> sessionMap = new HashMap<>();
public static QqSession newQqSession(Long qq, Object credential, Consumer<Object> doRequest) {
QqSession qqSession;
if (credential instanceof BotAuthorization)
qqSession = new QqSession(qq, (BotAuthorization) credential, doRequest);
else if (credential instanceof String)
qqSession = new QqSession(qq, (String) credential, doRequest);
else throw new IllegalArgumentException("无效的credential");
sessionMap.put(qq, qqSession);
return qqSession;
}
public static QqSession getQqSession(Long qq) {
return sessionMap.get(qq);
}
public static void removeQqSession(Long qq) {
sessionMap.get(qq).close();
sessionMap.remove(qq);
}
}
Controller层实现
@PostMapping("/login")
public Result<Object> request(@RequestParam("qq") Long qq, @RequestParam(value = "pwd", required = false) String pwd) throws InterruptedException {
Result<Object> result = new Result<>(); // 将url信息设置到result中
QqSession[] qqSession = new QqSession[]{QqSessionManager.getQqSession(qq)};
if (qqSession[0] == null || !qqSession[0].isOnline()) {
CountDownLatch latch = new CountDownLatch(1); // 定义一个CountDownLatch对象,用于等待result.setData
new Thread(() -> {
if (pwd == null) {
result.setCode(220);
qqSession[0] = QqSessionManager.newQqSession(qq, BotAuthorization.byQRCode(), object -> {
byte[] bytes = (byte[]) object;
String base64Image = "data:image/png;base64," + Base64.getEncoder().encodeToString(bytes);
result.setData(base64Image, "请扫码"); // 将图片设置到result中
latch.countDown();
});
} else {
result.setCode(210);
qqSession[0] = QqSessionManager.newQqSession(qq, pwd, object -> {
if (object instanceof byte[]) {
byte[] bytes = (byte[]) object;
String base64Image = "data:image/png;base64," + Base64.getEncoder().encodeToString(bytes);
result.setData(base64Image, "请处理验证码"); // 将图片设置到result中
} else result.setData(object, "请处理url"); // 将url信息设置到result中
latch.countDown();
});
}
result.setCode(200).setData(qqSession[0].login(),"登录成功");
latch.countDown();
}).start();
latch.await(10000, TimeUnit.MILLISECONDS); // 调用CountDownLatch对象的await方法等待url信息被设置
} else {
result.setCode(200).setData(qqSession[0].isOnline(), "已经登录过了");
}
return result; // 返回result对象给前端
}
Result类
package com.domain;
import java.util.HashMap;
import java.util.Map;
public class Result<T> {
static {
Result.codeMap = new HashMap<>();
Result.codeMap.put(100, "查询失败,没有找到相关数据");
Result.codeMap.put(110, "添加失败,无法添加该数据");
Result.codeMap.put(120, "删除失败,相关数据不存在");
Result.codeMap.put(130, "修改失败,相关数据不存在");
Result.codeMap.put(200, "登录失败");
Result.codeMap.put(210, "验证码失效");
Result.codeMap.put(220, "二维码失效");
Result.codeMap.put(230, "短信验证失效");
Result.codeMap.put(290, "登出失败");
Result.codeMap.put(900, "请求数据有误");
Result.codeMap.put(910, "系统繁忙,请稍后再试");
Result.codeMap.put(990, "发生未知的错误,暂时无法处理");
}
private static Map<Integer, String> codeMap;
private int code;
private String msg;
private T data;
public Result() {
}
public Result(int code) {
// 设置十位数上的值
this.code = code;
this.msg = codeMap.get(code);
}
public int getCode() {
return code;
}
public Result<T> setCode(int code) {
this.code = code;
this.msg = codeMap.get(code);
return this;
}
public String getMsg() {
return msg;
}
public Result<T> setErrorMsg(String errorMsg) {
// 如果代码为0,则表示异常或失败,设置错误信息
if (this.code % 10 == 0) this.msg = errorMsg;
return this;
}
public T getData() {
return data;
}
public Result<T> setData(T data) {
// 改变个位数上的值
if (notNone(data) && this.code / 100 != 9) {
this.code = this.code / 10 * 10 + 1;
this.msg = "操作成功";
}
this.data = data;
return this;
}
public Result<T> setData(T data, String msg) {
// 改变个位数上的值
if (notNone(data) && this.code / 100 != 9) {
this.code = this.code / 10 * 10 + 1;
this.msg = msg;
}
this.data = data;
return this;
}
private boolean notNone(Object value) {
// Character(char(\u0000)) 会被 instanceof Number == 0 处理
return value instanceof Boolean ? (Boolean) value : value instanceof Number ? value != (Number) 0 : value instanceof String ? value != "" : value != null;
}
@Override
public String toString() {
return "Result{code=" + code + ", msg=" + msg + ", data=" + data + '}';
}
}