您现在的位置是:首页 >学无止境 >QQ机器人接入国内版ChatGPT网站首页学无止境

QQ机器人接入国内版ChatGPT

.鱼子酱 2024-06-17 10:22:13
简介QQ机器人接入国内版ChatGPT

实现的功能

1.调用国内版ChatGPT的API进行私聊,QQ群@聊天

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

3.定时自动发送消息

本项目使用了JDK17,如果已经导入了相应的jar包但代码还是爆红显示找不到class:

1.禁用kotlin插件。

2.检查idea的版本,建议2022.1以上。

GitHub讨论,有问题可以去这里提: https://github.com/orgs/simple-robot/discussions

Robot 官方文档: https://simbot.forte.love

 

 1. 新建一个空白的springBoot项目

fec659e9f5f14a3483afdd98b9149348.png

 0bbeddcda94b418897c49376453750d2.png

 2.引入相关依赖

        <!--java机器人框架-->
        <dependency>
            <groupId>love.forte.simbot.boot</groupId>
            <artifactId>simboot-core-spring-boot-starter</artifactId>
            <version>3.0.0-RC.3</version>
        </dependency>

        <dependency>
            <groupId>love.forte.simbot.component</groupId>
            <artifactId>simbot-component-mirai-core</artifactId>
            <version>3.0.0.0-beta.6</version>
        </dependency>


        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>2.0.20</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--okhttp3用来请求chatGPT的API接口-->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.10.0</version>
        </dependency>

 3.编写application.properties配置文件

# 是否在bot注册完成后自动启动他们。
# 默认为true
simbot.auto-start-bots=true
 
# 自定义配置bot资源文件的扫描路径。
# 默认为 classpath:simbot-bots/*.bot*
simbot.bot-configuration-resources[0]=classpath:simbot-bots/*.bot*
 
#配置监听的QQ号,多个QQ用逗号分割
MonitorQQ=2741744509

4.根据application.properties配置文件配置得到,需要在resources目录下新建一个simbot-bots目录,在里面新建一个xxx.bot.json的文件,根据自己的实际情况对配置文件进行修改即可!

334e064b31034a578850ad112f4e25d2.png

{
  "component": "simbot.mirai",
  "code": 你的QQ账号,
  "passwordInfo": {
    "type": "text",
    "text": "你的密码"
  },
  "config": {
    "protocol": "MACOS"
  }
}

5.定时发送信息类,通过配置达到自动发信息的目的,在代码中更改你自己的QQ机器人号,此功能可写可不写!

package com.yy.qqrobot.scheduling;

import lombok.extern.slf4j.Slf4j;
import love.forte.simbot.Identifies;
import love.forte.simbot.application.BotManagers;
import love.forte.simbot.bot.BotManager;
import love.forte.simbot.component.mirai.MiraiFriend;
import love.forte.simbot.component.mirai.bot.MiraiBot;
import love.forte.simbot.component.mirai.bot.MiraiBotManager;
import love.forte.simbot.component.mirai.message.MiraiSendOnlyImage;
import love.forte.simbot.resources.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.net.URL;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Set;

@Component
@Slf4j
public class AutoQQMessage {
    

    @Autowired
    private BotManagers botManagers;

    @Value("${MonitorQQ}")
    private Set<String> qqSet;

    /**
     * 定义语录
     */
    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 * * * ?
     * 每天晚上8点: 0 0 20 * * ?
     */
    @Scheduled(cron = "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 SecureRandom().nextInt(content.size()));
                //图片URL: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
                final String img = images.get(new SecureRandom().nextInt(images.size()));
                // 获取所有的bot
                for (BotManager<?> manager : botManagers) {
                    if (manager instanceof MiraiBotManager miraiBotManager) {
                        MiraiBot bot = miraiBotManager.get(Identifies.ID("你的机器人QQ号"));
                        // 拿到bot,怎么操作看你心情,比如往某个群发消息
                        assert bot != null;
                        MiraiFriend friend = bot.getFriend(Identifies.ID(qq));
                        assert friend != null;
                        friend.sendAsync(msg);
                        // 构建图片
                        MiraiSendOnlyImage offlineImage = MiraiSendOnlyImage.of(Resource.of(new URL(img)));
                        // 上传图片到friend,然后向其发送
                        // 得到发送回执的 Future
                        offlineImage.uploadAsync(friend).thenCompose(friend::sendAsync);
                        log.info("正在发送定义语录,当前qq={}, 语录={}, img={}", qq, msg, img);
                        break;
                    }
                }
            } catch (Exception e) {
                log.error("发送定义语录异常, qq={}", qq, e);
            }
        });
    }
}

6.监听消息类

package com.yy.qqrobot.listener;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import love.forte.simboot.annotation.Filter;
import love.forte.simboot.annotation.Listener;
import love.forte.simbot.ID;
import love.forte.simbot.event.FriendAddRequestEvent;
import love.forte.simbot.event.FriendMessageEvent;
import love.forte.simbot.event.GroupMessageEvent;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 监听类
 * Author:鱼子酱
 */
