用JAVA做個(gè)QQ機(jī)器人,幫我提醒女神按時(shí)喝水和陪她聊天~(帶源碼)

微信機(jī)器人會(huì)有幾率封號(hào),暫時(shí)不開(kāi)教程

1、前言

正常人每天平均耗水量為2000-2500毫升,體內(nèi)物質(zhì)氧化可生水300毫升,故每日應(yīng)補(bǔ)充水分2200毫升,包括飲食中的含水量。夏天每日補(bǔ)充水分在3000毫升左右,才能滿足人體需要。
如果有個(gè)機(jī)器人能按時(shí)提醒我們喝水,那該多好啊~~

2、創(chuàng)建一個(gè)springboot項(xiàng)目

(這個(gè)步驟是為小白提供,大佬們直接跳到第三步)

2.1. 新建項(xiàng)目

在這里插入圖片描述

2.2. 選擇springboot項(xiàng)目

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

2.3. 創(chuàng)建完成的項(xiàng)目結(jié)構(gòu)如下

在這里插入圖片描述

3、引入simple-robot機(jī)器人依賴

3.1. 在pom.xml文件引入simple-robot依賴

<properties>
    <java.version>1.8</java.version>
    <simbot.version>2.0.3</simbot.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>love.forte.simple-robot</groupId>
            <artifactId>parent</artifactId>
            <version>${simbot.version}</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>
<!--java機(jī)器人框架-->
<dependency>
    <groupId>love.forte.simple-robot</groupId>
    <artifactId>component-mirai-spring-boot-starter</artifactId>
</dependency>
在這里插入圖片描述

3.2. 配置application.yml文件,使用ANDROID_PAD協(xié)議可以保持手機(jī)QQ和機(jī)器人同時(shí)在線

simbot:
  core:
    # 機(jī)器人的QQ賬號(hào)與密碼(帳號(hào):密碼)
    bots: 6013505:yinfeng
  component:
    mirai:
      # mirai心跳周期. 過(guò)長(zhǎng)會(huì)導(dǎo)致被服務(wù)器斷開(kāi)連接. 單位毫秒。
      heartbeat-period-millis: 30000
      # 每次心跳時(shí)等待結(jié)果的時(shí)間.一旦心跳超時(shí), 整個(gè)網(wǎng)絡(luò)服務(wù)將會(huì)重啟 (將消耗約 1s). 除正在進(jìn)行的任務(wù) (如圖片上傳) 會(huì)被中斷外, 事件和插件均不受影響.
      heartbeat-timeout-millis: 5000
      # 心跳失敗后的第一次重連前的等待時(shí)間.
      first-reconnect-delay-millis: 5000
      # 重連失敗后, 繼續(xù)嘗試的每次等待時(shí)間
      reconnect-period-millis: 5000
      # 最多嘗試多少次重連
      reconnection-retry-times: 2147483647
      # 使用協(xié)議類型。注,此值為枚舉類 net.mamoe.mirai.utils.BotConfiguration.MiraiProtocol 的元素值,
      # 可選值為:ANDROID_PHONE、ANDROID_PAD、ANDROID_WATCH
      protocol: ANDROID_PAD
      # 是否關(guān)閉mirai的bot logger
      no-bot-log: true
      # 關(guān)閉mirai網(wǎng)絡(luò)日志
      no-network-log: true
      # mirai bot log切換使用simbot的log
      use-simbot-bot-log: true
      # mirai 網(wǎng)絡(luò)log 切換使用simbot的log
      use-simbot-network-log: true
      # mirai配置自定義deviceInfoSeed的時(shí)候使用的隨機(jī)種子。默認(rèn)為1.
      device-info-seed: 1
      # mirai圖片緩存策略,為枚舉 love.forte.simbot.component.mirai.configuration.MiraiCacheType 的元素值,
      # 可選為 FILE、 MEMORY
      cache-type: MEMORY
      # 如果配置項(xiàng) simbot.mirai.cacheType 的值為 FILE,此處為緩存文件的保存目錄。為空時(shí)默認(rèn)為系統(tǒng)臨時(shí)文件夾。
      cache-directory:
      # 登錄驗(yàn)證碼處理器,當(dāng)?shù)卿浶枰斎腧?yàn)證碼的時(shí)候可能會(huì)用到。
      login-solver-type: DEFAULT
      # 如果不為空,此處代表指定一個(gè) deviceInfo 的 json文件路徑。
      dispatcher:
        # mirai組件中,對(duì)事件進(jìn)行調(diào)度的線程池參數(shù):最大線程數(shù)。
        core-pool-size: 8
        # mirai組件中,對(duì)事件進(jìn)行調(diào)度的線程池參數(shù):最大線程數(shù)。
        maximum-pool-size: 8
        # mirai組件中,對(duì)事件進(jìn)行調(diào)度的線程池參數(shù):線程存活時(shí)間(毫秒)
        keep-alive-time: 1000
