上一篇完成了项目搭建,并实现了私聊机器人复读机的功能。

本文主要实现一些群聊的功能:

  1. 当群聊有人@机器人的时候,解析@消息的内容,并通过聊天机器人接口获取聊天应答的内容进行应答。
  2. 添加一个定时任务,在每天7点及23点发送早安和晚安。
  3. 一些特定指令的解析。

技术方案

  • 聊天机器人这里使用青云客免费机器人接口,无需注册申请,简单粗暴
  • 定时功能则使用一个开源库cron
  • 部分指令解析等则使用一般正则

功能开发

聊天功能

  1. 判断消息是否有@自己,at消息的格式==[CQ:at,qq=对方QQ]==,这里简单正则判断即可

    //是否@自己
    func hasAtSelf(msg string) bool {
    	reg := regexp.MustCompile(`\[CQ:at,qq=(\d+)\]`)
    	match := reg.FindStringSubmatch(msg)
    	for _, v := range match {
    		if strconv.FormatInt(cqp.GetLoginQQ(), 10) == v {
    			return true
    		}
    	}
    	return false
    }
    
  2. 从机器人接口获取应答内容并进行回复

    //机器人智能回复
    func robotAnswer(fromGroup, fromQQ int64, msg string) {
       //get请求
       //http.Get的参数必须是带http://协议头的完整url,不然请求结果为空
       cqp.AddLog(cqp.Debug, "robotAnswer-msg", msg)
       resp, _ := http.Get(RobotUrl + msg)
       defer resp.Body.Close()
       body, _ := ioutil.ReadAll(resp.Body)
       cqp.AddLog(cqp.Debug, "robotAnswer-body", string(body))
       var robotMsg RobotMsg
       var jsonIterator = jsoniter.ConfigCompatibleWithStandardLibrary
       if err := jsonIterator.Unmarshal(body, &robotMsg); err == nil {
          cqp.SendGroupMsg(fromGroup, util.CQCode("at", "qq", fromQQ)+util.Escape(robotMsg.Content))
       } else {
          cqp.AddLog(cqp.Debug, "robotAnswer-answer", err.Error())
       }
    }
    

其他消息处理

  1. 普通指令。如菜单、帮助这种单一词汇,只需要简单判断消息内容即可。

    if strings.Contains(msg, "帮助") {
    		code = 1
    		cqp.SendGroupMsg(fromGroup, "帮助菜单:\n"+"巴拉巴拉~")
    	}
    
  2. 组合指令。先判断前缀,然后截取后面的内容。

    //一个搜题功能,不知接口是否还能正常工作
    if strings.HasPrefix(msg, "搜题 ") && len(strings.Split(msg, " ")) > 1 {
    	split := strings.Split(msg, " ")
    	cqp.AddLog(cqp.Debug, "搜题", split[1])
    	resp, _ := http.Post("https://ninja.yua.im/ninja/qa",
    		"application/x-www-form-urlencoded",
    		strings.NewReader("search="+split[1]))
    	defer resp.Body.Close()
    	body, _ := ioutil.ReadAll(resp.Body)
    	response := string(body)
    	msg := "搜题出错,请稍后再试~"
    
    	var exam Exam
    	if err := json.Unmarshal([]byte(response), &exam); err == nil {
    		if exam.IsSuc && exam.Data.Total > 0 {
    			all := make([]string, exam.Data.Total+1)
    			all[0] = "小改改为你找到以下结果:"
    			for index, v := range exam.Data.Rows {
    				title := strconv.Itoa(index+1) + ". " + v.Title
    				s1 := make([]string, len(v.Answers)+1)
    				s1[0] = title
    				for k, v := range v.Answers {
    					if v.IsCorrect {
    						//正确
    						s1[k+1] = v.Content + " √"
    					} else {
    						s1[k+1] = v.Content
    					}
    				}
    				//一条题目及回答
    				all[index+1] = strings.Join(s1, "\n")
    			}
    			msg = strings.TrimSpace(strings.Join(all, "\n"))
    		} else {
    			msg = "没有找到你要的题目哦~"
    		}
    	}
    	cqp.SendGroupMsg(fromGroup, msg)
    }
    

定时功能

这个比较简单,具体用法可参战相关文档。

//定时任务
func initJob() {
	//早晨播报
	err = c.AddFunc("5 0 7 * * ?", func() {
		cqp.SendGroupMsg(816440954, "早上好,今天也是充满希望的一天(●'◡'●)ノ")
	})
	//晚上播报
	err = c.AddFunc("5 0 23 * * ?", func() {
		cqp.SendGroupMsg(816440954, "【碎觉碎觉】")
	})

	if err != nil {
		cqp.AddLog(cqp.Debug, "job", err.Error())
		return
	}
	c.Start()
}

测试截图

群聊截图。图床失效了,脑补一下吧。

Demo获取

点我