Files
jiang13-bbs/backend/service/visit_ref.go
freefire 7b327bc8cc feat: 站点访问统计与可配置侧边栏组件
- 新增访问统计:visitstats 服务与查询、visit_capture 中间件、爬虫/来源识别、管理端 analytics 页面
- 新增侧边栏:sidebar 服务与 handler、管理端 sidebar 配置页、前端侧边栏组件
- 新增 widget 嵌入代码生成(widgetCode)与 widgetApi
- 遥测逻辑迁移至 handler 层,删除 service/telemetry
- env 示例补充 Docker 部署可信代理 IP 说明
2026-09-24 18:53:45 +08:00

64 lines
1.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"net/url"
"strings"
)
// 来源分类常量
const (
RefKindDirect = "direct"
RefKindInternal = "internal"
RefKindSearch = "search"
RefKindSocial = "social"
RefKindExternal = "external"
)
// searchHosts 搜索引擎域名(按「等于或以 .子域结尾」匹配)
var searchHosts = []string{"google.com", "bing.com", "baidu.com", "sogou.com", "so.com", "sm.cn", "duckduckgo.com", "yandex.com", "yandex.ru", "yahoo.com"}
// socialHosts 社交/社区域名特征
var socialHosts = []string{
"weibo.com", "weibo.cn", "zhihu.com", "zhuanlan.zhihu.com", "twitter.com", "x.com",
"t.me", "telegram.me", "douyin.com", "xiaohongshu.com", "bilibili.com", "b23.tv",
"qq.com", "tieba.baidu.com", "v2ex.com", "juejin.cn", "csdn.net", "segmentfault.com",
"github.com", "gitee.com", "reddit.com", "facebook.com", "instagram.com", "discord.com",
}
// hostMatches 按「等于或以 .子域结尾」匹配 host 与域名列表
func hostMatches(host string, list []string) bool {
for _, d := range list {
if host == d || strings.HasSuffix(host, "."+d) {
return true
}
}
return false
}
// ClassifyReferrer 解析并归类 Referer:返回 (来源 host, 来源类别)。
// 空 → direct;本站 → internal;搜索引擎 → search;社交 → social;其余 → external;解析失败按 direct。
func ClassifyReferrer(raw, siteHost string) (string, string) {
raw = strings.TrimSpace(raw)
if raw == "" {
return "", RefKindDirect
}
u, err := url.Parse(raw)
if err != nil || u.Host == "" {
return "", RefKindDirect
}
host := strings.ToLower(u.Host)
if i := strings.LastIndex(host, ":"); i >= 0 && !strings.Contains(host, "]") {
host = host[:i] // 去端口
}
if siteHost != "" && (host == siteHost || siteHost == host) {
return host, RefKindInternal
}
if hostMatches(host, searchHosts) {
return host, RefKindSearch
}
if hostMatches(host, socialHosts) {
return host, RefKindSocial
}
return host, RefKindExternal
}