mirror of
https://github.com/eryajf/chatgpt-dingtalk.git
synced 2025-10-05 00:02:42 +08:00
feat: 优化钉钉机器人的消息发送方式,兼容outgoing模式 (#128)
Co-authored-by: eryajf <eryajf@users.noreply.github.com>
This commit is contained in:
20
README.md
20
README.md
@@ -24,6 +24,8 @@
|
|||||||
- [使用前提](#%E4%BD%BF%E7%94%A8%E5%89%8D%E6%8F%90)
|
- [使用前提](#%E4%BD%BF%E7%94%A8%E5%89%8D%E6%8F%90)
|
||||||
- [使用教程](#%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B)
|
- [使用教程](#%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B)
|
||||||
- [第一步,创建机器人](#%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%88%9B%E5%BB%BA%E6%9C%BA%E5%99%A8%E4%BA%BA)
|
- [第一步,创建机器人](#%E7%AC%AC%E4%B8%80%E6%AD%A5%E5%88%9B%E5%BB%BA%E6%9C%BA%E5%99%A8%E4%BA%BA)
|
||||||
|
- [方案一:outgoing类型机器人](#%E6%96%B9%E6%A1%88%E4%B8%80outgoing%E7%B1%BB%E5%9E%8B%E6%9C%BA%E5%99%A8%E4%BA%BA)
|
||||||
|
- [方案二:企业内部应用](#%E6%96%B9%E6%A1%88%E4%BA%8C%E4%BC%81%E4%B8%9A%E5%86%85%E9%83%A8%E5%BA%94%E7%94%A8)
|
||||||
- [第二步,部署应用](#%E7%AC%AC%E4%BA%8C%E6%AD%A5%E9%83%A8%E7%BD%B2%E5%BA%94%E7%94%A8)
|
- [第二步,部署应用](#%E7%AC%AC%E4%BA%8C%E6%AD%A5%E9%83%A8%E7%BD%B2%E5%BA%94%E7%94%A8)
|
||||||
- [docker部署](#docker%E9%83%A8%E7%BD%B2)
|
- [docker部署](#docker%E9%83%A8%E7%BD%B2)
|
||||||
- [二进制部署](#%E4%BA%8C%E8%BF%9B%E5%88%B6%E9%83%A8%E7%BD%B2)
|
- [二进制部署](#%E4%BA%8C%E8%BF%9B%E5%88%B6%E9%83%A8%E7%BD%B2)
|
||||||
@@ -85,6 +87,24 @@
|
|||||||
|
|
||||||
### 第一步,创建机器人
|
### 第一步,创建机器人
|
||||||
|
|
||||||
|
#### 方案一:outgoing类型机器人
|
||||||
|
|
||||||
|
钉钉群内的机器人有一个outgoing模式,当你创建机器人的时候,可以选择启用这个模式,然后直接配置回调地址,免去在管理后台创建应用的步骤,就可以直接投入使用。
|
||||||
|
|
||||||
|
官方文档:[自定义机器人接入](https://open.dingtalk.com/document/orgapp/custom-robot-access)
|
||||||
|
|
||||||
|
但是这个模式貌似是部分开放的(目前来看貌似是部分人有创建这个类型的白名单),所以如果你在钉钉群聊中添加`自定义机器人`的时候,看到和我一样的信息,则说明无法使用这种方式:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
`📢 注意`
|
||||||
|
|
||||||
|
- 如果你的和我一样,那么就只能放弃这种方案,往下看第二种对接方案。
|
||||||
|
- 如果使用这种方案,那么就不能与机器人私聊对话,只能局限在群聊当中艾特机器人聊天。
|
||||||
|
- 如果使用这种方案,则在群聊当中并不能达到真正的艾特发消息人的效果,因为这种机器人回调过来的关键信息为空。
|
||||||
|
|
||||||
|
#### 方案二:企业内部应用
|
||||||
|
|
||||||
创建步骤参考文档:[企业内部开发机器人](https://open.dingtalk.com/document/robots/enterprise-created-chatbot),或者根据如下步骤进行配置。
|
创建步骤参考文档:[企业内部开发机器人](https://open.dingtalk.com/document/robots/enterprise-created-chatbot),或者根据如下步骤进行配置。
|
||||||
|
|
||||||
1. 创建机器人。
|
1. 创建机器人。
|
||||||
|
3
main.go
3
main.go
@@ -44,12 +44,13 @@ func Start() {
|
|||||||
logger.Warning("从钉钉回调过来的内容为空,根据过往的经验,或许重新创建一下机器人,能解决这个问题")
|
logger.Warning("从钉钉回调过来的内容为空,根据过往的经验,或许重新创建一下机器人,能解决这个问题")
|
||||||
return ship.ErrBadRequest.New(fmt.Errorf("从钉钉回调过来的内容为空,根据过往的经验,或许重新创建一下机器人,能解决这个问题"))
|
return ship.ErrBadRequest.New(fmt.Errorf("从钉钉回调过来的内容为空,根据过往的经验,或许重新创建一下机器人,能解决这个问题"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打印钉钉回调过来的请求明细
|
// 打印钉钉回调过来的请求明细
|
||||||
logger.Info(fmt.Sprintf("dingtalk callback parameters: %#v", msgObj))
|
logger.Info(fmt.Sprintf("dingtalk callback parameters: %#v", msgObj))
|
||||||
// TODO: 校验请求
|
// TODO: 校验请求
|
||||||
if len(msgObj.Text.Content) == 1 || strings.TrimSpace(msgObj.Text.Content) == "帮助" {
|
if len(msgObj.Text.Content) == 1 || strings.TrimSpace(msgObj.Text.Content) == "帮助" {
|
||||||
// 欢迎信息
|
// 欢迎信息
|
||||||
_, err := msgObj.ReplyToDingtalk(string(public.TEXT), Welcome, msgObj.SenderStaffId)
|
_, err := msgObj.ReplyToDingtalk(string(public.MARKDOWN), Welcome)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
return ship.ErrBadRequest.New(fmt.Errorf("send message error: %v", err))
|
return ship.ErrBadRequest.New(fmt.Errorf("send message error: %v", err))
|
||||||
|
@@ -17,20 +17,20 @@ func ProcessRequest(rmsg *public.ReceiveMsg) error {
|
|||||||
switch content {
|
switch content {
|
||||||
case "单聊":
|
case "单聊":
|
||||||
public.UserService.SetUserMode(rmsg.SenderStaffId, content)
|
public.UserService.SetUserMode(rmsg.SenderStaffId, content)
|
||||||
_, err := rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("=====现在进入与👉%s👈单聊的模式 =====", rmsg.SenderNick), rmsg.SenderStaffId)
|
_, err := rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("=====现在进入与👉%s👈单聊的模式 =====", rmsg.SenderNick))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
}
|
}
|
||||||
case "串聊":
|
case "串聊":
|
||||||
public.UserService.SetUserMode(rmsg.SenderStaffId, content)
|
public.UserService.SetUserMode(rmsg.SenderStaffId, content)
|
||||||
_, err := rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("=====现在进入与👉%s👈串聊的模式 =====", rmsg.SenderNick), rmsg.SenderStaffId)
|
_, err := rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("=====现在进入与👉%s👈串聊的模式 =====", rmsg.SenderNick))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
}
|
}
|
||||||
case "重置":
|
case "重置":
|
||||||
public.UserService.ClearUserMode(rmsg.SenderStaffId)
|
public.UserService.ClearUserMode(rmsg.SenderStaffId)
|
||||||
public.UserService.ClearUserSessionContext(rmsg.SenderStaffId)
|
public.UserService.ClearUserSessionContext(rmsg.SenderStaffId)
|
||||||
_, err := rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("=====已重置与👉%s👈的对话模式,可以开始新的对话=====", rmsg.SenderNick), rmsg.SenderStaffId)
|
_, err := rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("=====已重置与👉%s👈的对话模式,可以开始新的对话=====", rmsg.SenderNick))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
}
|
}
|
||||||
@@ -39,12 +39,12 @@ func ProcessRequest(rmsg *public.ReceiveMsg) error {
|
|||||||
for _, v := range *public.Prompt {
|
for _, v := range *public.Prompt {
|
||||||
title = title + v.Title + " | "
|
title = title + v.Title + " | "
|
||||||
}
|
}
|
||||||
_, err := rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("%s 您好,当前程序内置集成了这些prompt:\n====================================\n| %s \n====================================\n你可以选择某个prompt开头,然后进行对话。\n以周报为例,可发送 #周报 我本周用Go写了一个钉钉集成ChatGPT的聊天应用", rmsg.SenderNick, title), rmsg.SenderStaffId)
|
_, err := rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("%s 您好,当前程序内置集成了这些prompt:\n====================================\n| %s \n====================================\n你可以选择某个prompt开头,然后进行对话。\n以周报为例,可发送 #周报 我本周用Go写了一个钉钉集成ChatGPT的聊天应用", rmsg.SenderNick, title))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
}
|
}
|
||||||
case "图片":
|
case "图片":
|
||||||
_, err := rmsg.ReplyToDingtalk(string(public.MARKDOWN), "发送以 **#图片** 开头的内容,将会触发绘画能力,图片生成之后,将会保存在程序根目录下的 **images目录** \n 如果你绘图没有思路,可以在这两个网站寻找灵感。\n - [https://lexica.art/](https://lexica.art/)\n- [https://www.clickprompt.org/zh-CN/](https://www.clickprompt.org/zh-CN/)", rmsg.SenderStaffId)
|
_, err := rmsg.ReplyToDingtalk(string(public.MARKDOWN), "发送以 **#图片** 开头的内容,将会触发绘画能力,图片生成之后,将会保存在程序根目录下的 **images目录** \n 如果你绘图没有思路,可以在这两个网站寻找灵感。\n - [https://lexica.art/](https://lexica.art/)\n- [https://www.clickprompt.org/zh-CN/](https://www.clickprompt.org/zh-CN/)")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ func ProcessRequest(rmsg *public.ReceiveMsg) error {
|
|||||||
cacheMsg = fmt.Sprintf("💵 已用: 💲%v\n💵 剩余: 💲%v\n⏳ 有效时间: 从 %v 到 %v\n", fmt.Sprintf("%.2f", rst.TotalUsed), fmt.Sprintf("%.2f", rst.TotalAvailable), t1.Format("2006-01-02 15:04:05"), t2.Format("2006-01-02 15:04:05"))
|
cacheMsg = fmt.Sprintf("💵 已用: 💲%v\n💵 剩余: 💲%v\n⏳ 有效时间: 从 %v 到 %v\n", fmt.Sprintf("%.2f", rst.TotalUsed), fmt.Sprintf("%.2f", rst.TotalAvailable), t1.Format("2006-01-02 15:04:05"), t2.Format("2006-01-02 15:04:05"))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := rmsg.ReplyToDingtalk(string(public.TEXT), cacheMsg, rmsg.SenderStaffId)
|
_, err := rmsg.ReplyToDingtalk(string(public.TEXT), cacheMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
}
|
}
|
||||||
@@ -87,13 +87,13 @@ func Do(mode string, rmsg *public.ReceiveMsg) error {
|
|||||||
logger.Info(fmt.Errorf("gpt request error: %v", err))
|
logger.Info(fmt.Errorf("gpt request error: %v", err))
|
||||||
if strings.Contains(fmt.Sprintf("%v", err), "maximum text length exceeded") {
|
if strings.Contains(fmt.Sprintf("%v", err), "maximum text length exceeded") {
|
||||||
public.UserService.ClearUserSessionContext(rmsg.SenderStaffId)
|
public.UserService.ClearUserSessionContext(rmsg.SenderStaffId)
|
||||||
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v,看起来是超过最大对话限制了,已自动重置您的对话", err), rmsg.SenderStaffId)
|
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v,看起来是超过最大对话限制了,已自动重置您的对话", err))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v", err), rmsg.SenderStaffId)
|
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v", err))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
return err
|
return err
|
||||||
@@ -107,8 +107,7 @@ func Do(mode string, rmsg *public.ReceiveMsg) error {
|
|||||||
reply = strings.TrimSpace(reply)
|
reply = strings.TrimSpace(reply)
|
||||||
reply = strings.Trim(reply, "\n")
|
reply = strings.Trim(reply, "\n")
|
||||||
// 回复@我的用户
|
// 回复@我的用户
|
||||||
// fmt.Println("单聊结果是:", reply)
|
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), reply)
|
||||||
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), reply, rmsg.SenderStaffId)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
return err
|
return err
|
||||||
@@ -120,13 +119,13 @@ func Do(mode string, rmsg *public.ReceiveMsg) error {
|
|||||||
logger.Info(fmt.Sprintf("gpt request error: %v", err))
|
logger.Info(fmt.Sprintf("gpt request error: %v", err))
|
||||||
if strings.Contains(fmt.Sprintf("%v", err), "maximum text length exceeded") {
|
if strings.Contains(fmt.Sprintf("%v", err), "maximum text length exceeded") {
|
||||||
public.UserService.ClearUserSessionContext(rmsg.SenderStaffId)
|
public.UserService.ClearUserSessionContext(rmsg.SenderStaffId)
|
||||||
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v,看起来是超过最大对话限制了,已自动重置您的对话", err), rmsg.SenderStaffId)
|
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v,看起来是超过最大对话限制了,已自动重置您的对话", err))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v", err), rmsg.SenderStaffId)
|
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v", err))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
return err
|
return err
|
||||||
@@ -140,7 +139,7 @@ func Do(mode string, rmsg *public.ReceiveMsg) error {
|
|||||||
reply = strings.TrimSpace(reply)
|
reply = strings.TrimSpace(reply)
|
||||||
reply = strings.Trim(reply, "\n")
|
reply = strings.Trim(reply, "\n")
|
||||||
// 回复@我的用户
|
// 回复@我的用户
|
||||||
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), reply, rmsg.SenderStaffId)
|
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
return err
|
return err
|
||||||
@@ -157,7 +156,7 @@ func ImageGenerate(rmsg *public.ReceiveMsg) error {
|
|||||||
reply, err := chatgpt.ImageQa(rmsg.Text.Content, rmsg.SenderStaffId)
|
reply, err := chatgpt.ImageQa(rmsg.Text.Content, rmsg.SenderStaffId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Info(fmt.Errorf("gpt request error: %v", err))
|
logger.Info(fmt.Errorf("gpt request error: %v", err))
|
||||||
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v", err), rmsg.SenderStaffId)
|
_, err = rmsg.ReplyToDingtalk(string(public.TEXT), fmt.Sprintf("请求openai失败了,错误信息:%v", err))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
return err
|
return err
|
||||||
@@ -170,7 +169,7 @@ func ImageGenerate(rmsg *public.ReceiveMsg) error {
|
|||||||
reply = strings.TrimSpace(reply)
|
reply = strings.TrimSpace(reply)
|
||||||
reply = strings.Trim(reply, "\n")
|
reply = strings.Trim(reply, "\n")
|
||||||
// 回复@我的用户
|
// 回复@我的用户
|
||||||
_, err = rmsg.ReplyToDingtalk(string(public.MARKDOWN), fmt.Sprintf(">点击图片可旋转或放大。\n", reply), rmsg.SenderStaffId)
|
_, err = rmsg.ReplyToDingtalk(string(public.MARKDOWN), fmt.Sprintf(">点击图片可旋转或放大。\n", reply))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
return err
|
return err
|
||||||
|
@@ -3,6 +3,7 @@ package public
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -68,15 +69,19 @@ type At struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 发消息给钉钉
|
// 发消息给钉钉
|
||||||
func (r ReceiveMsg) ReplyToDingtalk(msgType, msg, staffId string) (statuscode int, err error) {
|
func (r ReceiveMsg) ReplyToDingtalk(msgType, msg string) (statuscode int, err error) {
|
||||||
|
atUser := r.SenderStaffId
|
||||||
|
if atUser == "" {
|
||||||
|
msg = fmt.Sprintf("%s\n\n@%s", msg, r.SenderNick)
|
||||||
|
}
|
||||||
var msgtmp interface{}
|
var msgtmp interface{}
|
||||||
switch msgType {
|
switch msgType {
|
||||||
case string(TEXT):
|
case string(TEXT):
|
||||||
msgtmp = &TextMessage{Text: &Text{Content: msg}, MsgType: TEXT, At: &At{AtUserIds: []string{staffId}}}
|
msgtmp = &TextMessage{Text: &Text{Content: msg}, MsgType: TEXT, At: &At{AtUserIds: []string{atUser}}}
|
||||||
case string(MARKDOWN):
|
case string(MARKDOWN):
|
||||||
msgtmp = &MarkDownMessage{MsgType: MARKDOWN, At: &At{AtUserIds: []string{staffId}}, MarkDown: &MarkDown{Title: "根据您提供的信息,为您生成图片如下", Text: msg}}
|
msgtmp = &MarkDownMessage{MsgType: MARKDOWN, At: &At{AtUserIds: []string{atUser}}, MarkDown: &MarkDown{Title: "Markdown Type", Text: msg}}
|
||||||
default:
|
default:
|
||||||
msgtmp = &TextMessage{Text: &Text{Content: msg}, MsgType: TEXT, At: &At{AtUserIds: []string{staffId}}}
|
msgtmp = &TextMessage{Text: &Text{Content: msg}, MsgType: TEXT, At: &At{AtUserIds: []string{atUser}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := json.Marshal(msgtmp)
|
data, err := json.Marshal(msgtmp)
|
||||||
|
@@ -45,7 +45,7 @@ func CheckRequest(rmsg *ReceiveMsg) bool {
|
|||||||
// 判断访问次数是否超过限制
|
// 判断访问次数是否超过限制
|
||||||
if count >= Config.MaxRequest {
|
if count >= Config.MaxRequest {
|
||||||
logger.Info(fmt.Sprintf("亲爱的: %s,您今日请求次数已达上限,请明天再来,交互发问资源有限,请务必斟酌您的问题,给您带来不便,敬请谅解!", rmsg.SenderNick))
|
logger.Info(fmt.Sprintf("亲爱的: %s,您今日请求次数已达上限,请明天再来,交互发问资源有限,请务必斟酌您的问题,给您带来不便,敬请谅解!", rmsg.SenderNick))
|
||||||
_, err := rmsg.ReplyToDingtalk(string(TEXT), fmt.Sprintf("一个好的问题,胜过十个好的答案!\n亲爱的: %s,您今日请求次数已达上限,请明天再来,交互发问资源有限,请务必斟酌您的问题,给您带来不便,敬请谅解!", rmsg.SenderNick), rmsg.SenderStaffId)
|
_, err := rmsg.ReplyToDingtalk(string(TEXT), fmt.Sprintf("一个好的问题,胜过十个好的答案!\n亲爱的: %s,您今日请求次数已达上限,请明天再来,交互发问资源有限,请务必斟酌您的问题,给您带来不便,敬请谅解!", rmsg.SenderNick))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning(fmt.Errorf("send message error: %v", err))
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user