在這里插入圖片描述

3.3 在springboot啟動(dòng)類加上@EnableSimbot注解

/**
* @author yinfeng
* @description 啟動(dòng)類
* @since 2021/12/22 22:50
*/
@EnableSimbot
@EnableScheduling
@SpringBootApplication
@Slf4j
public class RobotApplication {

   public static void main(String[] args) {
       SpringApplication.run(RobotApplication.class, args);
       log.info("機(jī)器人啟動(dòng)成功~~~~");
   }

}

3.4 simple-robot機(jī)器人官方文檔

https://www.yuque.com/simpler-robot/simpler-robot-doc/gbqsz5

4、編寫(xiě)定時(shí)任務(wù)

4.1. 創(chuàng)建一個(gè)DrinkNotify.java類

/**
 * @author yinfeng
 * @description 定時(shí)喝水提醒
 * @since 2021/12/22 23:32
 */
@Component
@Slf4j
public class DrinkNotify {

    @Resource
    private BotManager botManager;

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

    /**
     * 喝水語(yǔ)錄
     */
    static List<String> content;

    /**
     * 喝水圖片
     */
    static List<String> images;

    static {
        content = new ArrayList<>();
        images = new ArrayList<>();
        log.info("開(kāi)始加載喝水語(yǔ)錄~~~");
        // 喝水語(yǔ)錄
        content.add("俗話說(shuō)\"女人是水造的\",所以身為女生就要時(shí)刻喝水,這樣就可以保持充足的水分,皮膚、頭發(fā)就會(huì)更有光澤~");
        content.add("喝多點(diǎn)水還可以保持身材哦,因?yàn)樗龠M(jìn)了我們身體的循環(huán)~");
        content.add("該喝水了喲,喝多點(diǎn)水整體上也會(huì)容光煥發(fā)~");
        content.add("該喝水了喲,要多愛(ài)護(hù)自己,多喝水、多吃新鮮水果蔬菜、盡量保證充足睡眠。加油!");
        content.add("多喝水很簡(jiǎn)單的話,多喝水對(duì)身體好!只有心中掛念著你們的人才會(huì)說(shuō)你的家人也老說(shuō)的話:你要多喝水呀?。");
        content.add("天氣寒冷干燥。多喝水,注意保暖。少抽煙喝酒吃辣。多想念我~");
        log.info("開(kāi)始加載喝水圖片~~~");
        // 喝水圖片
        images.add("https://gitee.com/yinfeng-code/study-image/raw/master/image/20211224221637.jpeg");
        images.add("https://gitee.com/yinfeng-code/study-image/raw/master/image/20211224221739.jpeg");
        images.add("https://gitee.com/yinfeng-code/study-image/raw/master/image/20211224221758.jpeg");
        images.add("https://gitee.com/yinfeng-code/study-image/raw/master/image/20211224221815.jpeg");
        images.add("https://gitee.com/yinfeng-code/study-image/raw/master/image/20211224221834.jpeg");
        images.add("https://gitee.com/yinfeng-code/study-image/raw/master/image/20211224221913.jpeg");
        images.add("https://gitee.com/yinfeng-code/study-image/raw/master/image/20211224221925.jpeg");
    }

