QQ robot related instructions implementation - docking small clip

Code address and video address

code address
video address

Realize the docking of small clip network

Open the small clip network to learn how to connect

Small clip network image.png small clip API docking document image.png

Complete the function of authentication

Write related constant information through the small clip network

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]";


}
复制代码

Write a small clip net public response

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

    @SerializedName("code")
    private Integer code;

    @SerializedName("message")
    private String message;

    @SerializedName("data")
    private Object data;
}
复制代码

Introduce http request dependencies

Reference documentation

<!--    okhttp    -->
<dependency>
    <groupId>com.mzlion</groupId>
    <artifactId>easy-okhttp</artifactId>
    <version>1.1.4</version>
</dependency>
复制代码

Test if the authentication request is successful

@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

Finish getting the content list

@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

Implement the list_clip_title_like directive

Add related configuration information

Add in application.yml

qq:
  owner: 1781913075
  group: 680634950
复制代码

Instruction definition

Fuzzy query clip list
definition command : list_clip_title_like
corresponding regular : list_clip_title_like\s.{1,30}

Write list_clip_title_like instruction code

    @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

Implement token caching and introduce related dependencies

<!--    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>
复制代码

Add relevant configuration information in 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("=============");
        }
    }


}
复制代码

Complete push function

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;
    }

}
复制代码

Guess you like

Origin juejin.im/post/7083905813131034632