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

代码地址以及视频地址

代码地址
视频地址

实现小夹子网的对接

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

小夹子网 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 = "[email protected]";


}
复制代码

编写小夹子网公共响应

@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
```java
/**
 * 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;
    }

}
复制代码

猜你喜欢

转载自juejin.im/post/7083905813131034632