QQ机器人相关指令实现-对接小夹子

2023-10-27

代码地址以及视频地址

代码地址

视频地址

实现小夹子网的对接

打开小夹子网了解如何对接

小夹子网
image.png
小夹子API对接文档
image.png

完成认证的功能

通过小夹子网编写相关常量信息

public interface ClipWebConstants {
    /**
     * 基础路由
     */
    String BASIC_URI = "http://101.33.214.46/comm_pc/communication-support-clip/v1/clip-api";
    /**
     * 应用ID
     */
    String APPID = "";
    /**
     * 绑定邮箱
     */
    String mail = "18061877017@163.com";


}

编写小夹子网公共响应

@Data
public class ClipWebResponse {
    @SerializedName("result")
    private Boolean result;

    @SerializedName("code")
    private Integer code;

    @SerializedName("message")
    private String message;

    @SerializedName("data")
    private Object data;
}

引入http请求依赖

参考文档

<!--    okhttp    -->
<dependency>
    <groupId>com.mzlion</groupId>
    <artifactId>easy-okhttp</artifactId>
    <version>1.1.4</version>
</dependency>

测试认证请求是否成功

@SpringBootTest
public class ClipWebTest {
    @Test
    public void testAuth() {
        var response = HttpClient
                .get(ClipWebConstants.BASIC_URI + "/auth")
                .queryString("appId", ClipWebConstants.APPID)
                .queryString("mail", ClipWebConstants.MAIL)
                .asBean(ClipWebResponse.class);
        System.out.println(response);
    }
}

image.png

完成获取内容列表

@Test
public void testContentList() {
    var authResponse = HttpClient
            .get(ClipWebConstants.BASIC_URI + "/auth")
            .queryString("appId", ClipWebConstants.APPID)
            .queryString("mail", ClipWebConstants.MAIL)
            .asBean(ClipWebResponse.class);
    String token = authResponse.getData().toString();
    var contentListResponse = HttpClient
            .get(ClipWebConstants.BASIC_URI + "/contentList")
            .header("ApiToken", token)
            .queryString("title", "qq")
            .queryString("current", 1)
            .queryString("size", 100)
            .asBean(ClipWebResponse.class);
    System.out.println(contentListResponse);
}

image.png

实现list_clip_title_like指令

增加相关配置信息

在application.yml中加入

qq:
  owner: 1781913075
  group: 680634950

指令定义

模糊查询clip列表

定义指令: list_clip_title_like

对应正则: list_clip_title_like\s.{1,30}

编写list_clip_title_like指令代码

    @OnGroup
    @Filter(value = "list_clip_title_like\s(?<title>.{1,30})", matchType = MatchType.REGEX_MATCHES, trim = true)
    public void doPrivateMsg(GroupMsg event, MsgSender sender, @FilterValue("title") String title) {
        GroupInfo groupInfo = event.getGroupInfo();
        if (groupCode.equals(groupInfo.getGroupCode())) {
            String msg = event.getMsg();
            System.out.println("=============");
            System.out.println(title);
            System.out.println("=============");
        }
    }
}

image.png

image.png

实现token缓存,引入相关依赖

<!--    redis    -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--    fastjson    -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.72</version>
</dependency>

在application.yml添加相关配置信息

spring:
  redis:
    url: redis://123456@localhost:6379
    username: root
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        min-idle: 0
        max-idle: 8
/**
 * Redis使用FastJson序列化
 *
 * @author linq
 */
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    static {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    }

    @SuppressWarnings("unused")
    private ObjectMapper objectMapper = new ObjectMapper();
    private Class<T> clazz;

    public FastJson2JsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);

        return JSON.parseObject(str, clazz);
    }

    public void setObjectMapper(ObjectMapper objectMapper) {
        Assert.notNull(objectMapper, "'objectMapper' must not be null");
        this.objectMapper = objectMapper;
    }

    protected JavaType getJavaType(Class<?> clazz) {
        return TypeFactory.defaultInstance().constructType(clazz);
    }
}
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    @SuppressWarnings(value = {"unchecked", "rawtypes", "deprecation"})
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);

        template.setValueSerializer(serializer);
        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}
