mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
183 lines
4.9 KiB
Go
183 lines
4.9 KiB
Go
package controllers
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"fotbal-club/internal/models"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// SitemapController handles sitemap generation
|
|
type SitemapController struct {
|
|
DB *gorm.DB
|
|
}
|
|
|
|
// URLSet represents the root sitemap element
|
|
type URLSet struct {
|
|
XMLName xml.Name `xml:"urlset"`
|
|
XMLNS string `xml:"xmlns,attr"`
|
|
URLs []URL `xml:"url"`
|
|
}
|
|
|
|
// URL represents a single URL entry in sitemap
|
|
type URL struct {
|
|
Loc string `xml:"loc"`
|
|
LastMod string `xml:"lastmod,omitempty"`
|
|
ChangeFreq string `xml:"changefreq,omitempty"`
|
|
Priority float32 `xml:"priority,omitempty"`
|
|
}
|
|
|
|
// GetSitemap generates and returns sitemap.xml
|
|
func (sc *SitemapController) GetSitemap(c *gin.Context) {
|
|
// Get base URL from request or settings
|
|
scheme := "https"
|
|
if c.Request.TLS == nil && c.Request.Header.Get("X-Forwarded-Proto") != "https" {
|
|
scheme = "http"
|
|
}
|
|
baseURL := fmt.Sprintf("%s://%s", scheme, c.Request.Host)
|
|
|
|
// Initialize sitemap
|
|
sitemap := URLSet{
|
|
XMLNS: "http://www.sitemaps.org/schemas/sitemap/0.9",
|
|
URLs: []URL{},
|
|
}
|
|
|
|
// Add homepage
|
|
sitemap.URLs = append(sitemap.URLs, URL{
|
|
Loc: baseURL + "/",
|
|
ChangeFreq: "daily",
|
|
Priority: 1.0,
|
|
})
|
|
|
|
// Add static pages
|
|
staticPages := []struct {
|
|
path string
|
|
freq string
|
|
priority float32
|
|
}{
|
|
{"/blog", "daily", 0.9},
|
|
{"/zapasy", "daily", 0.9},
|
|
{"/tabulky", "weekly", 0.8},
|
|
{"/hraci", "weekly", 0.8},
|
|
{"/o-klubu", "monthly", 0.7},
|
|
{"/kontakt", "monthly", 0.6},
|
|
{"/galerie", "weekly", 0.7},
|
|
{"/videa", "weekly", 0.7},
|
|
{"/sponzori", "monthly", 0.5},
|
|
{"/kalendar", "weekly", 0.7},
|
|
{"/aktivity", "weekly", 0.7},
|
|
{"/obleceni", "monthly", 0.6},
|
|
{"/ankety", "weekly", 0.6},
|
|
}
|
|
|
|
for _, page := range staticPages {
|
|
sitemap.URLs = append(sitemap.URLs, URL{
|
|
Loc: baseURL + page.path,
|
|
ChangeFreq: page.freq,
|
|
Priority: page.priority,
|
|
})
|
|
}
|
|
|
|
// Add published articles
|
|
var articles []models.Article
|
|
if err := sc.DB.Where("published = ?", true).
|
|
Order("published_at DESC, created_at DESC").
|
|
Limit(1000). // Reasonable limit
|
|
Find(&articles).Error; err == nil {
|
|
for _, article := range articles {
|
|
lastMod := article.UpdatedAt.Format("2006-01-02")
|
|
if !article.PublishedAt.IsZero() {
|
|
lastMod = article.PublishedAt.Format("2006-01-02")
|
|
}
|
|
|
|
// Add both slug and ID URLs
|
|
if article.Slug != "" {
|
|
sitemap.URLs = append(sitemap.URLs, URL{
|
|
Loc: baseURL + "/articles/slug/" + article.Slug,
|
|
LastMod: lastMod,
|
|
ChangeFreq: "weekly",
|
|
Priority: 0.8,
|
|
})
|
|
}
|
|
sitemap.URLs = append(sitemap.URLs, URL{
|
|
Loc: baseURL + fmt.Sprintf("/articles/%d", article.ID),
|
|
LastMod: lastMod,
|
|
ChangeFreq: "weekly",
|
|
Priority: 0.7,
|
|
})
|
|
}
|
|
}
|
|
|
|
// Add players
|
|
var players []models.Player
|
|
if err := sc.DB.Order("created_at DESC").Limit(500).Find(&players).Error; err == nil {
|
|
for _, player := range players {
|
|
sitemap.URLs = append(sitemap.URLs, URL{
|
|
Loc: baseURL + fmt.Sprintf("/hraci/%d", player.ID),
|
|
LastMod: player.UpdatedAt.Format("2006-01-02"),
|
|
ChangeFreq: "monthly",
|
|
Priority: 0.6,
|
|
})
|
|
}
|
|
}
|
|
|
|
// Generate XML
|
|
output, err := xml.MarshalIndent(sitemap, "", " ")
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate sitemap"})
|
|
return
|
|
}
|
|
|
|
// Set headers and return
|
|
c.Header("Content-Type", "application/xml; charset=utf-8")
|
|
c.Header("Cache-Control", "public, max-age=3600") // Cache for 1 hour
|
|
c.String(http.StatusOK, xml.Header+string(output))
|
|
}
|
|
|
|
// GetRobotsTxt returns robots.txt with sitemap reference
|
|
func (sc *SitemapController) GetRobotsTxt(c *gin.Context) {
|
|
scheme := "https"
|
|
if c.Request.TLS == nil && c.Request.Header.Get("X-Forwarded-Proto") != "https" {
|
|
scheme = "http"
|
|
}
|
|
baseURL := fmt.Sprintf("%s://%s", scheme, c.Request.Host)
|
|
|
|
// Check if indexing is disabled in settings
|
|
var settings models.Settings
|
|
allowIndex := true
|
|
if err := sc.DB.First(&settings).Error; err == nil {
|
|
allowIndex = settings.EnableIndexing
|
|
}
|
|
|
|
var robots strings.Builder
|
|
robots.WriteString("# robots.txt for " + c.Request.Host + "\n")
|
|
robots.WriteString("# Generated: " + time.Now().Format(time.RFC1123) + "\n\n")
|
|
|
|
if !allowIndex {
|
|
// Block all robots if indexing disabled
|
|
robots.WriteString("User-agent: *\n")
|
|
robots.WriteString("Disallow: /\n")
|
|
} else {
|
|
// Allow most content, block admin and API
|
|
robots.WriteString("User-agent: *\n")
|
|
robots.WriteString("Disallow: /admin/\n")
|
|
robots.WriteString("Disallow: /api/\n")
|
|
robots.WriteString("Disallow: /login\n")
|
|
robots.WriteString("Disallow: /setup\n")
|
|
robots.WriteString("Allow: /\n\n")
|
|
|
|
// Add sitemap reference
|
|
robots.WriteString("Sitemap: " + baseURL + "/sitemap.xml\n")
|
|
}
|
|
|
|
c.Header("Content-Type", "text/plain; charset=utf-8")
|
|
c.Header("Cache-Control", "public, max-age=86400") // Cache for 24 hours
|
|
c.String(http.StatusOK, robots.String())
|
|
}
|