新增AI反诈助理页面和软件设置页面
This commit is contained in:
		
							parent
							
								
									72743e2809
								
							
						
					
					
						commit
						88b117c0c8
					
				
							
								
								
									
										36
									
								
								go/deepseek.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								go/deepseek.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/ssgo/httpclient"
 | 
				
			||||||
 | 
						"github.com/ssgo/log"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Ans struct {
 | 
				
			||||||
 | 
						Choices []struct {
 | 
				
			||||||
 | 
							Message struct {
 | 
				
			||||||
 | 
								Content string
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ask(text string) string {
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("start ask", "text", text)
 | 
				
			||||||
 | 
						ansR := httpclient.GetClient(time.Second*60).Post("https://api.ppinfra.com/v3/openai/chat/completions", map[string]any{
 | 
				
			||||||
 | 
							"model": "deepseek/deepseek-r1/community",
 | 
				
			||||||
 | 
							"messages": []map[string]any{
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									"role":    "user",
 | 
				
			||||||
 | 
									"content": text,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"response_format": map[string]any{"type": "text"},
 | 
				
			||||||
 | 
						}, "Content-Type", "application/json", "Authorization", "Bearer sk_siUuVF2utu9Mg0-LM5aM1KteXNQand33myY2iTq7Pcw")
 | 
				
			||||||
 | 
						if err := ansR.Error; err != nil {
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("ask error", "err", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ans := Ans{}
 | 
				
			||||||
 | 
						ansR.To(&ans)
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("ask stopped", "ans", ans)
 | 
				
			||||||
 | 
						return ans.Choices[0].Message.Content
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								go/go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								go/go.mod
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					module main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go 1.23.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require (
 | 
				
			||||||
 | 
						github.com/PuerkitoBio/goquery v1.10.2
 | 
				
			||||||
 | 
						github.com/gorilla/websocket v1.5.3
 | 
				
			||||||
 | 
						github.com/sashabaranov/go-openai v1.38.0
 | 
				
			||||||
 | 
						github.com/ssgo/httpclient v1.7.8
 | 
				
			||||||
 | 
						github.com/ssgo/log v1.7.7
 | 
				
			||||||
 | 
						github.com/ssgo/s v1.7.22
 | 
				
			||||||
 | 
						github.com/ssgo/u v1.7.13
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require (
 | 
				
			||||||
 | 
						github.com/andybalholm/cascadia v1.3.3 // indirect
 | 
				
			||||||
 | 
						github.com/go-ole/go-ole v1.3.0 // indirect
 | 
				
			||||||
 | 
						github.com/gomodule/redigo v1.9.2 // indirect
 | 
				
			||||||
 | 
						github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
 | 
				
			||||||
 | 
						github.com/otiai10/gosseract/v2 v2.4.1 // indirect
 | 
				
			||||||
 | 
						github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
 | 
				
			||||||
 | 
						github.com/shirou/gopsutil/v3 v3.24.5 // indirect
 | 
				
			||||||
 | 
						github.com/shoenig/go-m1cpu v0.1.6 // indirect
 | 
				
			||||||
 | 
						github.com/ssgo/config v1.7.9 // indirect
 | 
				
			||||||
 | 
						github.com/ssgo/discover v1.7.9 // indirect
 | 
				
			||||||
 | 
						github.com/ssgo/redis v1.7.7 // indirect
 | 
				
			||||||
 | 
						github.com/ssgo/standard v1.7.7 // indirect
 | 
				
			||||||
 | 
						github.com/tklauser/go-sysconf v0.3.14 // indirect
 | 
				
			||||||
 | 
						github.com/tklauser/numcpus v0.9.0 // indirect
 | 
				
			||||||
 | 
						github.com/yusufpapurcu/wmi v1.2.4 // indirect
 | 
				
			||||||
 | 
						golang.org/x/net v0.35.0 // indirect
 | 
				
			||||||
 | 
						golang.org/x/sys v0.30.0 // indirect
 | 
				
			||||||
 | 
						golang.org/x/text v0.22.0 // indirect
 | 
				
			||||||
 | 
						gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										70
									
								
								go/image.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								go/image.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/otiai10/gosseract/v2"
 | 
				
			||||||
 | 
						"github.com/ssgo/log"
 | 
				
			||||||
 | 
						"github.com/ssgo/u"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkImg(imgStr string) error {
 | 
				
			||||||
 | 
						text := ocrImage(u.UnBase64(strings.Split(imgStr, "base64,")[1]))
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("checkImg", "imgStrLen", len(imgStr), "imgLen", len(u.UnBase64(strings.Split(imgStr, "base64,")[1])), "text", text)
 | 
				
			||||||
 | 
						score, err := parseRiskScore(ask(buildImgDetectionPrompt(text)))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("parseImgResp error", "err", err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = conn.WriteJSON(map[string]any{
 | 
				
			||||||
 | 
							"type": "imageResult",
 | 
				
			||||||
 | 
							"result": map[string]any{
 | 
				
			||||||
 | 
								"score":        score,
 | 
				
			||||||
 | 
								"isSuspicious": score >= 50,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("sendImgScore Error", "err", err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("sendImgScore")
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ocrImage(image []byte) string {
 | 
				
			||||||
 | 
						client := gosseract.NewClient()
 | 
				
			||||||
 | 
						defer client.Close()
 | 
				
			||||||
 | 
						err := client.SetImageFromBytes(image)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Println(err)
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("ocr setimg error", "err", err)
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Println(u.Red("111"))
 | 
				
			||||||
 | 
						text, err := client.Text()
 | 
				
			||||||
 | 
						fmt.Println(text)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Println(err)
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("ocr error", "err", err)
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return text
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func buildImgDetectionPrompt(content string) string {
 | 
				
			||||||
 | 
						return fmt.Sprintf(`你是一名反诈骗专家,专门分析聊天记录,判断其中是否涉及诈骗信息。请仔细阅读以下文字,并回答以下问题:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. 这段内容是否包含诈骗信息?如果是,请给出具体的诈骗类型(如刷单、冒充客服、杀猪盘等)。
 | 
				
			||||||
 | 
					2. 请分析这段内容是否具有诈骗话术,例如使用了“限时优惠”“保证赚钱”“不透露给别人”等常见诈骗用语。
 | 
				
			||||||
 | 
					3. 诈骗信息通常会使用哪些伎俩欺骗受害者?请指出可能的欺诈手法。
 | 
				
			||||||
 | 
					4. 请用简洁的语言(不超过100字)总结你的分析结果,并给出风险等级(低、中、高)。
 | 
				
			||||||
 | 
					5. 如果有必要,请建议用户如何避免被骗。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					请返回JSON格式:
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    "risk_score": 0-100,
 | 
				
			||||||
 | 
					    "risk_reason": "主要风险点"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					待分析的文本如下:%s`, content)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								go/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								go/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gorilla/websocket"
 | 
				
			||||||
 | 
						"github.com/ssgo/log"
 | 
				
			||||||
 | 
						"github.com/ssgo/s"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var conn *websocket.Conn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Message struct {
 | 
				
			||||||
 | 
						Type      string
 | 
				
			||||||
 | 
						Url       string
 | 
				
			||||||
 | 
						ImageData string
 | 
				
			||||||
 | 
						Text      string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						s.Config.Listen = "9000"
 | 
				
			||||||
 | 
						s.Static("/", "../web/")
 | 
				
			||||||
 | 
						s.RegisterSimpleWebsocket(0, "/socket", func(connect *websocket.Conn) {
 | 
				
			||||||
 | 
							log.DefaultLogger.Info("Socket connected")
 | 
				
			||||||
 | 
							conn = connect
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								data := &Message{}
 | 
				
			||||||
 | 
								err := conn.ReadJSON(data)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									log.DefaultLogger.Error("Read WS error", "err", err.Error())
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								go onMessage(data)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}, "")
 | 
				
			||||||
 | 
						s.Start()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func onMessage(data *Message) {
 | 
				
			||||||
 | 
						switch data.Type {
 | 
				
			||||||
 | 
						case "checkPhishing":
 | 
				
			||||||
 | 
							checkUrl(data.Url)
 | 
				
			||||||
 | 
						case "checkImage":
 | 
				
			||||||
 | 
							checkImg(data.ImageData)
 | 
				
			||||||
 | 
						case "checkScript":
 | 
				
			||||||
 | 
							checkText(data.Text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								go/text.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								go/text.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/ssgo/log"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkText(text string) error {
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("checkText", "text", text)
 | 
				
			||||||
 | 
						score, err := parseRiskScore(ask(buildTextDetectionPrompt(text)))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("parseTextResp error", "err", err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = conn.WriteJSON(map[string]any{
 | 
				
			||||||
 | 
							"type": "textResult",
 | 
				
			||||||
 | 
							"result": map[string]any{
 | 
				
			||||||
 | 
								"score":        score,
 | 
				
			||||||
 | 
								"isSuspicious": score >= 50,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("sendTextScore Error", "err", err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("sendTextScore")
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func buildTextDetectionPrompt(content string) string {
 | 
				
			||||||
 | 
						return fmt.Sprintf(`你是一名反诈骗专家,专门分析聊天记录,判断其中是否涉及诈骗信息。请仔细阅读以下文字,并回答以下问题:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. 这段内容是否包含诈骗信息?如果是,请给出具体的诈骗类型(如刷单、冒充客服、杀猪盘等)。
 | 
				
			||||||
 | 
					2. 请分析这段内容是否具有诈骗话术,例如使用了“限时优惠”“保证赚钱”“不透露给别人”等常见诈骗用语。
 | 
				
			||||||
 | 
					3. 诈骗信息通常会使用哪些伎俩欺骗受害者?请指出可能的欺诈手法。
 | 
				
			||||||
 | 
					4. 请用简洁的语言(不超过100字)总结你的分析结果,并给出风险等级(低、中、高)。
 | 
				
			||||||
 | 
					5. 如果有必要,请建议用户如何避免被骗。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					请返回JSON格式:
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    "risk_score": 0-100,
 | 
				
			||||||
 | 
					    "risk_reason": "主要风险点"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					待分析的文本如下:%s`, content)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										159
									
								
								go/website.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								go/website.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,159 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/PuerkitoBio/goquery"
 | 
				
			||||||
 | 
						"github.com/ssgo/log"
 | 
				
			||||||
 | 
						"github.com/ssgo/u"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkUrl(url string) error {
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("UrlTest", "url", url)
 | 
				
			||||||
 | 
						score := analyzeHandler(url)
 | 
				
			||||||
 | 
						if score == -1 || score == -2 {
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("ckwebsiteErr")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("ckwebsite2", "score", score)
 | 
				
			||||||
 | 
						err := conn.WriteJSON(map[string]any{
 | 
				
			||||||
 | 
							"type":   "urlResult",
 | 
				
			||||||
 | 
							"result": score,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("sendURLScore Error", "err", err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("sendURLScore")
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						MaxContentLength = 8000 // 根据模型上下文窗口限制
 | 
				
			||||||
 | 
						RequestTimeout   = 15 * time.Second
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DeepseekConfig struct {
 | 
				
			||||||
 | 
						Model       string
 | 
				
			||||||
 | 
						Temperature float32
 | 
				
			||||||
 | 
						MaxTokens   int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						aiConfig = DeepseekConfig{
 | 
				
			||||||
 | 
							Model:       "deepseek/deepseek-r1/community", // 根据API权限选择
 | 
				
			||||||
 | 
							Temperature: 0.7,
 | 
				
			||||||
 | 
							MaxTokens:   500,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HTTP处理函数
 | 
				
			||||||
 | 
					func analyzeHandler(targetURL string) int {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 安全爬取网页内容
 | 
				
			||||||
 | 
						content, err := safeCrawl(targetURL)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return -2
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 调用OpenAI分析
 | 
				
			||||||
 | 
						score, err := analyzeContent(content)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return -1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("ckwebsite1", "score", score)
 | 
				
			||||||
 | 
						return score
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func safeCrawl(targetURL string) (string, error) {
 | 
				
			||||||
 | 
						client := &http.Client{
 | 
				
			||||||
 | 
							Timeout: RequestTimeout,
 | 
				
			||||||
 | 
							CheckRedirect: func(req *http.Request, via []*http.Request) error {
 | 
				
			||||||
 | 
								if len(via) >= 5 {
 | 
				
			||||||
 | 
									return fmt.Errorf("too many redirects (max 5)")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Println(u.Red(111))
 | 
				
			||||||
 | 
						resp, err := client.Get(targetURL)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("222Err")
 | 
				
			||||||
 | 
							fmt.Println(err)
 | 
				
			||||||
 | 
							return "", fmt.Errorf("HTTP request failed: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer resp.Body.Close()
 | 
				
			||||||
 | 
						fmt.Println(u.Red(222))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if resp.StatusCode < 200 || resp.StatusCode >= 400 {
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("223Err")
 | 
				
			||||||
 | 
							fmt.Println(err)
 | 
				
			||||||
 | 
							return "", fmt.Errorf("invalid status code: %d", resp.StatusCode)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						doc, err := goquery.NewDocumentFromReader(resp.Body)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.DefaultLogger.Error("224Err")
 | 
				
			||||||
 | 
							fmt.Println(err)
 | 
				
			||||||
 | 
							return "", fmt.Errorf("HTML parsing failed: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						doc.Find("script, style, noscript").Remove()
 | 
				
			||||||
 | 
						text := doc.Find("body").Text()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 预处理内容
 | 
				
			||||||
 | 
						cleanText := strings.Join(strings.Fields(text), " ")
 | 
				
			||||||
 | 
						if len(cleanText) > MaxContentLength {
 | 
				
			||||||
 | 
							cleanText = cleanText[:MaxContentLength]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log.DefaultLogger.Info("getwebsite", "cleanText", cleanText)
 | 
				
			||||||
 | 
						return cleanText, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AI分析处理
 | 
				
			||||||
 | 
					func analyzeContent(content string) (int, error) {
 | 
				
			||||||
 | 
						return parseRiskScore(ask(buildDetectionPrompt(content)))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 构造模板prompt
 | 
				
			||||||
 | 
					func buildDetectionPrompt(content string) string {
 | 
				
			||||||
 | 
						return fmt.Sprintf(`作为网络安全分析系统,请对以下网页内容进行风险评估。评估标准包括:
 | 
				
			||||||
 | 
					1. 紧急金融操作请求(转账、验证账户等)
 | 
				
			||||||
 | 
					2. 仿冒品牌或误导性信息
 | 
				
			||||||
 | 
					3. 可疑链接/下载请求
 | 
				
			||||||
 | 
					4. 语法及排版异常
 | 
				
			||||||
 | 
					5. 非法个人信息收集
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					请返回JSON格式:
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    "risk_score": 0-100,
 | 
				
			||||||
 | 
					    "risk_reason": "主要风险点"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					网页内容:%s`, content)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func parseRiskScore(response string) (int, error) {
 | 
				
			||||||
 | 
						var result struct {
 | 
				
			||||||
 | 
							RiskScore int `json:"risk_score"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						start := strings.Index(response, "{")
 | 
				
			||||||
 | 
						end := strings.LastIndex(response, "}")
 | 
				
			||||||
 | 
						if start == -1 || end <= start {
 | 
				
			||||||
 | 
							return 0, fmt.Errorf("invalid response format")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := json.Unmarshal([]byte(response[start:end+1]), &result)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return 0, fmt.Errorf("failed to parse JSON: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if result.RiskScore < 0 || result.RiskScore > 100 {
 | 
				
			||||||
 | 
							return 0, fmt.Errorf("invalid risk score range")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result.RiskScore, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -22,6 +22,7 @@
 | 
				
			|||||||
        <div class="section">
 | 
					        <div class="section">
 | 
				
			||||||
            <h2>聊天图片检测</h2>
 | 
					            <h2>聊天图片检测</h2>
 | 
				
			||||||
            <input type="file" id="imageInput">
 | 
					            <input type="file" id="imageInput">
 | 
				
			||||||
 | 
					            <hr style="visibility: hidden">
 | 
				
			||||||
            <button onclick="checkChatImage()">检测图片</button>
 | 
					            <button onclick="checkChatImage()">检测图片</button>
 | 
				
			||||||
            <div id="imageResult" class="result"></div>
 | 
					            <div id="imageResult" class="result"></div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								web/main.js
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								web/main.js
									
									
									
									
									
								
							@ -1,5 +1,5 @@
 | 
				
			|||||||
// 创建 WebSocket 连接
 | 
					// 创建 WebSocket 连接
 | 
				
			||||||
const socket = new WebSocket('ws://localhost:8080'); // 后端WebSocket服务器的地址
 | 
					const socket = new WebSocket('ws://localhost:9000/socket'); // 后端WebSocket服务器的地址
 | 
				
			||||||
 | 
					
 | 
				
			||||||
socket.onopen = () => {
 | 
					socket.onopen = () => {
 | 
				
			||||||
    console.log('WebSocket 连接已建立');
 | 
					    console.log('WebSocket 连接已建立');
 | 
				
			||||||
@ -40,8 +40,12 @@ function checkChatImage() {
 | 
				
			|||||||
    if (imageInput.files.length > 0) {
 | 
					    if (imageInput.files.length > 0) {
 | 
				
			||||||
        const file = imageInput.files[0];
 | 
					        const file = imageInput.files[0];
 | 
				
			||||||
        const reader = new FileReader();
 | 
					        const reader = new FileReader();
 | 
				
			||||||
        reader.onload = function(e) {
 | 
					        reader.readAsDataURL(file);
 | 
				
			||||||
            socket.send(JSON.stringify({ type: 'checkImage', imageData: e.target.result }));
 | 
					        reader.onload = (e) => {
 | 
				
			||||||
 | 
					            console.info(reader.result)
 | 
				
			||||||
 | 
					            console.info(reader.result.length)
 | 
				
			||||||
 | 
					            console.info(e.target.result.length)
 | 
				
			||||||
 | 
					            socket.send(JSON.stringify({ type: 'checkImage', imageData: reader.result }));
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        reader.readAsDataURL(file);
 | 
					        reader.readAsDataURL(file);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -74,7 +78,7 @@ function displayUrlResult(result) {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (result.isPhishing) {
 | 
					    if (result>=50) {
 | 
				
			||||||
        resultDiv.textContent = translations[language].warning;
 | 
					        resultDiv.textContent = translations[language].warning;
 | 
				
			||||||
        resultDiv.classList.remove('success');
 | 
					        resultDiv.classList.remove('success');
 | 
				
			||||||
        resultDiv.classList.add('error');
 | 
					        resultDiv.classList.add('error');
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user