You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

112 lines
3.2 KiB

package server
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
gonostr "github.com/nbd-wtf/go-nostr"
"gitcitadel-online/internal/cache"
"gitcitadel-online/internal/generator"
"gitcitadel-online/internal/nostr"
)
// Server represents the HTTP server
type Server struct {
httpServer *http.Server
cache *cache.Cache
feedCache *cache.FeedCache
port int
issueService IssueServiceInterface
repoAnnouncement string
htmlGenerator HTMLGeneratorInterface
}
// IssueServiceInterface defines the interface for issue service
type IssueServiceInterface interface {
FetchRepoAnnouncement(ctx context.Context, repoNaddr string) (*nostr.RepoAnnouncement, error)
PublishIssue(ctx context.Context, repoAnnouncement *nostr.RepoAnnouncement, req *nostr.IssueRequest, privateKey string) (string, error)
PublishSignedIssue(ctx context.Context, signedEvent *gonostr.Event) (string, error)
}
// HTMLGeneratorInterface defines the interface for HTML generator
type HTMLGeneratorInterface interface {
GenerateContactPage(success bool, errorMsg string, eventID string, formData map[string]string, repoAnnouncement *nostr.RepoAnnouncement, feedItems []generator.FeedItemInfo) (string, error)
GenerateErrorPage(statusCode int, feedItems []generator.FeedItemInfo) (string, error)
}
// NewServer creates a new HTTP server
func NewServer(port int, pageCache *cache.Cache, feedCache *cache.FeedCache, issueService IssueServiceInterface, repoAnnouncement string, htmlGenerator HTMLGeneratorInterface) *Server {
s := &Server{
cache: pageCache,
feedCache: feedCache,
port: port,
issueService: issueService,
repoAnnouncement: repoAnnouncement,
htmlGenerator: htmlGenerator,
}
mux := http.NewServeMux()
// Setup routes
s.setupRoutes(mux)
s.httpServer = &http.Server{
Addr: fmt.Sprintf(":%d", port),
Handler: s.middleware(mux),
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}
return s
}
// Start starts the HTTP server
func (s *Server) Start() error {
log.Printf("Starting server on port %d", s.port)
return s.httpServer.ListenAndServe()
}
// Shutdown gracefully shuts down the server
func (s *Server) Shutdown(ctx context.Context) error {
return s.httpServer.Shutdown(ctx)
}
// WaitForShutdown waits for shutdown signals
func (s *Server) WaitForShutdown() {
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("Shutting down server...")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := s.Shutdown(ctx); err != nil {
log.Fatal("Server forced to shutdown:", err)
}
log.Println("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{
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
}