mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 11:36:36 +08:00
161 lines
4.9 KiB
Go
161 lines
4.9 KiB
Go
// Package handler — cloud-disk (网盘) endpoints: directory browsing, QR-code
|
|
// login, media import and 302 playback redirects.
|
|
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/ShukeBta/MediaStationGo/internal/service"
|
|
)
|
|
|
|
// cloudListHandler browses a configured cloud disk directory.
|
|
func cloudListHandler(svc *service.Container) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
typ := c.Param("type")
|
|
if !service.IsAdminCloudConfigurable(typ) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "unsupported cloud provider", "items": []any{}})
|
|
return
|
|
}
|
|
dir := c.Query("dir")
|
|
entries, err := svc.StorageCfg.CloudList(c.Request.Context(), typ, dir)
|
|
if err != nil {
|
|
c.JSON(http.StatusOK, gin.H{"error": err.Error(), "items": []any{}})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"items": entries})
|
|
}
|
|
}
|
|
|
|
func cloudMkdirHandler(svc *service.Container) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
typ := c.Param("type")
|
|
if !service.IsAdminCloudConfigurable(typ) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "unsupported cloud provider"})
|
|
return
|
|
}
|
|
var in struct {
|
|
Dir string `json:"dir"`
|
|
Name string `json:"name" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&in); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
entry, err := svc.StorageCfg.CloudMkdir(c.Request.Context(), typ, in.Dir, in.Name)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"entry": entry})
|
|
}
|
|
}
|
|
|
|
func cloudRenameHandler(svc *service.Container) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
typ := c.Param("type")
|
|
if !service.IsAdminCloudConfigurable(typ) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "unsupported cloud provider"})
|
|
return
|
|
}
|
|
var in struct {
|
|
Ref string `json:"ref" binding:"required"`
|
|
Name string `json:"name" binding:"required"`
|
|
}
|
|
if err := c.ShouldBindJSON(&in); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
entry, err := svc.StorageCfg.CloudRename(c.Request.Context(), typ, in.Ref, in.Name)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"entry": entry})
|
|
}
|
|
}
|
|
|
|
// cloudImportHandler turns a cloud file into a playable 302-backed media item.
|
|
func cloudImportHandler(svc *service.Container) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
typ := c.Param("type")
|
|
if !service.IsAdminCloudConfigurable(typ) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "unsupported cloud provider"})
|
|
return
|
|
}
|
|
var in struct {
|
|
Ref string `json:"ref" binding:"required"`
|
|
Name string `json:"name"`
|
|
Size int64 `json:"size"`
|
|
}
|
|
if err := c.ShouldBindJSON(&in); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
m, err := svc.StorageCfg.CloudImport(c.Request.Context(), typ, in.Ref, in.Name, in.Size)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, m)
|
|
}
|
|
}
|
|
|
|
func cloudScanAllHandler(svc *service.Container) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
if svc.Scan == nil {
|
|
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "scanner unavailable"})
|
|
return
|
|
}
|
|
statuses, err := svc.Scan.StartAllCloudLibraryScans()
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
return
|
|
}
|
|
c.JSON(http.StatusAccepted, gin.H{
|
|
"items": statuses,
|
|
"scan_queued": true,
|
|
"message": "已开始扫描所有启用的网盘媒体库",
|
|
"resume_message": "中断后再次点击扫描会重新遍历,但已入库媒体会去重更新,只补齐缺失项。",
|
|
"estimate_message": "小目录通常几十秒;几万文件的大目录可能需要数分钟到数小时,取决于网盘接口速度",
|
|
})
|
|
}
|
|
}
|
|
|
|
func cloudScanCancelHandler(svc *service.Container) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
if svc.Scan == nil {
|
|
c.JSON(http.StatusServiceUnavailable, gin.H{"error": "scanner unavailable"})
|
|
return
|
|
}
|
|
libraryID := strings.TrimSpace(c.Query("library_id"))
|
|
provider := strings.TrimSpace(c.Query("provider"))
|
|
cancelled := 0
|
|
if libraryID != "" {
|
|
if svc.Scan.CancelCloudScan(libraryID) {
|
|
cancelled = 1
|
|
}
|
|
} else if provider != "" {
|
|
cancelled = svc.Scan.CancelCloudScansForProvider(provider)
|
|
} else {
|
|
cancelled = svc.Scan.CancelAllCloudScans()
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"cancelled": cancelled,
|
|
"message": "已发送中断信号;正在等待当前网盘请求返回后停止",
|
|
})
|
|
}
|
|
}
|
|
|
|
func cloudScanStatusHandler(svc *service.Container) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
if svc.Scan == nil {
|
|
c.JSON(http.StatusOK, gin.H{"items": []service.CloudScanStatus{}})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{"items": svc.Scan.CloudScanStatuses()})
|
|
}
|
|
}
|