@Slf4j
@Component("simpleBotPrivateMsgEvent")
public class SimpleBotPrivateMsgEvent {

    @Value("${qq.group}")
    private String groupCode;
    @Value("${qq.owner}")
    private String ownerCode;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @PostConstruct
    public void initAuthToken() {
        doSetAuthToken();
        log.info("auth-token: {}", stringRedisTemplate.opsForValue().get(ClipWebConstants.AUTH_TOKEN));
    }

    private void doSetAuthToken() {
        var response = HttpClient
                .get(ClipWebConstants.BASIC_URI + "/auth")
                .queryString("appId", ClipWebConstants.APPID)
                .queryString("mail", ClipWebConstants.MAIL)
                .asBean(ClipWebResponse.class);
        stringRedisTemplate.opsForValue().setIfAbsent(ClipWebConstants.AUTH_TOKEN, response.getData().toString(), 12, TimeUnit.HOURS);
    }


    @OnGroup
    @Filter(value = "list_clip_title_like\s(?<title>.{1,30})", matchType = MatchType.REGEX_MATCHES, trim = true)
    public void doPrivateMsg(GroupMsg event, MsgSender sender, @FilterValue("title") String title) {
        GroupInfo groupInfo = event.getGroupInfo();
        if (groupCode.equals(groupInfo.getGroupCode())) {
            String authToken = stringRedisTemplate.opsForValue().get(ClipWebConstants.AUTH_TOKEN);
            if (authToken == null || authToken.equals("")) {
                doSetAuthToken();
            }
            String msg = event.getMsg();
            System.out.println("=============");
            System.out.println(title);
            System.out.println("=============");
        }
    }


}

完成推送功能

package linc.cool.robot.simple;

import catcode.CatCodeUtil;
import catcode.CodeBuilder;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mzlion.easyokhttp.HttpClient;
import linc.cool.robot.clip.ClipWebContentInfo;
import linc.cool.robot.clip.response.ClipWebResponse;
import linc.cool.robot.constants.ClipWebConstants;
import lombok.extern.slf4j.Slf4j;
import love.forte.simbot.annotation.Filter;
import love.forte.simbot.annotation.FilterValue;
import love.forte.simbot.annotation.OnGroup;
import love.forte.simbot.api.message.containers.GroupAccountInfo;
import love.forte.simbot.api.message.containers.GroupInfo;
import love.forte.simbot.api.message.events.GroupMsg;
import love.forte.simbot.api.sender.MsgSender;
import love.forte.simbot.filter.MatchType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author yqlin
 * @date 2022/4/6 17:05
 * @description
 */
@Slf4j
@Component("simpleBotPrivateMsgEvent")
public class SimpleBotPrivateMsgEvent {

    @Value("${qq.group}")
    private String groupCode;
    @Value("${qq.owner}")
    private String ownerCode;
    private final CatCodeUtil catCodeUtil = CatCodeUtil.INSTANCE;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @PostConstruct
    public void initAuthToken() {
        doSetAuthToken();
        log.info("auth-token: {}", stringRedisTemplate.opsForValue().get(ClipWebConstants.AUTH_TOKEN));
    }

    private void doSetAuthToken() {
        var response = HttpClient
                .get(ClipWebConstants.BASIC_URI + "/auth")
                .queryString("appId", ClipWebConstants.APPID)
                .queryString("mail", ClipWebConstants.MAIL)
                .asBean(ClipWebResponse.class);
        stringRedisTemplate.opsForValue().setIfAbsent(ClipWebConstants.AUTH_TOKEN, response.getData().toString(), 12, TimeUnit.HOURS);
    }


