forked from StrafesNET/maps-service
Closes #229 This is a MVP and only includes maps. Reviewed-on: StrafesNET/maps-service#253 Reviewed-by: itzaname <itzaname@noreply@itzana.me> Co-authored-by: Rhys Lloyd <krakow20@gmail.com> Co-committed-by: Rhys Lloyd <krakow20@gmail.com>
154 lines
3.9 KiB
Go
154 lines
3.9 KiB
Go
package handlers
|
|
|
|
import (
|
|
"git.itzana.me/strafesnet/go-grpc/maps_extended"
|
|
"git.itzana.me/strafesnet/maps-service/pkg/public_api/dto"
|
|
"github.com/gin-gonic/gin"
|
|
log "github.com/sirupsen/logrus"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
"net/http"
|
|
"strconv"
|
|
)
|
|
|
|
// MapHandler handles HTTP requests related to maps.
|
|
type MapHandler struct {
|
|
*Handler
|
|
}
|
|
|
|
// NewMapHandler creates a new MapHandler with the provided options.
|
|
func NewMapHandler(options ...HandlerOption) (*MapHandler, error) {
|
|
baseHandler, err := NewHandler(options...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &MapHandler{
|
|
Handler: baseHandler,
|
|
}, nil
|
|
}
|
|
|
|
// @Summary Get map by ID
|
|
// @Description Get a specific map by its ID
|
|
// @Tags maps
|
|
// @Produce json
|
|
// @Security ApiKeyAuth
|
|
// @Param id path int true "Map ID"
|
|
// @Success 200 {object} dto.Response[dto.Map]
|
|
// @Failure 404 {object} dto.Error "Map not found"
|
|
// @Failure default {object} dto.Error "General error response"
|
|
// @Router /map/{id} [get]
|
|
func (h *MapHandler) Get(ctx *gin.Context) {
|
|
// Extract map ID from path parameter
|
|
id := ctx.Param("id")
|
|
mapID, err := strconv.ParseInt(id, 10, 64)
|
|
if err != nil {
|
|
ctx.JSON(http.StatusBadRequest, dto.Error{
|
|
Error: "Invalid map ID format",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Call the gRPC service
|
|
mapData, err := maps_extended.NewMapsServiceClient(h.mapsClient).Get(ctx, &maps_extended.MapId{
|
|
ID: mapID,
|
|
})
|
|
if err != nil {
|
|
statusCode := http.StatusInternalServerError
|
|
errorMessage := "Failed to get map"
|
|
|
|
// Check if it's a "not found" error
|
|
if status.Code(err) == codes.NotFound {
|
|
statusCode = http.StatusNotFound
|
|
errorMessage = "Map not found"
|
|
}
|
|
|
|
ctx.JSON(statusCode, dto.Error{
|
|
Error: errorMessage,
|
|
})
|
|
log.WithError(err).Error(
|
|
"Failed to get map",
|
|
)
|
|
return
|
|
}
|
|
|
|
// Convert gRPC MapResponse object to dto.Map object
|
|
var mapDto dto.Map
|
|
result := mapDto.FromGRPC(mapData)
|
|
|
|
// Return the map data
|
|
ctx.JSON(http.StatusOK, dto.Response[dto.Map]{
|
|
Data: *result,
|
|
})
|
|
}
|
|
|
|
// @Summary List maps
|
|
// @Description Get a list of maps
|
|
// @Tags maps
|
|
// @Produce json
|
|
// @Security ApiKeyAuth
|
|
// @Param page_size query int false "Page size (max 100)" default(10) minimum(1) maximum(100)
|
|
// @Param page_number query int false "Page number" default(1) minimum(1)
|
|
// @Param filter query dto.MapFilter false "Map filter parameters"
|
|
// @Success 200 {object} dto.PagedResponse[dto.Map]
|
|
// @Failure default {object} dto.Error "General error response"
|
|
// @Router /map [get]
|
|
func (h *MapHandler) List(ctx *gin.Context) {
|
|
// Extract and constrain pagination parameters
|
|
query := struct {
|
|
PageSize int `form:"page_size,default=10" binding:"min=1,max=100"`
|
|
PageNumber int `form:"page_number,default=1" binding:"min=1"`
|
|
SortBy int `form:"sort_by,default=0" binding:"min=0,max=3"`
|
|
}{}
|
|
if err := ctx.ShouldBindQuery(&query); err != nil {
|
|
ctx.JSON(http.StatusBadRequest, dto.Error{
|
|
Error: err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
// Get list filter
|
|
var filter dto.MapFilter
|
|
if err := ctx.ShouldBindQuery(&filter); err != nil {
|
|
ctx.JSON(http.StatusBadRequest, dto.Error{
|
|
Error: err.Error(),
|
|
})
|
|
return
|
|
}
|
|
|
|
// Call the gRPC service
|
|
mapList, err := maps_extended.NewMapsServiceClient(h.mapsClient).List(ctx, &maps_extended.ListRequest{
|
|
Filter: &maps_extended.MapFilter{
|
|
GameID: filter.GameID,
|
|
},
|
|
Page: &maps_extended.Pagination{
|
|
Size: uint32(query.PageSize),
|
|
Number: uint32(query.PageNumber),
|
|
},
|
|
})
|
|
if err != nil {
|
|
ctx.JSON(http.StatusInternalServerError, dto.Error{
|
|
Error: "Failed to list maps",
|
|
})
|
|
log.WithError(err).Error(
|
|
"Failed to list maps",
|
|
)
|
|
return
|
|
}
|
|
|
|
// Convert gRPC MapResponse objects to dto.Map objects
|
|
dtoMaps := make([]dto.Map, len(mapList.Maps))
|
|
for i, m := range mapList.Maps {
|
|
var mapDto dto.Map
|
|
dtoMaps[i] = *mapDto.FromGRPC(m)
|
|
}
|
|
|
|
// Return the paged response
|
|
ctx.JSON(http.StatusOK, dto.PagedResponse[dto.Map]{
|
|
Data: dtoMaps,
|
|
Pagination: dto.Pagination{
|
|
Page: query.PageNumber,
|
|
PageSize: query.PageSize,
|
|
},
|
|
})
|
|
}
|