diff --git a/go/deepseek.go b/go/deepseek.go new file mode 100644 index 0000000..25e809e --- /dev/null +++ b/go/deepseek.go @@ -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 +} diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 0000000..d7bcd1d --- /dev/null +++ b/go/go.mod @@ -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 +) diff --git a/go/image.go b/go/image.go new file mode 100644 index 0000000..6278002 --- /dev/null +++ b/go/image.go @@ -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) +} diff --git a/go/main b/go/main new file mode 100755 index 0000000..c05763b Binary files /dev/null and b/go/main differ diff --git a/go/main.go b/go/main.go new file mode 100644 index 0000000..f242bd6 --- /dev/null +++ b/go/main.go @@ -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) + + } +} diff --git a/go/text.go b/go/text.go new file mode 100644 index 0000000..60cae82 --- /dev/null +++ b/go/text.go @@ -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) +} diff --git a/go/website.go b/go/website.go new file mode 100644 index 0000000..8cc80c4 --- /dev/null +++ b/go/website.go @@ -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 +} diff --git a/web/index.html b/web/index.html index 2c72e17..7112c51 100644 --- a/web/index.html +++ b/web/index.html @@ -22,6 +22,7 @@