    @OnGroup
    @Filter(value = "list_clip_title_like\s(?<title>.{1,30})", matchType = MatchType.REGEX_MATCHES, trim = true)
    public void doPrivateMsg(GroupMsg event, MsgSender sender, @FilterValue("title") String title) {
        GroupInfo groupInfo = event.getGroupInfo();
        if (groupCode.equals(groupInfo.getGroupCode())) {
            String authToken = stringRedisTemplate.opsForValue().get(ClipWebConstants.AUTH_TOKEN);
            if (authToken == null || authToken.equals("")) {
                doSetAuthToken();
            }
            authToken = stringRedisTemplate.opsForValue().get(ClipWebConstants.AUTH_TOKEN);
            List<ClipWebContentInfo> contentInfoList = doGetUrlList(title, authToken);
            final CodeBuilder<String> codeBuilder = catCodeUtil.getStringCodeBuilder("at", false);
            GroupAccountInfo accountInfo = event.getAccountInfo();
            String atAccountInfo = codeBuilder.key("code").value(accountInfo.getAccountCode()).build();
            StringBuilder contentInfo = new StringBuilder();
            for (ClipWebContentInfo content : contentInfoList) {
                contentInfo.append(content.getTitle()).append("->").append(content.getUrlContent()).append("\n");
            }
            String template = """
                    = = = 亮哥小弟提示你 = = =
                            %s   
                            %s    
                    = = = = = = = = = = = =                
                            """;
            sender.SENDER.sendGroupMsgAsync(groupCode, String.format(template, contentInfo, atAccountInfo));
        }
    }