@Component
@Slf4j
public class MessageListener {
    //青云客url
    static final String URLqyk = "http://api.qingyunke.com/api.php";
    //舔狗日记url
    static final String URLtgrj = "https://v.api.aa1.cn/api/tiangou/index.php";


    /**
     * 监听好友添加请求
     */
    @Listener
    public void onFriendAddRequest(FriendAddRequestEvent friendAddRequestEvent) {
        String message = friendAddRequestEvent.getMessage();
        ID id = friendAddRequestEvent.getFriend().getId();
        log.info(id + ",添加我为好友");
        //触发关键词即自动同意,否则拒绝
        if (Objects.equals(message, "鱼子酱")) {
            log.info("同意添加" + id + "为好友");
            friendAddRequestEvent.acceptAsync();
        } else {
            log.info("拒绝添加" + id + "为好友");
            friendAddRequestEvent.rejectAsync();
        }
    }

    /**
     * 监听私信消息
     */
    @Listener
    public synchronized void onMessage(FriendMessageEvent friendMessage) throws IOException {
        String msg = friendMessage.getMessageContent().getPlainText();
        //把空格自动转换为逗号
        msg = msg.trim().replaceAll(" ", ",");
        log.info(friendMessage.getFriend().getId() + "提问:" + msg);
        //AI自动回复
        String reply = chatGPT(msg);
        if (reply == null) {
            reply = "回复失败!重新试试把!";
        }
        //异步回复消息
        friendMessage.replyAsync(reply);
    }
    /**
     * 监听群消息
     */
    @Listener
    @Filter(targets = @Filter.Targets(atBot = true))
    public synchronized void onGroupMessage(GroupMessageEvent groupMessage) throws IOException {
        String msg = groupMessage.getMessageContent().getPlainText();
        if (msg.equals(""))
            return;

        log.info(groupMessage.getAuthor().getId() + "提问:" + msg);

        msg = msg.trim().replaceAll(" ", ",");
        //AI自动回复
        String reply = chatGPT(msg);

        //异步回复消息
        groupMessage.replyAsync(reply);
    }
    

    public static String AiOne(String sendMsg) {
        try {
            String url = URLqyk + "?key=free&appid=0&msg=" + sendMsg;

            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(120, TimeUnit.SECONDS)//设置连接超时时间
                    .readTimeout(120, TimeUnit.SECONDS)//设置读取超时时间
                    .build();

            okhttp3.Request request = new okhttp3.Request.Builder()
                    .url(url)
                    .get()
                    .build();

            String json = client.newCall(request).execute().body().string();
            JSONObject jsonObject = JSON.parseObject(json);
            Integer result = jsonObject.getInteger("result");
            String content = jsonObject.getString("content");

            return result != 0 ? null:content;

        } catch (Exception e) {
            log.error(e.toString());
            return null;
        }
    }
    public static String chatGPT(String msg) throws IOException {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(120, TimeUnit.SECONDS)//设置连接超时时间
                .readTimeout(120, TimeUnit.SECONDS)//设置读取超时时间
                .build();

        String url = StringUtils.uriDecode("http://6.hnruanda.top/api?content="+msg, Charset.defaultCharset());

        okhttp3.Request request = new okhttp3.Request.Builder()
                .url(url)
                .get()
                .build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

}

 7.代码部分完成,由于腾讯管理的太严需要用到一个安卓的app进行qq登录验证

下载链接:Releases · kagg886/Seiko · GitHub,下的慢的可以挂国外加速器

下载好以后,打开是这样的,我用的是V0.1.6版本,选择MACOS协议或者手表协议登录即可。选择好协议记得把demo.bot.json文件的协议与登录协议保持一致

 d065302bc1dd401ebc9b72d49945f295.jpeg

 

{
  "component": "simbot.mirai",
  "code": 你的QQ账号,
  "passwordInfo": {
    "type": "text",
    "text": "你的密码"
  },
  "config": {
    "protocol": "ANDROID_WATCH"
  }
}

登录好以后将登录的数据打包发送到电脑上(点 导出登录信息)

afc7f603264643fc898f64ec2cbb5905.jpeg

发送到电脑端以后是一个压缩包,我们只要cache目录和device.json和loginTemplate.yml文件,将这三个文件复制粘贴到项目的根目录下,用于认证 

354039a3305b437883507a8ebe8e2ce2.png 

c5e255ed4c2347bbb5b3120fb936e617.png 

如登录还是遭遇235或45错误,可以试着多换几种协议试试,如果还是不行请更换一个新的QQ账号!可以注册一个新的QQ号!

8.编写启动类

@EnableSimbot //开启Simbot
@EnableScheduling //开启定时任务
@SpringBootApplication
@Slf4j
public class RobotApplication {
    private static final Logger log = LoggerFactory.getLogger(qqRobotApplication.class);
    public static void main(String[] args) {
        SpringApplication.run(qqRobotApplication.class, args);
        log.info("鱼子酱机器人启动成功!");
    }
}

如果还没学会可以观看官方教程:【simbot3】如何用JAVA写机器人 还是入门篇 v3.0_哔哩哔哩_bilibili,有问题留言评论,我会第一时间解答!

 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。