基于SpringBoot实现QQ机器人

本博客内容已不可用,可以看主页的另外一篇Mirai3+SpringBoot3的 

本QQ机器人实现的功能

1.输入关机,进入30秒倒计时关机

2.输入锁屏,电脑自动进行锁屏操作

3.输入取消关机,即可取消关机指令

4.调用青云客的API进行自动聊天

5.输入关键词自动添加为好友

技术栈:

非特殊情况保持一致即可!

1.SpringBoot2.7.5

2.JDK1.8

3.mirai2.3.0

mirai的github:GitHub - simple-robot

mirai官方文档:mirai语雀文档

源码链接:QQ_robot.zip - 蓝奏云

实现步骤:

1. 新建一个springBoot项目,选择lombok这一个依赖即可

2. 引入相关依赖

         <!--使用mirai组件开发QQ机器人-->
        <dependency>
            <groupId>love.forte.simple-robot</groupId>
            <artifactId>component-mirai-spring-boot-starter</artifactId>
            <version>2.3.0</version>
        </dependency>
        <!-- httpclient用来请求自动回复API -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>

3.启动类

/**
 * 启动类
 * Author:木芒果
 */
@EnableSimbot
@EnableScheduling
@SpringBootApplication
@Slf4j
public class QqRobotApplication {
    public static void main(String[] args) {
        SpringApplication.run(QqRobotApplication.class, args);
        log.info("木芒果机器人启动成功~~~~");
    }
}

4.HTTP请求工具类,需要引入httpclient依赖

/**
 * http工具类
 * Author:木芒果
 */
public class HttpUtil {
    private static final CloseableHttpClient HTTP_CLIENT;

    static {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(100);
        cm.setDefaultMaxPerRoute(20);
        cm.setDefaultMaxPerRoute(50);
        HTTP_CLIENT = HttpClients.custom().setConnectionManager(cm).build();
    }