    private List<ClipWebContentInfo> doGetUrlList(String title, String authToken) {
        var contentListResponse = HttpClient
                .get(ClipWebConstants.BASIC_URI + "/contentList")
                .header("ApiToken", authToken)
                .queryString("title", title)
                .queryString("current", 1)
                .queryString("size", 100)
                .asBean(ClipWebResponse.class);
        Object data = contentListResponse.getData();
        JSONObject jsonObject = JSONArray.parseObject(JSON.toJSONString(data));
        JSONArray records = jsonObject.getJSONArray("records");
        List<ClipWebContentInfo> contentList = new ArrayList<>();
        for (int i = 0; i < records.size(); i++) {
            JSONObject record = records.getJSONObject(i);
            String t = String.valueOf(record.get("title"));
            String u = String.valueOf(record.get("urlContent"));
            contentList.add(new ClipWebContentInfo(t, u));
        }
        return contentList;
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QQ机器人相关指令实现-对接小夹子 的相关文章

随机推荐

  • ApacheBench_ab性能测试工具

    前言 在学习使用ab命令之前 首先要了解压力测试的几个概念 吞吐率 Requests per second 概念 服务器并发处理能力的量化描述 单位是reqs s 指的是某个并发用户数下单位时间内处理的请求数 某个并发用户数下单位时间内能处
  • VS中Qt项目不能打开ui文件

    在VS中创建的Qt项目 若不能打开ui文件 或者弹出以下提示的 其本质是找不到designer exe的路径 那么需要手动添加designer exe的路径 第一步 右键点击打不开的ui文件 选择打开方式 第二步 点击添加 第三步 点击右侧
  • 解空间的维数

    线性代数 齐次方程组的系数矩阵的秩与增广矩阵的秩为R a 解空间的维数就是n R a 维数为1 直线 维数为2 面 维数为3 空间
  • [个人笔记]FDTD solutions8.0 02

    先再次熟悉一下软件布局 演示实验 在玻璃基底上镀50nm厚的硅 测量400 800nm宽光谱的反射率和透射率 创建模型 玻璃底是一个基本的长方体 在结构中可以找到基本的几何体模型 如果想删除你创建的物体 找到Object Tree 选选中你
  • Node.js之模块系统

    CommonJS规范 希望JavaScript可以在任何地方运行 以达到像Java PHP Ruby Python具备开发大型应用的能力 出发点 没有模块系统 标准库较少 缺乏包管理系统 CommonJS模块规范 模块引用require 模
  • 使用json-server出现的 500 internal server error

    首先声明 是使用json server搭建本地数据接口 在请求数据中出现的 500错误哦 最近在做一个项目 为了找工作使用的 o 使用的是json server搭建的本地数据接口 在实现注册页面向搭建的数据接口post数据的时候 遇到了一个
  • Tensorflow深度学习笔记(四)-利用神经网络预测非线性回归示例

    本文主要分享一个利用神经网络来预测非线性回归的示例 首先 定义生成我们的测试数据 即y data np square x data noise 通过x data的平方再加上噪声来生成y data 然后 利用神经网络 将x data作为输入
  • 区块链在数字经济中的地位和作用都有哪些?

    区块链是校正经济数字化进程的关键性底层技术架构 具有不可替代的作用 数字经济的关键技术包括大数据 物联网 人工智能 区块链等 技术是实现经济数字化的手段 不同的技术在经济数字化过程中扮演着不同的角色 云计算 边缘计算 IPFS按需提供数据存
  • Android加密和解密(DES,AES,MD5)

    加密是通过加密算法和加密密钥将明文转变为密文的过程 解密是其逆过程 加密算法有很多种 一般可以分为对称加密 如DES AES等 非对称加密 如RSA等 和单向加密 如MD5等 3类算法 1 在对称加密算法中 双方使用的密钥相同 要求解密方事
  • 科技查新报告的查新流程

    科技查新可以当天出报告吗 亲 我着急做一篇科技查新 当天能出报告吗 一天的时间是不够的 额 一般是多久呢 二到十个工作日 大家可能会很疑惑 为啥连查新员自己都不好确定报告的完成时间呢 这就要说说一份科技查新报告是怎么写出来的了 看完这个业务
  • C语言编写学生籍贯信息记录簿

    学生籍贯信息记录簿 前言 这是本人第一次写博客 有不足之处请见谅 本文是利用简单的C语言编写的学生籍贯信息记录簿 写这篇是为了记录学习过程 也为后来者提供一些参考和思路 我使用的平台为Visual C 6 0 其功能主要分为录入 保存 查询
  • hadoop报错:Exception in thread “main“ org.apache.hadoop.security.AccessControlException: Permission de

    Exception in thread main org apache hadoop security AccessControlException Permission denied user xuan access WRITE inod
  • R 安装函数包及绘制图形

    R语言绘制简单条形图 一 载入数据 1 安装函数包 2 导入文件 3 读取数据 csv文件 二 绘制图形 绘制简单条形图 一 载入数据 1 安装函数包 在控制台console输入命令 install packages bruceR 查看是否
  • Qt笔记(五十九)之Qt使用自定义字体

    一 前言 楼主在实际开发中 遇到有使用对界面字体要求的需求 有些客户希望用自己的字体 一开始 楼主还是有点懵 但是想到Qt一开始肯定是考虑到这个方式了 于是就去寻找 果然有 二 设置字体 1 使用内置字体 常规的设置方式 QApplicat
  • python语法-函数多返回值、函数多种传参方式、匿名函数

    python语法 函数多返回值 函数多种传参方式 匿名函数 函数多返回值 函数多个返回值 def test return return 1 hello True x y z test return print f x x ny y nz z
  • angularJs中的发送请求例子

    http 发送请求 url http localhost 8080 teacher api login method post data obj success function data rootScope data data 返回结果
  • MacBookAir M1 遇到 nodesass不兼容问题的解决方案

    引言 在工作中接手了一个新项目 项目采用了nodesass 想尽方法让他跑起来 却抛出一个错误 Node Sass does not yet support your current environment OS X Unsupported
  • [1151]python连接 redis cluster集群

    使用pip search查看可安装的Redis模块版本 PS D code gt pip install pip search 安装pip search模块 PS D code gt pip search redis 利用pip searc
  • 从DEMO到完成项目过程的流程

    一 项目评审 认真看demo需求是关键 根据项目demo原型 将项目功能点细分 按每个功能点实现的大致期限 去估计整个项目的期限 一旦项目评估预期确定 需要严格按照预期来实现 决不能拖拉 二 项目实施中 项目实施中 尽量以实现demo功能为
  • QQ机器人相关指令实现-对接小夹子

    代码地址以及视频地址 代码地址 视频地址 实现小夹子网的对接 打开小夹子网了解如何对接 小夹子网 小夹子API对接文档 完成认证的功能 通过小夹子网编写相关常量信息 public interface ClipWebConstants 基础路