turash/bugulma/backend/internal/handler/public_transport_handler.go
2025-12-15 10:06:41 +01:00

97 lines
2.7 KiB
Go

package handler
import (
"bugulma/backend/internal/service"
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
)
// PublicTransportHandler handles endpoints for public transport data
type PublicTransportHandler struct {
service *service.PublicTransportService
schedule *service.ScheduleService
}
// NewPublicTransportHandler creates a new handler
func NewPublicTransportHandler(svc *service.PublicTransportService, schedule *service.ScheduleService) *PublicTransportHandler {
return &PublicTransportHandler{service: svc, schedule: schedule}
}
// GetMetadata returns general metadata about the public transport dataset
func (h *PublicTransportHandler) GetMetadata(c *gin.Context) {
c.JSON(http.StatusOK, h.service.GetMetadata())
}
// ListStops returns a list of common stops
func (h *PublicTransportHandler) ListStops(c *gin.Context) {
stops := h.service.ListStops()
c.JSON(http.StatusOK, gin.H{"stops": stops})
}
// GetStop returns a single stop by key
func (h *PublicTransportHandler) GetStop(c *gin.Context) {
id := c.Param("id")
if st, ok := h.service.GetStop(id); ok {
c.JSON(http.StatusOK, st)
return
}
c.JSON(http.StatusNotFound, gin.H{"error": "stop not found"})
}
// SearchStops searches stops by name
func (h *PublicTransportHandler) SearchStops(c *gin.Context) {
q := c.Query("q")
res := h.service.SearchStops(q)
c.JSON(http.StatusOK, gin.H{"results": res})
}
// GetGTFSFile returns a raw GTFS file from the export directory
func (h *PublicTransportHandler) GetGTFSFile(c *gin.Context) {
filename := c.Param("filename")
content, err := h.service.ReadGTFSFile(filename)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
return
}
c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte(content))
}
// GetNextDepartures returns upcoming departures for a stop
func (h *PublicTransportHandler) GetNextDepartures(c *gin.Context) {
if h.schedule == nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "schedule service not available"})
return
}
stopID := c.Param("id")
fromStr := c.DefaultQuery("from", "")
limitStr := c.DefaultQuery("limit", "10")
var from time.Time
var err error
if fromStr == "" {
from = time.Now().UTC()
} else {
from, err = time.Parse(time.RFC3339, fromStr)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid from time, expected RFC3339"})
return
}
}
limit, err := strconv.Atoi(limitStr)
if err != nil || limit <= 0 {
limit = 10
}
deps, err := h.schedule.GetNextDepartures(c.Request.Context(), stopID, from, limit)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"departures": deps})
}