    /**
     * 每一分鐘提醒一次: 0 0/1 * * * ?
     * 每一小時(shí)提醒一次: 0 0 0/1 * * ?
     */
    @Scheduled(cron = "0 0 0/1 * * ?")
    public void handler() {
        Calendar calendar = Calendar.getInstance();
        // 獲取當(dāng)前小時(shí)
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        // 只在早上9點(diǎn)到晚上8點(diǎn)發(fā)送消息提醒
        if (hour < 9 || hour > 20) {
            return;
        }
        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(content.size())));
                // 發(fā)送隨機(jī)喝水語(yǔ)錄
                botManager.getDefaultBot().getSender().SENDER.sendPrivateMsg(qq, msg);
                // 發(fā)送隨機(jī)喝水圖片
                botManager.getDefaultBot().getSender().SENDER.sendPrivateMsg(qq, img);
                log.info("正在發(fā)送喝水提醒,當(dāng)前qq={}, 語(yǔ)錄={}, img={}", qq, msg, img);
            } catch (Exception e) {
                log.error("發(fā)送喝水提醒異常, qq={}", qq, e);
            }

        });
    }

}

4.2. 在yml文件中配置女神們的QQ號(hào)

#配置女神們的QQ號(hào),多個(gè)QQ用逗號(hào)分割
bello:
 qq: 1332483344,52000012
在這里插入圖片描述

5、加入智能聊天功能

5.1. 這里主要使用青云客的api進(jìn)行聊天,官網(wǎng)

http://api.qingyunke.com/

5.2. 封裝http工具類

/**
 * @author yinfeng
 * @description http工具類
 * @since 2021/12/23 23:21
 */
public class HttpUtil {
    /**
     * 向指定URL發(fā)送GET方法的請(qǐng)求
     *
     * @param url   發(fā)送請(qǐng)求的URL
     * @param param 請(qǐng)求參數(shù),請(qǐng)求參數(shù)應(yīng)該是 name1=value1&name2=value2 的形式。
     * @return URL 所代表遠(yuǎn)程資源的響應(yīng)結(jié)果
     */
    public static String sendGet(String url, String param) {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        try {
            String urlNameString = url;
            if (!StringUtils.isEmpty(param)) {
                urlNameString += "?" + param;
            }
            URL realUrl = new URL(urlNameString);
            // 打開(kāi)和URL之間的連接
            URLConnection connection = realUrl.openConnection();
            // 設(shè)置通用的請(qǐng)求屬性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1");
            // 建立實(shí)際的連接
            connection.connect();
            // 定義 BufferedReader輸入流來(lái)讀取URL的響應(yīng)
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            System.out.println("發(fā)送GET請(qǐng)求出現(xiàn)異常!" + e);
            e.printStackTrace();
        }
        // 使用finally塊來(lái)關(guān)閉輸入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result.toString();
    }
}

5.3. 創(chuàng)建消息監(jiān)聽(tīng)類,支持私聊消息和群消息的智能聊天

/**
 * @author yinfeng
 * @description 機(jī)器人監(jiān)聽(tīng)
 * @since 2021/11/6 20:51
 */
@Component
@Slf4j
public class MessageListener {

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

    /**
     * 監(jiān)聽(tīng)私聊消息
     */
    @OnPrivate
    public void privateMsg(PrivateMsg privateMsg, MsgSender sender) {
        sendMsg(privateMsg, sender, false);
    }

    /**
     * 監(jiān)聽(tīng)群消息
     */
    @OnGroup
    public ReplyAble groupMsg(GroupMsg groupMsg, MsgSender sender) {
        // 默認(rèn)關(guān)閉群聊模式,需要的話把注釋去掉
        // return sendMsg(groupMsg, sender, true);
        return null;
    }

