mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-28 03:06:38 +08:00
b0fe40142a
* Rebrand MMTL to MeBox across codebase and assets Rename the project display name, Go module path, environment variable prefix (MEBOX_*), Docker image references, and UI branding from MMTL/mmtl to MeBox/mebox. Replace logo assets with the new MeBox icon and keep legacy SQLite migration support for existing mmtl.db deployments. Co-authored-by: truewhile <truewhile@users.noreply.github.com> * Fix logo icons: use cube-only crop without truncated text Previous icon generation cropped too much of the source image, including partial MeBox wordmark text that was cut off in square icon containers. Regenerate logo-64/192/512, favicon, and SVG from cube-only region. Co-authored-by: truewhile <truewhile@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: truewhile <truewhile@users.noreply.github.com>
71 lines
2.4 KiB
Go
71 lines
2.4 KiB
Go
// Package handler — auxiliary media endpoints used by the home page
|
|
// rails (recent additions) and the admin dashboard summary card.
|
|
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/truewhile/MeBox/internal/model"
|
|
"github.com/truewhile/MeBox/internal/service"
|
|
)
|
|
|
|
func recentMediaHandler(svc *service.Container) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "12"))
|
|
if limit <= 0 || limit > 100 {
|
|
limit = 12
|
|
}
|
|
items, err := svc.Media.ListRecentSeriesCards(c.Request.Context(), limit, mediaVisibilityForRequest(c, svc))
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, items)
|
|
}
|
|
}
|
|
|
|
func mediaStatsHandler(svc *service.Container) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
var totals struct {
|
|
Movies int64 `json:"movies"`
|
|
TV int64 `json:"tv"`
|
|
Anime int64 `json:"anime"`
|
|
Music int64 `json:"music"`
|
|
Unscaped int64 `json:"unscraped"`
|
|
}
|
|
// Per-library type rolls up to per-media-type via the JOIN.
|
|
_ = svc.Repo.DB.Model(&model.Media{}).
|
|
Joins("JOIN libraries ON libraries.id = media.library_id").
|
|
Where("libraries.type = ?", "movie").Count(&totals.Movies).Error
|
|
_ = svc.Repo.DB.Model(&model.Media{}).
|
|
Joins("JOIN libraries ON libraries.id = media.library_id").
|
|
Where("libraries.type = ?", "tv").Count(&totals.TV).Error
|
|
_ = svc.Repo.DB.Model(&model.Media{}).
|
|
Joins("JOIN libraries ON libraries.id = media.library_id").
|
|
Where("libraries.type = ?", "anime").Count(&totals.Anime).Error
|
|
_ = svc.Repo.DB.Model(&model.Media{}).
|
|
Joins("JOIN libraries ON libraries.id = media.library_id").
|
|
Where("libraries.type = ?", "music").Count(&totals.Music).Error
|
|
_ = svc.Repo.DB.Model(&model.Media{}).
|
|
Where("scrape_status IS NULL OR scrape_status = '' OR scrape_status = 'pending'").
|
|
Count(&totals.Unscaped).Error
|
|
|
|
var totalCount, totalSize, totalSeconds int64
|
|
_ = svc.Repo.DB.Model(&model.Media{}).Count(&totalCount).Error
|
|
_ = svc.Repo.DB.Model(&model.Media{}).
|
|
Select("COALESCE(SUM(size_bytes),0)").Row().Scan(&totalSize)
|
|
_ = svc.Repo.DB.Model(&model.Media{}).
|
|
Select("COALESCE(SUM(duration_sec),0)").Row().Scan(&totalSeconds)
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"by_type": totals,
|
|
"total": totalCount,
|
|
"total_size": totalSize,
|
|
"total_seconds": totalSeconds,
|
|
})
|
|
}
|
|
}
|