Browse Source

removed dead and redundant code

implemented sitemap and expanded healthcheck
master
Silberengel 4 weeks ago
parent
commit
4fe07e636a
  1. 2
      cmd/server/main.go
  2. 9
      internal/generator/html.go
  3. 70
      internal/generator/seo.go
  4. 27
      internal/nostr/client.go
  5. 61
      internal/server/handlers.go
  6. 20
      internal/server/server.go

2
cmd/server/main.go

@ -124,7 +124,7 @@ func main() {
rewarmer.Start(ctx) rewarmer.Start(ctx)
// Initialize HTTP server // Initialize HTTP server
httpServer := server.NewServer(cfg.Server.Port, pageCache, feedCache, mediaCache, issueService, cfg.RepoAnnouncement, htmlGenerator, nostrClient) httpServer := server.NewServer(cfg.Server.Port, pageCache, feedCache, mediaCache, issueService, cfg.RepoAnnouncement, htmlGenerator, nostrClient, cfg.SEO.SiteURL)
// Start server in goroutine // Start server in goroutine
go func() { go func() {

9
internal/generator/html.go

@ -179,15 +179,6 @@ type EBookInfo struct {
TimeISO string // ISO time TimeISO string // ISO time
} }
// UserBadgeInfo represents user badge data for display
type UserBadgeInfo struct {
Pubkey string
Picture string
DisplayName string
Name string
ShortNpub string
}
// NewHTMLGenerator creates a new HTML generator // NewHTMLGenerator creates a new HTML generator
func NewHTMLGenerator(templateDir string, linkBaseURL, siteName, siteURL, defaultImage string, nostrClient *nostr.Client) (*HTMLGenerator, error) { func NewHTMLGenerator(templateDir string, linkBaseURL, siteName, siteURL, defaultImage string, nostrClient *nostr.Client) (*HTMLGenerator, error) {
tmpl := template.New("base").Funcs(getTemplateFuncs()) tmpl := template.New("base").Funcs(getTemplateFuncs())

70
internal/generator/seo.go

@ -1,70 +0,0 @@
package generator
import (
"encoding/json"
)
// GenerateStructuredData generates JSON-LD structured data
func GenerateStructuredData(siteName, siteURL, pageType, title, description, url string) string {
var data map[string]interface{}
switch pageType {
case "article":
data = map[string]interface{}{
"@context": "https://schema.org",
"@type": "Article",
"headline": title,
"description": description,
"url": url,
"publisher": map[string]interface{}{
"@type": "Organization",
"name": siteName,
},
}
case "website":
data = map[string]interface{}{
"@context": "https://schema.org",
"@type": "WebSite",
"name": siteName,
"url": siteURL,
}
default:
data = map[string]interface{}{
"@context": "https://schema.org",
"@type": "WebPage",
"name": title,
"url": url,
}
}
jsonData, _ := json.Marshal(data)
return string(jsonData)
}
// GenerateBreadcrumbStructuredData generates breadcrumb structured data
func GenerateBreadcrumbStructuredData(items []BreadcrumbItem, siteURL string) string {
breadcrumbList := make([]map[string]interface{}, len(items))
for i, item := range items {
breadcrumbList[i] = map[string]interface{}{
"@type": "ListItem",
"position": i + 1,
"name": item.Name,
"item": siteURL + item.URL,
}
}
data := map[string]interface{}{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": breadcrumbList,
}
jsonData, _ := json.Marshal(data)
return string(jsonData)
}
// BreadcrumbItem represents a breadcrumb item
type BreadcrumbItem struct {
Name string
URL string
}

27
internal/nostr/client.go

@ -3,7 +3,6 @@ package nostr
import ( import (
"context" "context"
"fmt" "fmt"
"sync"
"time" "time"
"gitcitadel-online/internal/logger" "gitcitadel-online/internal/logger"
@ -15,11 +14,9 @@ import (
type Client struct { type Client struct {
pool *nostr.SimplePool pool *nostr.SimplePool
relays []string relays []string
feedsRelay string // Relay for feeds feedsRelay string // Relay for feeds
profileRelays []string // Relays for profiles profileRelays []string // Relays for profiles
contactRelays []string // Relays for contact form contactRelays []string // Relays for contact form
mu sync.RWMutex
ctx context.Context
requestSem chan struct{} // Semaphore to limit concurrent requests requestSem chan struct{} // Semaphore to limit concurrent requests
maxConcurrent int // Maximum concurrent requests maxConcurrent int // Maximum concurrent requests
} }
@ -45,7 +42,6 @@ func NewClient(feedsRelay string, profileRelays []string, contactRelays []string
feedsRelay: feedsRelay, feedsRelay: feedsRelay,
profileRelays: profileRelays, profileRelays: profileRelays,
contactRelays: contactRelays, contactRelays: contactRelays,
ctx: ctx,
requestSem: make(chan struct{}, maxConcurrent), requestSem: make(chan struct{}, maxConcurrent),
maxConcurrent: maxConcurrent, maxConcurrent: maxConcurrent,
} }
@ -197,23 +193,6 @@ func (c *Client) FetchEventsBatchFromRelays(ctx context.Context, filters []nostr
return events, nil return events, nil
} }
// FetchEventByID fetches an event by its ID
func (c *Client) FetchEventByID(ctx context.Context, eventID string) (*nostr.Event, error) {
filter := nostr.Filter{
IDs: []string{eventID},
}
return c.FetchEvent(ctx, filter)
}
// FetchEventsByKind fetches events of a specific kind
func (c *Client) FetchEventsByKind(ctx context.Context, kind int, limit int) ([]*nostr.Event, error) {
filter := nostr.Filter{
Kinds: []int{kind},
Limit: limit,
}
return c.FetchEvents(ctx, filter)
}
// Close closes all relay connections in the pool // Close closes all relay connections in the pool
func (c *Client) Close() { func (c *Client) Close() {
// SimplePool manages connections, but we can close individual relays if needed // SimplePool manages connections, but we can close individual relays if needed

61
internal/server/handlers.go

@ -408,11 +408,24 @@ func (s *Server) handleMediaCache(w http.ResponseWriter, r *http.Request) {
// handleHealth handles health check requests // handleHealth handles health check requests
func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) { func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
// Check if cache has pages
if s.cache.Size() == 0 { if s.cache.Size() == 0 {
w.WriteHeader(http.StatusServiceUnavailable) w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte("Not ready")) w.Write([]byte("Not ready - cache empty"))
return return
} }
// Check relay connectivity with timeout
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
defer cancel()
if err := s.nostrClient.HealthCheck(ctx, 5*time.Second); err != nil {
logger.WithField("error", err).Warn("Health check: relay connectivity check failed")
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte("Not ready - relay connectivity check failed"))
return
}
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
w.Write([]byte("OK")) w.Write([]byte("OK"))
} }
@ -426,11 +439,51 @@ func (s *Server) handleMetrics(w http.ResponseWriter, r *http.Request) {
// handleSitemap handles sitemap requests // handleSitemap handles sitemap requests
func (s *Server) handleSitemap(w http.ResponseWriter, r *http.Request) { func (s *Server) handleSitemap(w http.ResponseWriter, r *http.Request) {
// TODO: Generate sitemap from cache // Get all cached page paths
w.Header().Set("Content-Type", "application/xml") paths := s.cache.GetAllPaths()
w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?> if len(paths) == 0 {
w.Header().Set("Content-Type", "application/xml")
w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
</urlset>`)) </urlset>`))
return
}
// Convert cached pages to sitemap URLs
sitemapURLs := make([]generator.SitemapURL, 0, len(paths))
for _, path := range paths {
page, exists := s.cache.Get(path)
if !exists {
continue
}
// Determine priority and change frequency based on path
priority := 0.5
changeFreq := "daily"
if path == "/" {
priority = 1.0
changeFreq = "hourly"
} else if path == "/wiki" || path == "/blog" || path == "/articles" || path == "/ebooks" {
priority = 0.8
changeFreq = "daily"
} else if strings.HasPrefix(path, "/wiki/") {
priority = 0.7
changeFreq = "weekly"
}
sitemapURLs = append(sitemapURLs, generator.SitemapURL{
Path: path,
LastMod: page.LastUpdated,
ChangeFreq: changeFreq,
Priority: priority,
})
}
// Generate sitemap XML
sitemapXML := generator.GenerateSitemap(sitemapURLs, s.siteURL)
w.Header().Set("Content-Type", "application/xml")
w.Write([]byte(sitemapXML))
} }
// handleRobots handles robots.txt requests // handleRobots handles robots.txt requests

20
internal/server/server.go

@ -28,6 +28,7 @@ type Server struct {
repoAnnouncement string repoAnnouncement string
htmlGenerator HTMLGeneratorInterface htmlGenerator HTMLGeneratorInterface
nostrClient *nostr.Client nostrClient *nostr.Client
siteURL string
} }
// IssueServiceInterface defines the interface for issue service // IssueServiceInterface defines the interface for issue service
@ -44,7 +45,7 @@ type HTMLGeneratorInterface interface {
} }
// NewServer creates a new HTTP server // NewServer creates a new HTTP server
func NewServer(port int, pageCache *cache.Cache, feedCache *cache.FeedCache, mediaCache *cache.MediaCache, issueService IssueServiceInterface, repoAnnouncement string, htmlGenerator HTMLGeneratorInterface, nostrClient *nostr.Client) *Server { func NewServer(port int, pageCache *cache.Cache, feedCache *cache.FeedCache, mediaCache *cache.MediaCache, issueService IssueServiceInterface, repoAnnouncement string, htmlGenerator HTMLGeneratorInterface, nostrClient *nostr.Client, siteURL string) *Server {
s := &Server{ s := &Server{
cache: pageCache, cache: pageCache,
feedCache: feedCache, feedCache: feedCache,
@ -54,6 +55,7 @@ func NewServer(port int, pageCache *cache.Cache, feedCache *cache.FeedCache, med
repoAnnouncement: repoAnnouncement, repoAnnouncement: repoAnnouncement,
htmlGenerator: htmlGenerator, htmlGenerator: htmlGenerator,
nostrClient: nostrClient, nostrClient: nostrClient,
siteURL: siteURL,
} }
mux := http.NewServeMux() mux := http.NewServeMux()
@ -99,19 +101,3 @@ func (s *Server) WaitForShutdown() {
logger.Info("Server exited") logger.Info("Server exited")
} }
// convertFeedItemsToInfo converts cache.FeedItem to generator.FeedItemInfo
func (s *Server) convertFeedItemsToInfo(items []cache.FeedItem) []generator.FeedItemInfo {
feedItems := make([]generator.FeedItemInfo, 0, len(items))
for _, item := range items {
feedItems = append(feedItems, generator.FeedItemInfo{
EventID: item.EventID,
Author: item.Author,
Content: item.Content,
Time: item.Time.Format("2006-01-02 15:04:05"),
TimeISO: item.Time.Format(time.RFC3339),
Link: item.Link,
})
}
return feedItems
}

Loading…
Cancel
Save