Files
2026-10-26 16:28:14 +08:00

135 lines
3.1 KiB
Go

package dhsitemap
import (
"context"
"encoding/xml"
"fmt"
"os"
"path/filepath"
"strings"
"sync"
"time"
"videoweb/app/service/configser"
"videoweb/pub/common/log"
"videoweb/pub/common/utils"
)
const (
outputDir = "../h5/templates/page/sitemaps"
filename = "dhsitemap.xml"
// 与主站 sitemap 一致:浏览器用 XSLT 把 loc 渲成可点击链接
stylesheetURLSet = `<?xml-stylesheet type="text/xsl" href="/static/sitemap.xsl"?>` + "\n"
)
var generateMu sync.Mutex
type urlSet struct {
XMLName xml.Name `xml:"urlset"`
Xmlns string `xml:"xmlns,attr"`
URLs []urlEntry `xml:"url"`
}
type urlEntry struct {
Loc string `xml:"loc"`
LastMod string `xml:"lastmod"`
}
// GenerateDHSitemap 生成导航站 sitemap,域名取自系统配置 newUrlAddr。
func GenerateDHSitemap() {
generateMu.Lock()
defer generateMu.Unlock()
ctx := context.Background()
config, serr := configser.GetSystemConfig(ctx)
if serr != nil {
log.Error("GenerateDHSitemap GetSystemConfig", log.Any("err", serr))
return
}
if config == nil {
log.Error("GenerateDHSitemap GetSystemConfig config is nil")
return
}
urls := collectDHURLs(config.NewUrlAddr, config.NewUrlAddr1, config.NewUrlAddr2)
if len(urls) == 0 {
log.Warn("GenerateDHSitemap: no newUrlAddr configured, skip")
return
}
today := time.Now().Format("2006-01-02")
entries := make([]urlEntry, 0, len(urls))
for _, u := range urls {
entries = append(entries, urlEntry{
Loc: u,
LastMod: today,
})
}
doc := urlSet{
Xmlns: "http://www.sitemaps.org/schemas/sitemap/0.9",
URLs: entries,
}
if err := writeFile(doc); err != nil {
log.Error("GenerateDHSitemap write", log.Any("err", err))
return
}
src := filepath.Join(outputDir, filename+".tmp")
dst := filepath.Join(outputDir, filename)
if err := os.Rename(src, dst); err != nil {
log.Error("GenerateDHSitemap rename", log.Any("err", err))
os.Remove(src)
return
}
log.Info("GenerateDHSitemap done", log.Any("urls", len(entries)))
}
func collectDHURLs(addrs ...string) []string {
seen := make(map[string]struct{}, len(addrs))
urls := make([]string, 0, len(addrs))
for _, addr := range addrs {
addr = strings.TrimSpace(addr)
if addr == "" {
continue
}
loc := utils.JoinUrlPath(addr, "/")
if _, ok := seen[loc]; ok {
continue
}
seen[loc] = struct{}{}
urls = append(urls, loc)
}
return urls
}
func writeFile(doc urlSet) error {
if err := os.MkdirAll(outputDir, 0755); err != nil {
return fmt.Errorf("mkdir %s: %w", outputDir, err)
}
path := filepath.Join(outputDir, filename+".tmp")
file, err := os.Create(path)
if err != nil {
return fmt.Errorf("create %s: %w", filename, err)
}
defer file.Close()
if _, err := file.WriteString(xml.Header); err != nil {
return fmt.Errorf("write header: %w", err)
}
if _, err := file.WriteString(stylesheetURLSet); err != nil {
return fmt.Errorf("write stylesheet: %w", err)
}
encoder := xml.NewEncoder(file)
encoder.Indent("", " ")
if err := encoder.Encode(doc); err != nil {
return fmt.Errorf("encode: %w", err)
}
if err := encoder.Flush(); err != nil {
return fmt.Errorf("flush: %w", err)
}
return file.Sync()
}