mirror of
https://github.com/eryajf/chatgpt-dingtalk.git
synced 2025-10-07 00:52:52 +08:00
feat: 增加敏感词功能 (#204)
This commit is contained in:
@@ -229,6 +229,7 @@ $ docker run -itd --name chatgpt -p 8090:8090 \
|
|||||||
-e DEFAULT_MODE="单聊" -e MAX_REQUEST=0 -e PORT=8090 \
|
-e DEFAULT_MODE="单聊" -e MAX_REQUEST=0 -e PORT=8090 \
|
||||||
-e SERVICE_URL="你当前服务外网可访问的URL" -e CHAT_TYPE="0" \
|
-e SERVICE_URL="你当前服务外网可访问的URL" -e CHAT_TYPE="0" \
|
||||||
-e ALLOW_GROUPS=a,b -e ALLOW_OUTGOING_GROUPS=a,b -e ALLOW_USERS=a,b -e DENY_USERS=a,b -e VIP_USERS=a,b -e ADMIN_USERS=a,b -e APP_SECRETS="xxx,yyy" \
|
-e ALLOW_GROUPS=a,b -e ALLOW_OUTGOING_GROUPS=a,b -e ALLOW_USERS=a,b -e DENY_USERS=a,b -e VIP_USERS=a,b -e ADMIN_USERS=a,b -e APP_SECRETS="xxx,yyy" \
|
||||||
|
-e SENSITIVE_WORDS="aa,bb" \
|
||||||
-e AZURE_ON="false" -e AZURE_API_VERSION="" -e AZURE_RESOURCE_NAME="" \
|
-e AZURE_ON="false" -e AZURE_API_VERSION="" -e AZURE_RESOURCE_NAME="" \
|
||||||
-e AZURE_DEPLOYMENT_NAME="" -e AZURE_OPENAI_TOKEN="" \
|
-e AZURE_DEPLOYMENT_NAME="" -e AZURE_OPENAI_TOKEN="" \
|
||||||
-e HELP="欢迎使用本工具\n\n你可以查看:[用户指南](https://github.com/eryajf/chatgpt-dingtalk/blob/main/docs/userGuide.md)\n\n这是一个[开源项目](https://github.com/eryajf/chatgpt-dingtalk/)
|
-e HELP="欢迎使用本工具\n\n你可以查看:[用户指南](https://github.com/eryajf/chatgpt-dingtalk/blob/main/docs/userGuide.md)\n\n这是一个[开源项目](https://github.com/eryajf/chatgpt-dingtalk/)
|
||||||
@@ -493,6 +494,8 @@ vip_users: []
|
|||||||
admin_users: []
|
admin_users: []
|
||||||
# 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果留空,将会忽略校验,则该接口将会存在其他人也能随意调用的安全隐患,因此强烈建议配置正确的secret,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret
|
# 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果留空,将会忽略校验,则该接口将会存在其他人也能随意调用的安全隐患,因此强烈建议配置正确的secret,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret
|
||||||
app_secrets: []
|
app_secrets: []
|
||||||
|
# 敏感词,提问时触发,则不允许提问,回答的内容中触发,则以 *** 代替
|
||||||
|
sensitive_words: []
|
||||||
# 帮助信息,放在配置文件,可供自定义
|
# 帮助信息,放在配置文件,可供自定义
|
||||||
help: "欢迎使用本工具\n\n你可以查看:[用户指南](https://github.com/eryajf/chatgpt-dingtalk/blob/main/docs/userGuide.md)\n\n这是一个[开源项目](https://github.com/eryajf/chatgpt-dingtalk/),觉得不错你可以来波素质三连."
|
help: "欢迎使用本工具\n\n你可以查看:[用户指南](https://github.com/eryajf/chatgpt-dingtalk/blob/main/docs/userGuide.md)\n\n这是一个[开源项目](https://github.com/eryajf/chatgpt-dingtalk/),觉得不错你可以来波素质三连."
|
||||||
|
|
||||||
|
@@ -42,6 +42,8 @@ vip_users: []
|
|||||||
admin_users: []
|
admin_users: []
|
||||||
# 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果留空,将会忽略校验,则该接口将会存在其他人也能随意调用的安全隐患,因此强烈建议配置正确的secret,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret
|
# 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果留空,将会忽略校验,则该接口将会存在其他人也能随意调用的安全隐患,因此强烈建议配置正确的secret,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret
|
||||||
app_secrets: []
|
app_secrets: []
|
||||||
|
# 敏感词,提问时触发,则不允许提问,回答的内容中触发,则以 *** 代替
|
||||||
|
sensitive_words: []
|
||||||
# 帮助信息,放在配置文件,可供自定义
|
# 帮助信息,放在配置文件,可供自定义
|
||||||
help: "欢迎使用本工具\n\n你可以查看:[用户指南](https://github.com/eryajf/chatgpt-dingtalk/blob/main/docs/userGuide.md)\n\n这是一个[开源项目](https://github.com/eryajf/chatgpt-dingtalk/),觉得不错你可以来波素质三连."
|
help: "欢迎使用本工具\n\n你可以查看:[用户指南](https://github.com/eryajf/chatgpt-dingtalk/blob/main/docs/userGuide.md)\n\n这是一个[开源项目](https://github.com/eryajf/chatgpt-dingtalk/),觉得不错你可以来波素质三连."
|
||||||
|
|
||||||
|
@@ -52,6 +52,8 @@ type Configuration struct {
|
|||||||
AdminUsers []string `yaml:"admin_users"`
|
AdminUsers []string `yaml:"admin_users"`
|
||||||
// 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret
|
// 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret
|
||||||
AppSecrets []string `yaml:"app_secrets"`
|
AppSecrets []string `yaml:"app_secrets"`
|
||||||
|
// 敏感词,提问时触发,则不允许提问,回答的内容中触发,则以 *** 代替
|
||||||
|
SensitiveWords []string `yaml:"sensitive_words"`
|
||||||
// 自定义帮助信息
|
// 自定义帮助信息
|
||||||
Help string `yaml:"help"`
|
Help string `yaml:"help"`
|
||||||
// AzureOpenAI 配置
|
// AzureOpenAI 配置
|
||||||
@@ -160,6 +162,10 @@ func LoadConfig() *Configuration {
|
|||||||
if appSecrets != "" {
|
if appSecrets != "" {
|
||||||
config.AppSecrets = strings.Split(appSecrets, ",")
|
config.AppSecrets = strings.Split(appSecrets, ",")
|
||||||
}
|
}
|
||||||
|
sensitiveWords := os.Getenv("SENSITIVE_WORDS")
|
||||||
|
if sensitiveWords != "" {
|
||||||
|
config.SensitiveWords = strings.Split(sensitiveWords, ",")
|
||||||
|
}
|
||||||
help := os.Getenv("HELP")
|
help := os.Getenv("HELP")
|
||||||
if help != "" {
|
if help != "" {
|
||||||
config.Help = help
|
config.Help = help
|
||||||
|
@@ -31,6 +31,7 @@ services:
|
|||||||
ADMIN_USERS: "" # 指定哪些人为此系统的管理员,如果留空,则表示没有人是管理员,如果要限制,则列表中写用户的userid
|
ADMIN_USERS: "" # 指定哪些人为此系统的管理员,如果留空,则表示没有人是管理员,如果要限制,则列表中写用户的userid
|
||||||
# 注意:如果下边的app_secrets为空,以及使用outgoing的方式配置机器人,这两种情况下,都表示没有人是管理员
|
# 注意:如果下边的app_secrets为空,以及使用outgoing的方式配置机器人,这两种情况下,都表示没有人是管理员
|
||||||
APP_SECRETS: "" # 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果留空,将会忽略校验,则该接口将会存在其他人也能随意调用的安全隐患,因此强烈建议配置正确的secret,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret,比如 "xxxx,yyyy"
|
APP_SECRETS: "" # 钉钉机器人在应用信息中的AppSecret,为了校验回调的请求是否合法,如果留空,将会忽略校验,则该接口将会存在其他人也能随意调用的安全隐患,因此强烈建议配置正确的secret,如果你的服务对接给多个机器人,这里可以配置多个机器人的secret,比如 "xxxx,yyyy"
|
||||||
|
SENSITIVE_WORDS: "" # 敏感词,提问时触发,则不允许提问,回答的内容中触发,则以 *** 代替
|
||||||
AZURE_ON: "false" # 是否走Azure OpenAi API, 默认false ,如果为true,则需要配置下边的四个参数
|
AZURE_ON: "false" # 是否走Azure OpenAi API, 默认false ,如果为true,则需要配置下边的四个参数
|
||||||
AZURE_API_VERSION: "" # Azure OpenAi API 版本,比如 "2023-03-15-preview"
|
AZURE_API_VERSION: "" # Azure OpenAi API 版本,比如 "2023-03-15-preview"
|
||||||
AZURE_RESOURCE_NAME: "" # Azure OpenAi API 资源名称,比如 "openai"
|
AZURE_RESOURCE_NAME: "" # Azure OpenAi API 资源名称,比如 "openai"
|
||||||
|
8
main.go
8
main.go
@@ -48,6 +48,14 @@ func Start() {
|
|||||||
}
|
}
|
||||||
// 去除问题的前后空格
|
// 去除问题的前后空格
|
||||||
msgObj.Text.Content = strings.TrimSpace(msgObj.Text.Content)
|
msgObj.Text.Content = strings.TrimSpace(msgObj.Text.Content)
|
||||||
|
if public.JudgeSensitiveWord(msgObj.Text.Content) {
|
||||||
|
_, err = msgObj.ReplyToDingtalk(string(dingbot.MARKDOWN), "**🤷 抱歉,您提问的问题中包含敏感词汇,请审核自己的对话内容之后再进行!**")
|
||||||
|
if err != nil {
|
||||||
|
logger.Warning(fmt.Errorf("send message error: %v", err))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// 打印钉钉回调过来的请求明细,调试时打开
|
// 打印钉钉回调过来的请求明细,调试时打开
|
||||||
logger.Debug(fmt.Sprintf("dingtalk callback parameters: %#v", msgObj))
|
logger.Debug(fmt.Sprintf("dingtalk callback parameters: %#v", msgObj))
|
||||||
|
|
||||||
|
@@ -146,6 +146,9 @@ func Do(mode string, rmsg *dingbot.ReceiveMsg) error {
|
|||||||
logger.Error("往MySQL新增数据失败,错误信息:", err)
|
logger.Error("往MySQL新增数据失败,错误信息:", err)
|
||||||
}
|
}
|
||||||
logger.Info(fmt.Sprintf("🤖 %s得到的答案: %#v", rmsg.SenderNick, reply))
|
logger.Info(fmt.Sprintf("🤖 %s得到的答案: %#v", rmsg.SenderNick, reply))
|
||||||
|
if public.JudgeSensitiveWord(reply) {
|
||||||
|
reply = public.SolveSensitiveWord(reply)
|
||||||
|
}
|
||||||
// 回复@我的用户
|
// 回复@我的用户
|
||||||
_, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), reply)
|
_, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -204,6 +207,9 @@ func Do(mode string, rmsg *dingbot.ReceiveMsg) error {
|
|||||||
// 将当前回答的ID放入缓存
|
// 将当前回答的ID放入缓存
|
||||||
public.UserService.SetAnswerID(rmsg.SenderNick, rmsg.GetChatTitle(), aid)
|
public.UserService.SetAnswerID(rmsg.SenderNick, rmsg.GetChatTitle(), aid)
|
||||||
logger.Info(fmt.Sprintf("🤖 %s得到的答案: %#v", rmsg.SenderNick, reply))
|
logger.Info(fmt.Sprintf("🤖 %s得到的答案: %#v", rmsg.SenderNick, reply))
|
||||||
|
if public.JudgeSensitiveWord(reply) {
|
||||||
|
reply = public.SolveSensitiveWord(reply)
|
||||||
|
}
|
||||||
// 回复@我的用户
|
// 回复@我的用户
|
||||||
_, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), reply)
|
_, err = rmsg.ReplyToDingtalk(string(dingbot.TEXT), reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -9,6 +9,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 将内容写入到文件,如果文件名带路径,则会判断路径是否存在,不存在则创建
|
// 将内容写入到文件,如果文件名带路径,则会判断路径是否存在,不存在则创建
|
||||||
@@ -140,3 +141,35 @@ func CheckRequest(ts, sg string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JudgeSensitiveWord 判断内容是否包含敏感词
|
||||||
|
func JudgeSensitiveWord(s string) bool {
|
||||||
|
if len(Config.SensitiveWords) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, v := range Config.SensitiveWords {
|
||||||
|
if strings.Contains(s, v) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SolveSensitiveWord 将敏感词用*号占位
|
||||||
|
func SolveSensitiveWord(s string) string {
|
||||||
|
for _, v := range Config.SensitiveWords {
|
||||||
|
if strings.Contains(s, v) {
|
||||||
|
return strings.Replace(s, v, printStars(utf8.RuneCountInString(v)), -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将对应敏感词替换为*
|
||||||
|
func printStars(num int) string {
|
||||||
|
s := ""
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
s += "*"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user