195 lines
4.6 KiB
Go
195 lines
4.6 KiB
Go
package seo
|
|
|
|
import (
|
|
"encoding/json"
|
|
"encoding/xml"
|
|
"fmt"
|
|
"net/http"
|
|
"path"
|
|
"time"
|
|
|
|
"github.com/pocketbase/pocketbase"
|
|
"github.com/pocketbase/pocketbase/core"
|
|
"github.com/pocketbase/pocketbase/tools/router"
|
|
)
|
|
|
|
type MenuRecord struct {
|
|
Active bool `json:"active"`
|
|
CollectionID string `json:"collectionId"`
|
|
CollectionName string `json:"collectionName"`
|
|
Created string `json:"created"`
|
|
ID string `json:"id"`
|
|
IDLang string `json:"id_lang"`
|
|
IDPage string `json:"id_page"`
|
|
IDParent string `json:"id_parent"`
|
|
IsDefault bool `json:"is_default"`
|
|
IsRoot bool `json:"is_root"`
|
|
LinkRewrite string `json:"link_rewrite"`
|
|
LinkTitle string `json:"link_title"`
|
|
MetaDescription string `json:"meta_description"`
|
|
MetaTitle string `json:"meta_title"`
|
|
Name string `json:"name"`
|
|
PageName string `json:"page_name"`
|
|
PositionID int `json:"position_id"`
|
|
Updated string `json:"updated"`
|
|
Url string `json:"url"`
|
|
}
|
|
|
|
type UrlSet struct {
|
|
XMLName xml.Name `xml:"urlset"`
|
|
Xmlns string `xml:"xmlns,attr"`
|
|
Urls []Url `xml:"url"`
|
|
}
|
|
|
|
type Url struct {
|
|
Loc string `xml:"loc"`
|
|
LastMod string `xml:"lastmod,omitempty"`
|
|
ChangeFreq string `xml:"changefreq,omitempty"`
|
|
Priority string `xml:"priority,omitempty"`
|
|
}
|
|
|
|
func ServeFeeds(app *pocketbase.PocketBase, se *core.ServeEvent) *router.Route[*core.RequestEvent] {
|
|
return se.Router.GET("/feeds/{lang}/sitemap.xml", func(e *core.RequestEvent) error {
|
|
|
|
lang := e.Request.PathValue("lang")
|
|
|
|
urls, err := getLocations(app, lang)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
xx := UrlSet{
|
|
Xmlns: "http://www.sitemaps.org/schemas/sitemap/0.9",
|
|
Urls: urls,
|
|
}
|
|
|
|
bytes, err := xml.MarshalIndent(xx, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
e.Response.Header().Add("content-type", "text/xml")
|
|
return e.String(http.StatusOK, xml.Header+string(bytes))
|
|
})
|
|
}
|
|
|
|
func getLocations(app *pocketbase.PocketBase, lang string) ([]Url, error) {
|
|
records, err := app.FindRecordsByFilter("menu_view", fmt.Sprintf("id_lang='%s'&&active=true", lang), "position_id", 200, 0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
baseUrl, err := getBaseUrl(app)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
locations := []Url{}
|
|
lastMod := time.Now().Add(time.Hour * 24 * 7 * -1).Format("2006-01-02")
|
|
|
|
for _, r := range records {
|
|
rec := MenuRecord{}
|
|
x, _ := r.MarshalJSON()
|
|
json.Unmarshal(x, &rec)
|
|
if rec.IsRoot {
|
|
continue
|
|
}
|
|
if len(rec.Url) > 0 {
|
|
continue
|
|
}
|
|
if rec.IsDefault {
|
|
|
|
locations = append(locations, Url{
|
|
Loc: baseUrl + path.Join(lang),
|
|
LastMod: lastMod,
|
|
ChangeFreq: "weekly",
|
|
Priority: "1.0",
|
|
})
|
|
}
|
|
locations = append(locations, Url{
|
|
Loc: baseUrl + path.Join(lang, rec.IDPage, rec.LinkRewrite),
|
|
LastMod: lastMod,
|
|
ChangeFreq: "weekly",
|
|
Priority: "1.0",
|
|
})
|
|
}
|
|
|
|
return locations, nil
|
|
}
|
|
|
|
type BaseUrl struct {
|
|
BaseURL string `json:"baseUrl"`
|
|
}
|
|
|
|
func getBaseUrl(app *pocketbase.PocketBase) (string, error) {
|
|
record, err := app.FindFirstRecordByFilter("settings", "key='baseUrl'", nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
settings := BaseUrl{}
|
|
json.Unmarshal([]byte(record.GetString("value")), &settings)
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return settings.BaseURL, nil
|
|
}
|
|
|
|
type SitemapIndex struct {
|
|
XMLName xml.Name `xml:"sitemapindex"`
|
|
Xmlns string `xml:"xmlns,attr"`
|
|
Sitemaps []Sitemap `xml:"sitemap"`
|
|
}
|
|
|
|
// Sitemap represents each <sitemap> entry
|
|
type Sitemap struct {
|
|
Loc string `xml:"loc"`
|
|
LastMod string `xml:"lastmod"`
|
|
}
|
|
|
|
func ServeFeedsIndex(app *pocketbase.PocketBase, se *core.ServeEvent) *router.Route[*core.RequestEvent] {
|
|
return se.Router.GET("/feeds/index.xml", func(e *core.RequestEvent) error {
|
|
index, err := makeSiteMapIndex(app)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
bytes, err := xml.MarshalIndent(index, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
e.Response.Header().Add("content-type", "text/xml")
|
|
return e.String(http.StatusOK, xml.Header+string(bytes))
|
|
})
|
|
}
|
|
|
|
func makeSiteMapIndex(app *pocketbase.PocketBase) (*SitemapIndex, error) {
|
|
index := &SitemapIndex{
|
|
Xmlns: "http://www.sitemaps.org/schemas/sitemap/0.9",
|
|
}
|
|
|
|
bseUrl, err := getBaseUrl(app)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
langs, err := app.FindRecordsByFilter("lang", "active=true", "", 200, 0)
|
|
if err != nil {
|
|
return index, err
|
|
}
|
|
|
|
lastMod := time.Now().Add(time.Hour * 24 * 7 * -1).Format("2006-01-02")
|
|
|
|
for _, l := range langs {
|
|
index.Sitemaps = append(index.Sitemaps, Sitemap{
|
|
Loc: bseUrl + path.Join("feeds/", l.Id, "sitemap.xml"),
|
|
LastMod: lastMod,
|
|
})
|
|
}
|
|
|
|
return index, nil
|
|
}
|