mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-05 13:06:36 +08:00
feat: port remaining Vue UI surfaces with full backend support
Backend additions:
- New GORM models: NotifyChannel, PlayProfile (with PIN hashing).
- NotifyChannelService: multi-channel CRUD + unified dispatcher
supporting Telegram / Bark / WeChat / Webhook with optional
per-channel event filtering.
- PlayProfileService: per-user 'viewing personas' with
content-rating gates, library scoping, PIN protection, and
player defaults (autoplay, skip-intro, audio/subtitle prefs).
- New endpoints:
GET /admin/notify/channels list
POST /admin/notify/channels create
PUT /admin/notify/channels/:id update
DELETE /admin/notify/channels/:id delete
POST /admin/notify/channels/:id/test send test
GET /play-profiles list (admin: ?all=true)
POST /play-profiles create
PUT /play-profiles/:id update
DELETE /play-profiles/:id delete
GET /media/recent home page rail
GET /media/stats library composition
GET /watch-history list
GET /watch-history/stats aggregate
GET /watch-history/continue continue-watching rail
DELETE /watch-history[?media_id=] clear
DELETE /watch-history/:id remove one
GET /discover/sections available rails
GET /discover/feed?sections=a,b multi-section TMDb fetch
GET /system/info name/version/runtime
GET /system/status uptime/cpu/mem/disk
GET /system/scheduler read-only scheduler view
GET /stats/overview counts only
GET /stats/trend daily plays
GET /stats/top-content most played
GET /stats/libraries per-library size
GET /stats/monitor live hardware
Frontend additions:
- New API helpers: notify_channels, play_profiles, history,
stats_extra, media_extra, discover_extra, system.
- ProfileManagementPage (/play-profiles): full CRUD form with
PIN management, library scoping, language preferences.
- NotifyChannelsPage (/notify-channels, admin): typed config
forms per channel type + per-channel test action.
- SettingsPage (/settings, admin): grouped key/value editor
covering General, Organize/Scrape, Adult, qBittorrent.
- Layout sidebar links and App.tsx routes wired for all three.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
// Package handler — multi-section discover endpoints.
|
||||
//
|
||||
// The Vue DiscoverView paginates a configurable list of "sections"
|
||||
// (trending day/week, popular movies, top rated, etc.) and asks the
|
||||
// backend for a feed keyed by section name. We mirror that surface so
|
||||
// the React DiscoverPage can render the same rails without a rewrite.
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/ShukeBta/MediaStationGo/internal/service"
|
||||
)
|
||||
|
||||
// discoverSectionsHandler returns the catalog of sections the UI can
|
||||
// pick from. The names match the upstream Vue UI so existing settings
|
||||
// keep working.
|
||||
func discoverSectionsHandler(_ *service.Container) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"sections": []gin.H{
|
||||
{"key": "trending_day", "label": "今日热门"},
|
||||
{"key": "trending_week", "label": "本周热门"},
|
||||
{"key": "popular_movie", "label": "热门电影"},
|
||||
{"key": "popular_tv", "label": "热门剧集"},
|
||||
{"key": "top_rated_movie", "label": "高分电影"},
|
||||
{"key": "upcoming_movie", "label": "即将上映"},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// discoverFeedHandler resolves one or more section keys (?sections=a,b)
|
||||
// to TMDb endpoint paths and returns the joined results keyed by
|
||||
// section name. Unknown keys are silently dropped so URL typos don't
|
||||
// break the page.
|
||||
func discoverFeedHandler(svc *service.Container) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
keys := strings.Split(c.DefaultQuery("sections", "trending_day,popular_movie"), ",")
|
||||
out := gin.H{}
|
||||
for _, raw := range keys {
|
||||
k := strings.TrimSpace(raw)
|
||||
path := sectionPath(k)
|
||||
if path == "" {
|
||||
continue
|
||||
}
|
||||
items, err := svc.Discover.Fetch(c.Request.Context(), path)
|
||||
if err != nil {
|
||||
svc.Log.Debug("discover fetch failed", )
|
||||
items = nil
|
||||
}
|
||||
out[k] = items
|
||||
}
|
||||
c.JSON(http.StatusOK, out)
|
||||
}
|
||||
}
|
||||
|
||||
// sectionPath maps the UI-facing key to the TMDb endpoint suffix.
|
||||
func sectionPath(k string) string {
|
||||
switch k {
|
||||
case "trending_day":
|
||||
return "/trending/movie/day"
|
||||
case "trending_week":
|
||||
return "/trending/movie/week"
|
||||
case "popular_movie":
|
||||
return "/movie/popular"
|
||||
case "popular_tv":
|
||||
return "/tv/popular"
|
||||
case "top_rated_movie":
|
||||
return "/movie/top_rated"
|
||||
case "upcoming_movie":
|
||||
return "/movie/upcoming"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user