From 98ebbce6f13c05d1c23828d9daadca4945c3228e Mon Sep 17 00:00:00 2001 From: wood chen Date: Fri, 20 Sep 2024 12:03:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=A0=B8=E5=BF=83=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E6=96=87=E4=BB=B6,=20link=5Ffilter=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=A7=BB=E5=8A=A8=E5=88=B0=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E5=8C=85=E9=87=8C,=20=E7=AE=80=E6=B4=81=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=99=A8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/functions.go | 37 ++++++++ core/init.go | 18 ---- service/link_filter/link_filter.go | 111 ++++++++++++++++++++++ service/message_handler.go | 134 +-------------------------- service/prompt_reply/prompt_reply.go | 6 +- 5 files changed, 155 insertions(+), 151 deletions(-) create mode 100644 core/functions.go diff --git a/core/functions.go b/core/functions.go new file mode 100644 index 0000000..69a7554 --- /dev/null +++ b/core/functions.go @@ -0,0 +1,37 @@ +package core + +//核心函数 +import ( + "fmt" + "log" + "strconv" + "time" + + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" +) + +func IsAdmin(userID int64) bool { + return userID == ADMIN_ID +} +func mustParseInt64(s string) (int64, error) { + if s == "" { + return 0, fmt.Errorf("空字符串") + } + + value, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return 0, fmt.Errorf("未能将'%s'解析为 int64: %v", s, err) + } + + return value, nil +} +func DeleteMessageAfterDelay(bot *tgbotapi.BotAPI, chatID int64, messageID int, delay time.Duration) { + go func() { + time.Sleep(delay) + deleteMsg := tgbotapi.NewDeleteMessage(chatID, messageID) + _, err := bot.Request(deleteMsg) + if err != nil { + log.Printf("删除消息失败 (ChatID: %d, MessageID: %d): %v", chatID, messageID, err) + } + }() +} diff --git a/core/init.go b/core/init.go index 6c59e7a..6a37fc1 100644 --- a/core/init.go +++ b/core/init.go @@ -5,7 +5,6 @@ import ( "log" "os" "path/filepath" - "strconv" "strings" "time" @@ -25,24 +24,7 @@ var ( DB *Database ) -func IsAdmin(userID int64) bool { - return userID == ADMIN_ID -} -func mustParseInt64(s string) (int64, error) { - if s == "" { - return 0, fmt.Errorf("空字符串") - } - - value, err := strconv.ParseInt(s, 10, 64) - if err != nil { - return 0, fmt.Errorf("未能将'%s'解析为 int64: %v", s, err) - } - - return value, nil -} func Init() error { - var err error - // 从环境变量获取 BOT_TOKEN BOT_TOKEN = os.Getenv("BOT_TOKEN") if BOT_TOKEN == "" { diff --git a/service/link_filter/link_filter.go b/service/link_filter/link_filter.go index 11a934f..8330f8c 100644 --- a/service/link_filter/link_filter.go +++ b/service/link_filter/link_filter.go @@ -7,7 +7,9 @@ import ( "regexp" "strings" "sync" + "time" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" "github.com/woodchen-ink/Q58Bot/core" ) @@ -115,3 +117,112 @@ func (lf *LinkFilter) IsWhitelisted(link string) bool { logger.Printf("Whitelist check for %s: Failed", link) return false } + +func addNewKeyword(keyword string) error { + exists, err := core.DB.KeywordExists(keyword) + if err != nil { + return fmt.Errorf("检查关键词时发生错误: %v", err) + } + if !exists { + err = core.DB.AddKeyword(keyword) + if err != nil { + return fmt.Errorf("添加关键词时发生错误: %v", err) + } + logger.Printf("新关键词已添加: %s", keyword) + } + return nil +} +func containsKeyword(text string, linkFilter *LinkFilter) bool { + linkFilter.Mu.RLock() + defer linkFilter.Mu.RUnlock() + + for _, keyword := range linkFilter.Keywords { + if strings.Contains(strings.ToLower(text), strings.ToLower(keyword)) { + logger.Printf("文字包含关键字: %s", keyword) + return true + } + } + return false +} + +func extractLinks(text string, linkFilter *LinkFilter) []string { + linkFilter.Mu.RLock() + defer linkFilter.Mu.RUnlock() + + links := linkFilter.LinkPattern.FindAllString(text, -1) + logger.Printf("找到链接: %v", links) + return links +} +func ShouldFilter(text string, linkFilter *LinkFilter) (bool, []string) { + logger.Printf("Checking text: %s", text) + + if containsKeyword(text, linkFilter) { + return true, nil + } + + links := extractLinks(text, linkFilter) + return processLinks(links, linkFilter) +} +func processLinks(links []string, linkFilter *LinkFilter) (bool, []string) { + var newNonWhitelistedLinks []string + + for _, link := range links { + normalizedLink := linkFilter.NormalizeLink(link) + if !linkFilter.IsWhitelisted(normalizedLink) { + logger.Printf("链接未列入白名单: %s", normalizedLink) + if !containsKeyword(normalizedLink, linkFilter) { + newNonWhitelistedLinks = append(newNonWhitelistedLinks, normalizedLink) + err := addNewKeyword(normalizedLink) + if err != nil { + logger.Printf("添加关键词时发生错误: %v", err) + } + // 如果成功添加了新关键词,更新 linkFilter 的 Keywords + linkFilter.Mu.Lock() + linkFilter.Keywords = append(linkFilter.Keywords, normalizedLink) + linkFilter.Mu.Unlock() + } else { + return true, nil + } + } + } + + if len(newNonWhitelistedLinks) > 0 { + logger.Printf("发现新的非白名单链接: %v", newNonWhitelistedLinks) + } + return false, newNonWhitelistedLinks +} +func (lf *LinkFilter) CheckAndFilterLink(bot *tgbotapi.BotAPI, message *tgbotapi.Message) bool { + // 判断消息是否应当被过滤及找出新的非白名单链接 + shouldFilter, newLinks := ShouldFilter(message.Text, lf) + if shouldFilter { + // 记录被过滤的消息 + logger.Printf("消息应该被过滤: %s", message.Text) + // 删除原始消息 + deleteMsg := tgbotapi.NewDeleteMessage(message.Chat.ID, message.MessageID) + _, err := bot.Request(deleteMsg) + if err != nil { + // 删除消息失败时记录错误 + logger.Printf("删除消息失败: %v", err) + } + + // 发送提示消息 + notification := tgbotapi.NewMessage(message.Chat.ID, "已撤回该消息。注:一个链接不能发两次.") + sent, err := bot.Send(notification) + if err != nil { + // 发送通知失败时记录错误 + logger.Printf("发送通知失败: %v", err) + } else { + // 3分钟后删除提示消息 + core.DeleteMessageAfterDelay(bot, message.Chat.ID, sent.MessageID, 3*time.Minute) + } + return true + } + + // 如果发现新的非白名单链接 + if len(newLinks) > 0 { + // 记录新的非白名单链接 + logger.Printf("发现新的非白名单链接: %v", newLinks) + } + + return false +} diff --git a/service/message_handler.go b/service/message_handler.go index ca92ca6..4c00ab6 100644 --- a/service/message_handler.go +++ b/service/message_handler.go @@ -67,53 +67,14 @@ func processMessage(bot *tgbotapi.BotAPI, message *tgbotapi.Message, linkFilter // 如果不是管理员,才进行链接过滤 if !core.IsAdmin(message.From.ID) { - // 判断消息是否应当被过滤及找出新的非白名单链接 - shouldFilter, newLinks := ShouldFilter(message.Text, linkFilter) - if shouldFilter { - // 记录被过滤的消息 - log.Printf("消息应该被过滤: %s", message.Text) - // 删除原始消息 - deleteMsg := tgbotapi.NewDeleteMessage(message.Chat.ID, message.MessageID) - _, err := bot.Request(deleteMsg) - if err != nil { - // 删除消息失败时记录错误 - log.Printf("删除消息失败: %v", err) - } - - // 发送提示消息 - notification := tgbotapi.NewMessage(message.Chat.ID, "已撤回该消息。注:一个链接不能发两次.") - sent, err := bot.Send(notification) - if err != nil { - // 发送通知失败时记录错误 - log.Printf("发送通知失败: %v", err) - } else { - // 3分钟后删除提示消息 - go deleteMessageAfterDelay(bot, message.Chat.ID, sent.MessageID, 3*time.Minute) - } - // 结束处理 + // 使用新的 CheckAndFilterLink 函数 + if linkFilter.CheckAndFilterLink(bot, message) { return } - // 如果发现新的非白名单链接 - if len(newLinks) > 0 { - // 记录新的非白名单链接 - log.Printf("发现新的非白名单链接: %v", newLinks) - } } - // 检查消息文本是否匹配预设的提示词并回复 - if reply, found := prompt_reply.GetPromptReply(message.Text); found { - // 创建回复消息 - replyMsg := tgbotapi.NewMessage(message.Chat.ID, reply) - replyMsg.ReplyToMessageID = message.MessageID - // sent, err := bot.Send(replyMsg) - // if err != nil { - // 发送回复失败时记录错误 - // log.Printf("未能发送及时回复: %v", err) - // } else { - // // 3分钟后删除回复消息 - // go deleteMessageAfterDelay(bot, message.Chat.ID, sent.MessageID, 3*time.Minute) - // } - } + // 使用现有的 CheckAndReplyPrompt 函数进行提示词回复 + prompt_reply.CheckAndReplyPrompt(bot, message) } func RunMessageHandler() error { @@ -193,17 +154,6 @@ const ( maxMessageLength = 4000 ) -func deleteMessageAfterDelay(bot *tgbotapi.BotAPI, chatID int64, messageID int, delay time.Duration) { - go func() { - time.Sleep(delay) - deleteMsg := tgbotapi.NewDeleteMessage(chatID, messageID) - _, err := bot.Request(deleteMsg) - if err != nil { - log.Printf("删除消息失败 (ChatID: %d, MessageID: %d): %v", chatID, messageID, err) - } - }() -} - func SendLongMessage(bot *tgbotapi.BotAPI, chatID int64, prefix string, items []string) error { message := prefix + "\n" for i, item := range items { @@ -435,80 +385,4 @@ func handleDeleteWhitelist(bot *tgbotapi.BotAPI, message *tgbotapi.Message, doma } } -func addNewKeyword(keyword string) error { - exists, err := core.DB.KeywordExists(keyword) - if err != nil { - return fmt.Errorf("检查关键词时发生错误: %v", err) - } - if !exists { - err = core.DB.AddKeyword(keyword) - if err != nil { - return fmt.Errorf("添加关键词时发生错误: %v", err) - } - logger.Printf("新关键词已添加: %s", keyword) - } - return nil -} - // ShouldFilter 检查消息是否包含关键词或者非白名单链接 -func ShouldFilter(text string, linkFilter *link_filter.LinkFilter) (bool, []string) { - logger.Printf("Checking text: %s", text) - - if containsKeyword(text, linkFilter) { - return true, nil - } - - links := extractLinks(text, linkFilter) - return processLinks(links, linkFilter) -} - -func containsKeyword(text string, linkFilter *link_filter.LinkFilter) bool { - linkFilter.Mu.RLock() - defer linkFilter.Mu.RUnlock() - - for _, keyword := range linkFilter.Keywords { - if strings.Contains(strings.ToLower(text), strings.ToLower(keyword)) { - logger.Printf("文字包含关键字: %s", keyword) - return true - } - } - return false -} - -func extractLinks(text string, linkFilter *link_filter.LinkFilter) []string { - linkFilter.Mu.RLock() - defer linkFilter.Mu.RUnlock() - - links := linkFilter.LinkPattern.FindAllString(text, -1) - logger.Printf("找到链接: %v", links) - return links -} - -func processLinks(links []string, linkFilter *link_filter.LinkFilter) (bool, []string) { - var newNonWhitelistedLinks []string - - for _, link := range links { - normalizedLink := linkFilter.NormalizeLink(link) - if !linkFilter.IsWhitelisted(normalizedLink) { - logger.Printf("链接未列入白名单: %s", normalizedLink) - if !containsKeyword(normalizedLink, linkFilter) { - newNonWhitelistedLinks = append(newNonWhitelistedLinks, normalizedLink) - err := addNewKeyword(normalizedLink) - if err != nil { - logger.Printf("添加关键词时发生错误: %v", err) - } - // 如果成功添加了新关键词,更新 linkFilter 的 Keywords - linkFilter.Mu.Lock() - linkFilter.Keywords = append(linkFilter.Keywords, normalizedLink) - linkFilter.Mu.Unlock() - } else { - return true, nil - } - } - } - - if len(newNonWhitelistedLinks) > 0 { - logger.Printf("发现新的非白名单链接: %v", newNonWhitelistedLinks) - } - return false, newNonWhitelistedLinks -} diff --git a/service/prompt_reply/prompt_reply.go b/service/prompt_reply/prompt_reply.go index dc7ff6d..1b9f517 100644 --- a/service/prompt_reply/prompt_reply.go +++ b/service/prompt_reply/prompt_reply.go @@ -88,12 +88,12 @@ func GetPromptReply(message string) (string, bool) { func ListPromptReplies() string { replies, err := core.DB.GetAllPromptReplies() if err != nil { - log.Printf("Error getting prompt replies: %v", err) - return "Error retrieving prompt replies" + log.Printf("获取及时回复时出错: %v", err) + return "检索提示回复时出错" } if len(replies) == 0 { - return "No prompt replies found" + return "没有找到提示回复" } var result strings.Builder