    /**
     * 发送GET请求
     */
    public static String get(String url) {
        CloseableHttpResponse response = null;
        BufferedReader in;
        String result = "";
        try {
            HttpGet httpGet = new HttpGet(url);
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
            httpGet.setConfig(requestConfig);
            httpGet.setConfig(requestConfig);
            httpGet.addHeader("Content-type", "application/json; charset=utf-8");
            httpGet.setHeader("Accept", "application/json");
            response = HTTP_CLIENT.execute(httpGet);
            in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            String str = null;
            String line;
            //String nL = System.getProperty("line.separator");
            while ((line = in.readLine()) != null) {
                //sb.append(line).append(nL);
                //解决中文乱码问题
                str = new String((line).getBytes(), StandardCharsets.UTF_8);
            }
            in.close();
            System.out.println(str);
            result = str;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != response) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 发送POST请求
     */
    public static String post(String url, String jsonString) {
        HttpPost httpPost = new HttpPost(url);
        CloseableHttpClient client = HttpClients.createDefault();
        //解决中文乱码问题
        StringEntity entity = new StringEntity(jsonString, "utf-8");
        entity.setContentEncoding("utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        HttpResponse response;
        try {
            response = client.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity httpEntity = response.getEntity();
                return EntityUtils.toString(httpEntity, "utf-8");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}

5.定时发送信息类,通过配置达到自动发信息的目的

/**
 * 定时发送消息
 * Author:木芒果
 */
@Component
@Slf4j
public class AutoMessage {

    @Resource
    private BotManager botManager;

    @Value("${bello.qq}")
    private Set<String> qqSet;
    @Value("${belloGroup.group}")
    private Set<String> qqGroupSet;

    /**
     * 定义语录
     */
    static List<String> content;

    /**
     * 定义图片
     */
    static List<String> images;

    static {
        content = new ArrayList<>();
        images = new ArrayList<>();
        log.info("开始加载定义语录~~~");
        // 定义语录
        content.add("遇见你之前,我没想过结婚,遇见你之后,结婚我没想过别人。");
        content.add("你走向我,我觉得一日不见如隔三秋,你朝我笑,我又觉得三秋未见不过一日。");
        content.add("如果可以和你在一起,我宁愿让天空所有的星光全部损落,因为你的眼睛,是我生命里最亮的光芒。");
        content.add("我一直喜欢温暖的东西,而世界上最温暖的,无非阳光和你。");
        content.add("我不要短暂的温存,只要你一世的陪伴。");
        content.add("我没有特别喜欢的零食,没有特别喜欢的电影,没有特别喜欢听的歌,但我就是特别喜欢你。");
        content.add("一年四季想陪你度过,世间琐事都想与你做,此生也只想同你尝尽烟火。");
        content.add("我还是很喜欢你,像七月的风和八月的雨,毫无交集。");
        content.add("你在我身边也好,在天边也罢,想到世界的角落有一个你,觉得整个世界也变得温柔安定了。");
        content.add("我的人生理念是活十成,一成不变的是爱你,剩下九成是加倍爱你。");
        log.info("开始加载表情图片~~~");
        // 表情图片
        images.add("https://gitee.com/xxg-git/file-services/raw/master/QQ-robot/112ab4dd77ba5919bd830a75cf8973c.png");
        images.add("https://gitee.com/xxg-git/file-services/raw/master/QQ-robot/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20200623142757.jpg");
        images.add("https://gitee.com/xxg-git/file-services/raw/master/QQ-robot/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20201002220953.jpg");
        images.add("https://gitee.com/xxg-git/file-services/raw/master/QQ-robot/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20201002221329.jpg");
        images.add("https://gitee.com/xxg-git/file-services/raw/master/QQ-robot/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20201002221441.jpg");
        images.add("https://gitee.com/xxg-git/file-services/raw/master/QQ-robot/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20201002221545.jpg");
        images.add("https://gitee.com/xxg-git/file-services/raw/master/QQ-robot/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20201004212459.jpg");
        images.add("https://gitee.com/xxg-git/file-services/raw/master/QQ-robot/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20201004212532.jpg");
    }

    /**
     * 每一小时发送一次: 0 0 0/1 * * ?
     * 每五分钟发送一次: 0 0/5 * * * ?
     */
    @Scheduled(cron = "0 0 0/1 * * ?")
    public void handler() {
        Calendar calendar = Calendar.getInstance();
        // 获取当前小时
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        // 只在早上8点到晚上22点发送消息
        if (hour < 8 || hour > 22) {
            return;
        }
        //发送QQ私信
        qqSet.forEach(qq -> {
            try {
                final String msg = content.get(new Random().nextInt(content.size()));
                final String img = String.format("[CAT:image,url=%s,flash=false]", images.get(new Random().nextInt(images.size())));
                // 发送随机定义语录
                botManager.getDefaultBot().getSender().SENDER.sendPrivateMsg(qq, msg);
                // 发送随机定义图片
                botManager.getDefaultBot().getSender().SENDER.sendPrivateMsg(qq, img);
                log.info("正在发送定义语录,当前qq={}, 语录={}, img={}", qq, msg, img);
            } catch (Exception e) {
                log.error("发送定义语录异常, qq={}", qq, e);
            }

        });
        //发送QQ群
        if (null != qqGroupSet && qqGroupSet.size() > 0) {
            qqGroupSet.forEach(qq -> {
                try {
                    final String msg = content.get(new Random().nextInt(content.size()));
                    final String img = String.format("[CAT:image,url=%s,flash=false]", images.get(new Random().nextInt(images.size())));
                    // 发送随机定义语录
                    botManager.getDefaultBot().getSender().SENDER.sendGroupMsg(qq, msg);
                    // 发送随机定义图片
                    botManager.getDefaultBot().getSender().SENDER.sendGroupMsg(qq, img);
                    log.info("正在发送定义语录,当前qq={}, 语录={}, img={}", qq, msg, img);
                } catch (Exception e) {
                    log.error("发送定义语录异常, qq={}", qq, e);
                }
            });
        }
    }
}

6.消息监听类,你可以在这个类对QQ消息进行监听,并实现你的目的

/**
 * 消息监听类
 * Author:木芒果
 */
@Component
@Slf4j
public class MessageListener {

    static final String URL = "http://api.qingyunke.com/api.php";


    /**
     * 监听好友添加请求
     */
    @OnFriendAddRequest
    public void friendAddRequest(MiraiFriendRequest miraiFriendRequest) {
        long fromId = miraiFriendRequest.getEvent().getFromId();
        log.info(fromId + ",添加我为好友");
        //触发关键词即自动同意,否则拒绝
        if (miraiFriendRequest.getEvent().getMessage().equals("我爱你")) {
            log.info("同意添加" + fromId + "为好友");
            miraiFriendRequest.getEvent().accept();
        } else {
            log.info("拒绝添加" + fromId + "为好友");
            miraiFriendRequest.getEvent().reject(false);
        }
    }    


    /**
     * 监听私聊消息
     */
    @OnPrivate
    public void privateMsg(PrivateMsg privateMsg, MsgSender sender) {
        // 智能聊天
        sendMsg(privateMsg, sender, false);
    }


    /**
     * 监听群消息
     */
    @OnGroup
    public ReplyAble groupMsg(GroupMsg groupMsg, MsgSender sender) {
        // 默认关闭群聊模式,需要的话把注释去掉
        //return sendMsg(groupMsg, sender, true);
        return null;
    }

    /**
     * 通过青客云封装智能聊天
     */
    private ReplyAble sendMsg(MessageGet commonMsg, MsgSender sender, boolean group) {
        log.info("智能聊天中~~~,接收消息:qq={}, msg={}", commonMsg.getAccountInfo().getAccountCode(),
                commonMsg.getMsgContent().getMsg());
        Runtime run = Runtime.getRuntime();
        //锁屏
        if (commonMsg.getMsgContent().getMsg().equals("锁屏")) {
            try {
                run.exec("cmd /c start rundll32.exe user32.dll,LockWorkStation");
                sender.SENDER.sendPrivateMsg(commonMsg, "宝!已经为您的电脑进行锁屏了哦!");
                return null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //关机
        if (commonMsg.getMsgContent().getMsg().equals("关机")) {
            try {
                run.exec("cmd /c shutdown -t 30 -s");
                sender.SENDER.sendPrivateMsg(commonMsg, "宝!已经为您的电脑进行30秒倒计时关机了哦!");
                return null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //取消关机
        if (commonMsg.getMsgContent().getMsg().equals("取消关机")) {
            try {
                run.exec("cmd /c shutdown -a");
                sender.SENDER.sendPrivateMsg(commonMsg, "宝!已经为您取消关机了哦!");
                return null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


        // MsgSender中存在三大送信器,以及非常多的重载方法。
        // 通过get请求调用聊天接口
        String result = HttpUtil.get(URL.concat("?key=free&appid=0&msg=").concat(commonMsg.getMsgContent().getMsg()));
        if (!StringUtils.isEmpty(result)) {
            final JSONObject json = JSONObject.parseObject(result);
            if (json.getInteger("result") == 0 && !StringUtils.isEmpty(json.getString("content"))) {
                final String msg = json.getString("content").replace("{br}", "\n");
                log.info("智能聊天中~~~,发送消息:qq={}, msg={}", commonMsg.getAccountInfo().getAccountCode(), msg);
                //发送群消息
                if (group) {
                    // 参数1:回复的消息 参数2:是否at当事人
                    return Reply.reply(msg, true);
                }
                //发送私聊消息
                sender.SENDER.sendPrivateMsg(commonMsg, msg);
            }
        }
        return null;
    }

}

7.修改配置文件application.properties

#配置监听的QQ号,多个QQ用逗号分割
bello.qq=1805395628
#配置监听的qq群
belloGroup.group=
#机器人的qq账号与密码,格式:QQ号:密码
simbot.core.bots=123456:123456.

# mirai心跳周期. 过长会导致被服务器断开连接. 单位毫秒
simbot.component.mirai.heartbeat-period-millis=30000
# 每次心跳时等待结果的时间.一旦心跳超时, 整个网络服务将会重启 (将消耗约 1s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响
simbot.component.mirai.heartbeat-timeout-millis=5000
# 最多尝试多少次重连
simbot.component.mirai.reconnection-retry-times=2147483647
# 使用协议类型。注,此值为枚举类 net.mamoe.mirai.utils.BotConfiguration.MiraiProtocol 的元素值,
# 可选值为:ANDROID_PHONE、ANDROID_PAD、ANDROID_WATCH
simbot.component.mirai.protocol=ANDROID_PAD
# 是否关闭mirai的bot logger
simbot.component.mirai.no-bot-log=true
# 关闭mirai网络日志
simbot.component.mirai.no-network-log=true
# mirai bot log切换使用simbot的log
simbot.component.mirai.use-simbot-bot-log=true
# mirai 网络log 切换使用simbot的log
simbot.component.mirai.use-simbot-network-log=true
# mirai配置自定义deviceInfoSeed的时候使用的随机种子。默认为1.
simbot.component.mirai.device-info-seed=1

8.启动SpringBoot项目

值得注意的是:因为涉及到登录QQ,你的机器人QQ小号必须关闭设备锁,启动项目以后会让你进行滑块验证,你复制控制台中链接(千万别漏有好长一段,你直接点可能不对要手动复制)然后打开浏览器进行验证,将获取到的ticket码发送至控制台即可,如果还是验证失败,可以多重启几次项目,然后就会给你扫描登录链接让你进行扫码登录,全部完成后,会显示"木芒果机器人启动成功"字样,代表成功,就可以进行了哦!虽然很麻烦,但是只要验证一次,他会在你项目目录下生成一个cache文件保存账号信息别删就不用重复验证!如果还是不行可以去官方文档找找具体解决方法!

图解:

 

 大概需要3-5次,可以成功了!

 9.效果图

 

感谢各位观看!如果对你有帮助,点个赞把!

如果还是没看懂,这边给一个mirai作者在b站录得教程视频链接,你可以看看:[simbot] 如何用Java写QQ机器人 V2.1.0 贴心女友级教程_哔哩哔哩_bilibili

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木芒果呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值