    /**
     * 通過(guò)青客云封裝智能聊天
     *
     * @param commonMsg commonMsg
     * @param sender    sender
     */
    private ReplyAble sendMsg(MessageGet commonMsg, MsgSender sender, boolean group) {
        log.info("智能聊天中~~~,接收消息:qq={}, msg={}", commonMsg.getAccountInfo().getAccountCode(),
                commonMsg.getMsgContent().getMsg());
        // MsgSender中存在三大送信器,以及非常多的重載方法。
        // 通過(guò)get請(qǐng)求調(diào)用聊天接口
        final String result = HttpUtil.sendGet(URL,
                "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("智能聊天中~~~,發(fā)送消息:qq={}, msg={}", commonMsg.getAccountInfo().getAccountCode(), msg);
                //發(fā)送群消息
                if (group) {
                    // 參數(shù)1:回復(fù)的消息 參數(shù)2:是否at當(dāng)事人
                    return Reply.reply(msg, true);
                }
                //發(fā)送私聊消息
                sender.SENDER.sendPrivateMsg(commonMsg, msg);
            }
        }
        return null;
    }

}


6、測(cè)試一下

6.1. 啟動(dòng)項(xiàng)目

在這里插入圖片描述

6.2. 喝水提醒測(cè)試

在這里插入圖片描述

可以看到兩個(gè)qq都收到了提醒消息后臺(tái)日志也是沒(méi)問(wèn)題的
在這里插入圖片描述

6.3. 智能聊天測(cè)試

在這里插入圖片描述

可以看到聊天功能也是正常的 ,后臺(tái)日志也是正常的

在這里插入圖片描述

7、源碼地址

暫時(shí)無(wú)法監(jiān)聽(tīng)==單項(xiàng)好友==的消息,老鐵們自己下載源碼來(lái)玩吧

// 源碼地址,下載運(yùn)行即可
// 也可打成jar包放在服務(wù)器一直運(yùn)行
https://gitee.com/yinfeng-code/java-robot.git

肝文不易,老鐵們三連一波支持下吧,謝謝大家了~
下了源碼的老鐵麻煩點(diǎn)個(gè)star哈

8、常見(jiàn)問(wèn)題處理

8.1. 密碼錯(cuò)誤異常

Error(title=登錄失敗, message=帳號(hào)或密碼錯(cuò)誤,請(qǐng)重新輸入。, errorInfo=)

異常截圖如下

在這里插入圖片描述

解決方案:在application.yml中配置自己的qq賬號(hào)和密碼
在這里插入圖片描述

8.2. 滑塊驗(yàn)證異常

UnsupportedSliderCaptchaException: Mirai 無(wú)法完成滑塊驗(yàn)證. 使用協(xié)議 ANDROID_PHONE 強(qiáng)制要求滑塊驗(yàn)證, 請(qǐng)更換協(xié)議后重試. 另請(qǐng)參閱

異常截圖如下

在這里插入圖片描述

解決方案:在application.yml中更換協(xié)議為PAD協(xié)議或者watch協(xié)議試試

在這里插入圖片描述

如果還不行的話可以參考機(jī)器人框架官網(wǎng)文檔滑塊登錄異常

  1. 嘗試進(jìn)行滑塊驗(yàn)證
  2. 嘗試切換賬號(hào)
  3. 開(kāi)啟或者關(guān)閉設(shè)備鎖,各種情況都試試
  4. 換一個(gè)網(wǎng)絡(luò)環(huán)境,例如切換為熱點(diǎn)
  5. 用電腦或者手機(jī)多掛掛你要用的賬號(hào),并養(yǎng)養(yǎng)號(hào)后再嘗試
  6. 以上方法都不一定成功,或者說(shuō),大概率不會(huì)成功。但是目前來(lái)看,一段時(shí)間過(guò)后基本上就會(huì)變正常。這段時(shí)間可能是幾天,運(yùn)氣好可能是幾個(gè)小時(shí)。

8.3 下載項(xiàng)目后idea導(dǎo)入異常

在這里插入圖片描述

解決方案:升級(jí)你的IDEA到 2021 或以上版本。具體參考IDEA導(dǎo)包異常報(bào)錯(cuò)

8.4 機(jī)器人其他問(wèn)題解決方案參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容