mirror of
https://github.com/Dvorinka/SEEN.git
synced 2026-06-04 20:43:03 +00:00
small fix, don't worry about it
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/tdvorak/seen/backend/internal/domain"
|
||||
"github.com/tdvorak/seen/backend/internal/services/auth"
|
||||
"github.com/tdvorak/seen/backend/internal/services/catalog"
|
||||
"github.com/tdvorak/seen/backend/pkg/httpx"
|
||||
)
|
||||
|
||||
type CatalogHandler struct {
|
||||
service *catalog.Service
|
||||
authService *auth.Service
|
||||
}
|
||||
|
||||
func NewCatalogHandler(service *catalog.Service, authService *auth.Service) *CatalogHandler {
|
||||
return &CatalogHandler{service: service, authService: authService}
|
||||
}
|
||||
|
||||
type watchLaterAddRequest struct {
|
||||
MediaID int `json:"mediaId"`
|
||||
}
|
||||
|
||||
type progressUpdateRequest struct {
|
||||
MediaID int `json:"mediaId"`
|
||||
SeasonNumber int `json:"seasonNumber"`
|
||||
EpisodeNumber int `json:"episodeNumber"`
|
||||
ProgressPercent int `json:"progressPercent"`
|
||||
}
|
||||
|
||||
func (h *CatalogHandler) Dashboard(c *gin.Context) {
|
||||
httpx.JSON(c, http.StatusOK, h.service.Dashboard())
|
||||
}
|
||||
|
||||
func (h *CatalogHandler) ContinueWatching(c *gin.Context) {
|
||||
user, ok := h.resolveUser(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
items, err := h.service.ContinueWatching(user.ID)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, catalog.ErrInvalidInput):
|
||||
httpx.JSONError(c, http.StatusBadRequest, err.Error())
|
||||
default:
|
||||
httpx.JSONError(c, http.StatusInternalServerError, "failed to load continue watching")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
httpx.JSON(c, http.StatusOK, items)
|
||||
}
|
||||
|
||||
func (h *CatalogHandler) Discover(c *gin.Context) {
|
||||
page := parseInt(c.Query("page"), 1)
|
||||
pageSize := parseInt(c.Query("pageSize"), 6)
|
||||
|
||||
httpx.JSON(c, http.StatusOK, h.service.Discover(catalog.DiscoverParams{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
Query: c.Query("query"),
|
||||
Genre: c.Query("genre"),
|
||||
MediaType: c.Query("mediaType"),
|
||||
}))
|
||||
}
|
||||
|
||||
func (h *CatalogHandler) Games(c *gin.Context) {
|
||||
page := parseInt(c.Query("page"), 1)
|
||||
pageSize := parseInt(c.Query("pageSize"), 6)
|
||||
|
||||
httpx.JSON(c, http.StatusOK, h.service.Discover(catalog.DiscoverParams{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
Query: c.Query("query"),
|
||||
Genre: c.Query("genre"),
|
||||
MediaType: string(catalog.MediaTypeGame),
|
||||
}))
|
||||
}
|
||||
|
||||
func (h *CatalogHandler) Search(c *gin.Context) {
|
||||
httpx.JSON(c, http.StatusOK, h.service.Search(catalog.SearchParams{
|
||||
Query: c.Query("query"),
|
||||
Genre: c.Query("genre"),
|
||||
MediaType: c.Query("mediaType"),
|
||||
}))
|
||||
}
|
||||
|
||||
func (h *CatalogHandler) WatchLater(c *gin.Context) {
|
||||
user, ok := h.resolveUser(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
items, err := h.service.WatchLater(user.ID)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, catalog.ErrInvalidInput):
|
||||
httpx.JSONError(c, http.StatusBadRequest, err.Error())
|
||||
default:
|
||||
httpx.JSONError(c, http.StatusInternalServerError, "failed to load watch later")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
httpx.JSON(c, http.StatusOK, items)
|
||||
}
|
||||
|
||||
func (h *CatalogHandler) AddWatchLater(c *gin.Context) {
|
||||
user, ok := h.resolveUser(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var request watchLaterAddRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
httpx.JSONError(c, http.StatusBadRequest, "invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
items, err := h.service.AddWatchLater(user.ID, request.MediaID)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, catalog.ErrInvalidInput):
|
||||
httpx.JSONError(c, http.StatusBadRequest, err.Error())
|
||||
case errors.Is(err, catalog.ErrMediaNotFound):
|
||||
httpx.JSONError(c, http.StatusNotFound, err.Error())
|
||||
default:
|
||||
httpx.JSONError(c, http.StatusInternalServerError, "failed to add watch later item")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
httpx.JSON(c, http.StatusOK, items)
|
||||
}
|
||||
|
||||
func (h *CatalogHandler) RemoveWatchLater(c *gin.Context) {
|
||||
user, ok := h.resolveUser(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
mediaID := parseInt(c.Param("mediaId"), 0)
|
||||
items, err := h.service.RemoveWatchLater(user.ID, mediaID)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, catalog.ErrInvalidInput):
|
||||
httpx.JSONError(c, http.StatusBadRequest, err.Error())
|
||||
default:
|
||||
httpx.JSONError(c, http.StatusInternalServerError, "failed to remove watch later item")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
httpx.JSON(c, http.StatusOK, items)
|
||||
}
|
||||
|
||||
func (h *CatalogHandler) UpdateProgress(c *gin.Context) {
|
||||
user, ok := h.resolveUser(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
var request progressUpdateRequest
|
||||
if err := c.ShouldBindJSON(&request); err != nil {
|
||||
httpx.JSONError(c, http.StatusBadRequest, "invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
items, err := h.service.UpdateProgress(user.ID, catalog.ProgressUpdateInput{
|
||||
MediaID: request.MediaID,
|
||||
SeasonNumber: request.SeasonNumber,
|
||||
EpisodeNumber: request.EpisodeNumber,
|
||||
ProgressPercent: request.ProgressPercent,
|
||||
})
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, catalog.ErrInvalidInput):
|
||||
httpx.JSONError(c, http.StatusBadRequest, err.Error())
|
||||
case errors.Is(err, catalog.ErrMediaNotFound):
|
||||
httpx.JSONError(c, http.StatusNotFound, err.Error())
|
||||
default:
|
||||
httpx.JSONError(c, http.StatusInternalServerError, "failed to update progress")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
httpx.JSON(c, http.StatusOK, items)
|
||||
}
|
||||
|
||||
func (h *CatalogHandler) resolveUser(c *gin.Context) (*domain.User, bool) {
|
||||
accessToken, ok := bearerToken(c.GetHeader("Authorization"))
|
||||
if !ok {
|
||||
httpx.JSONError(c, http.StatusUnauthorized, "missing bearer token")
|
||||
return nil, false
|
||||
}
|
||||
|
||||
user, err := h.authService.UserFromAccessToken(c.Request.Context(), accessToken)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, auth.ErrInvalidToken):
|
||||
httpx.JSONError(c, http.StatusUnauthorized, err.Error())
|
||||
default:
|
||||
httpx.JSONError(c, http.StatusInternalServerError, "failed to resolve user")
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return user, true
|
||||
}
|
||||
|
||||
func parseInt(raw string, fallback int) int {
|
||||
if raw == "" {
|
||||
return fallback
|
||||
}
|
||||
|
||||
parsed, err := strconv.Atoi(raw)
|
||||
if err != nil {
|
||||
return fallback
|
||||
}
|
||||
|
||||
return parsed
|
||||
}
|
||||
Reference in New Issue
Block a user