优化
This commit is contained in:
truewhile
2026-08-24 17:40:43 +08:00
parent 99ef2ed410
commit 44ca451cd4
374 changed files with 1029 additions and 1028 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/repository"
)
var (
@@ -11,8 +11,8 @@ import (
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func TestAdultProviderRouting(t *testing.T) {
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func TestNormalizeAdultCode(t *testing.T) {
+3 -3
View File
@@ -5,7 +5,7 @@
// read so values stored on disk are useless without the JWT secret.
//
// On first read it seeds the table with the providers supported by
// MediaStationGo today (TMDb / Bangumi / TheTVDB / Fanart / OpenAI / Douban).
// MMTL today (TMDb / Bangumi / TheTVDB / Fanart / OpenAI / Douban).
package service
import (
@@ -17,8 +17,8 @@ import (
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// APIConfigService coordinates third-party API key storage.
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"strings"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// TestConnection 测试 API 连接。
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"net/url"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// GetEffectiveConfig 获取生效的 API 配置(数据库配置优先于配置文件)。
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// ApiConfigService 负责第三方 API 配置的 CRUD 和加密管理。
+2 -2
View File
@@ -12,8 +12,8 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// AuditService is the only sanctioned writer for the access_logs table.
+3 -3
View File
@@ -12,9 +12,9 @@ import (
"go.uber.org/zap"
"golang.org/x/crypto/bcrypt"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// AuthService handles registration, login, and JWT issuance.
+4 -4
View File
@@ -9,7 +9,7 @@ import (
"github.com/golang-jwt/jwt/v5"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// IssueToken signs a JWT for the given user (60min validity, includes tier).
@@ -21,7 +21,7 @@ func (s *AuthService) IssueToken(u *model.User) (string, error) {
RegisteredClaims: jwt.RegisteredClaims{
IssuedAt: jwt.NewNumericDate(time.Now()),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(60 * time.Minute)),
Issuer: "mediastationgo",
Issuer: "mmtl",
Subject: u.ID,
},
}
@@ -68,7 +68,7 @@ func (s *AuthService) IssueExternalPlaybackToken(u *model.User, mediaID string,
RegisteredClaims: jwt.RegisteredClaims{
IssuedAt: jwt.NewNumericDate(time.Now()),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(ExternalPlaybackTokenDurationForMedia(durationSec))),
Issuer: "mediastationgo",
Issuer: "mmtl",
Subject: u.ID,
},
}
@@ -95,7 +95,7 @@ func (s *AuthService) IssueEmbyToken(u *model.User) (string, error) {
RegisteredClaims: jwt.RegisteredClaims{
IssuedAt: jwt.NewNumericDate(time.Now()),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(EmbyTokenDuration)),
Issuer: "mediastationgo",
Issuer: "mmtl",
Subject: u.ID,
},
}
+4 -4
View File
@@ -12,10 +12,10 @@ import (
"go.uber.org/zap"
"golang.org/x/crypto/bcrypt"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/database"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/database"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func newAuthTestServices(t *testing.T) (*repository.Container, *AuthService, *ProfileService, *PermissionService) {
+2 -2
View File
@@ -19,7 +19,7 @@ import (
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MMTL/internal/config"
)
// BackupService manages database backups.
@@ -72,7 +72,7 @@ func (b *BackupService) Create(ctx context.Context) (*BackupInfo, error) {
return nil, err
}
ts := time.Now().Format("20060102_150405")
dst := filepath.Join(dir, fmt.Sprintf("mediastation_%s.db", ts))
dst := filepath.Join(dir, fmt.Sprintf("mmtl_%s.db", ts))
// VACUUM INTO creates a clean, non-WAL copy atomically.
if err := b.db.WithContext(ctx).Exec("VACUUM INTO ?", dst).Error; err != nil {
+2 -2
View File
@@ -23,7 +23,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MMTL/internal/config"
)
// BangumiProvider talks to https://api.bgm.tv.
@@ -181,7 +181,7 @@ func (b *BangumiProvider) getJSON(ctx context.Context, u string, out any) error
if err != nil {
return err
}
req.Header.Set("User-Agent", "MediaStationGo/0.1 (https://github.com/ShukeBta/MediaStationGo)")
req.Header.Set("User-Agent", "MMTL/0.1 (https://github.com/ShukeBta/MMTL)")
if t := strings.TrimSpace(b.cfg.Secrets.BangumiToken); t != "" {
req.Header.Set("Authorization", "Bearer "+t)
}
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"strconv"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// Bot / 设备管控相关的设置键。全部存储在 settings 表,由管理员通过
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"strings"
"testing"
"github.com/ShukeBta/MediaStationGo/internal/service/cloud115"
"github.com/ShukeBta/MMTL/internal/service/cloud115"
)
// 115 开放平台(openapi)驱动测试:mock proapi 的列目录/直链接口。
+1 -1
View File
@@ -13,7 +13,7 @@ import (
// cloudDrive2Provider bridges CloudDrive2 through its WebDAV endpoint.
//
// CloudDrive2 integrates many cloud disks (115 / 123 / Aliyun and more).
// Treating it as a WebDAV-backed cloud provider lets MediaStationGo
// Treating it as a WebDAV-backed cloud provider lets MMTL
// browse, mount and upload to those disks without carrying every provider's
// private chunk-upload protocol in this project.
type cloudDrive2Provider struct {
+1 -1
View File
@@ -19,7 +19,7 @@ import (
"fmt"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/service/cloud115"
"github.com/ShukeBta/MMTL/internal/service/cloud115"
)
// openAPI115Provider 实现 Provider 接口:List 列目录、Resolve 用 pickcode
@@ -6,8 +6,8 @@ import (
"path"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// CloudMountInfo 是云盘挂载库的规范标识(因网盘后端已移除,仅保留类型以兼容
+2 -2
View File
@@ -15,7 +15,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/repository"
)
// Danmaku setting keys, managed through the admin settings UI (PUT
@@ -296,7 +296,7 @@ func (s *DanmakuService) fetchBody(ctx context.Context, sourceURL string, follow
if err != nil {
return "", err
}
req.Header.Set("User-Agent", "MediaStationGo/danmaku (+https://github.com/ShukeBta/MediaStationGo)")
req.Header.Set("User-Agent", "MMTL/danmaku (+https://github.com/ShukeBta/MMTL)")
req.Header.Set("Accept", "application/json, application/xml, */*")
resp, err := client.Do(req)
if err != nil {
+2 -2
View File
@@ -13,8 +13,8 @@ import (
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func newDanmakuTestService(t *testing.T) *DanmakuService {
+1 -1
View File
@@ -1,6 +1,6 @@
package service
import "github.com/ShukeBta/MediaStationGo/internal/repository"
import "github.com/ShukeBta/MMTL/internal/repository"
func IsTransientDatabaseLock(err error) bool {
return repository.IsSQLiteBusyError(err)
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// SweepInactiveUsers is kept for compatibility with the existing scheduler; it
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"strings"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// KickDevice marks a device as kicked so the next request from it is rejected
+2 -2
View File
@@ -10,8 +10,8 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// DeviceService implements device/session tracking and the two decoupled
+1 -1
View File
@@ -6,7 +6,7 @@
// service to start playback of an HTTP URL.
//
// We do NOT mediate the renderer ↔ client traffic; the renderer pulls
// the bytes directly from MediaStationGo's /api/stream endpoint, so
// the bytes directly from MMTL's /api/stream endpoint, so
// the cast call only ever transports a URL string.
package service
+1 -1
View File
@@ -27,7 +27,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MMTL/internal/config"
)
// DoubanProvider talks to the unofficial Douban movie API.
+2 -2
View File
@@ -5,8 +5,8 @@ import (
"strings"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// ImageURL returns artwork for a media/series/season item id.
+1 -1
View File
@@ -3,7 +3,7 @@ package service
import (
"testing"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func TestImageURLFallsBackToLibraryCoverURL(t *testing.T) {
+4 -4
View File
@@ -3,7 +3,7 @@
// EmbyService produces JSON envelopes shaped like the most-consumed
// Emby-API endpoints so existing players (Infuse / Yamby / Hills /
// Senplayer / Kodi NextPVR extension / iOS native clients) can talk to
// MediaStationGo without a custom plugin.
// MMTL without a custom plugin.
//
// The shim is read-mostly: items, images, playback are fully covered;
// 播放进度上报 / 收藏切换 是写路径但走我们自己的 PlaybackHistory /
@@ -17,14 +17,14 @@ import (
"sync"
"time"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/repository"
"go.uber.org/zap"
)
// 用一个固定的 ServerId 字符串。Emby 客户端会缓存这个 id,第一次见到
// 该 id 后会把所有派生数据(cookie/收藏/历史)和它绑定。
const embyServerID = "mediastation-go-001"
const embyServerID = "mmtl-001"
// embyCompatVersion deliberately reports an Emby 4.x server. Official Emby
// clients reject Jellyfin-style 10.x identities as unsupported/too old during
+3 -3
View File
@@ -6,9 +6,9 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func newTestEmbyService(t *testing.T) *EmbyService {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"context"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
"gorm.io/gorm"
)
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"strings"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// Item 单条目详情。
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"strings"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func (e *EmbyService) mediaItems(ctx context.Context, p ItemsParams) (map[string]any, error) {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"sort"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func (e *EmbyService) mediaSourcesForItem(ctx context.Context, m *model.Media, asEmbedded, directOnly bool) []map[string]any {
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// movieLibraryHasEpisodicContent 报告电影类型库里是否混入了「剧集结构」内容
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"testing"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func TestEmbyMovieLibrarySeasonNumbersStayMovies(t *testing.T) {
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"strings"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// PlaybackInfo returns a PlaybackInfoResponse usable by Emby clients.
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"testing"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func TestEmbyRootItemsExposeLibraries(t *testing.T) {
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"strings"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
type embySeriesGroup struct {
@@ -6,7 +6,7 @@ import (
"testing"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func TestEmbyItemsExposeSeriesSeasonEpisodeHierarchy(t *testing.T) {
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"strings"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func (e *EmbyService) seriesIDForMedia(m *model.Media) string {
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// writeTempVideoWithSubtitle creates a temp directory with a fake video and a
+4 -4
View File
@@ -5,7 +5,7 @@ import (
"strings"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// SystemInfo returns the full Emby identity payload.
@@ -13,7 +13,7 @@ func (e *EmbyService) SystemInfo() map[string]any {
return map[string]any{
"Id": embyServerID,
"ServerId": embyServerID,
"ServerName": "MediaStationGo",
"ServerName": "MMTL",
"Version": embyCompatVersion,
"ServerVersion": embyCompatVersion,
"ProductName": "Emby Server",
@@ -42,7 +42,7 @@ func (e *EmbyService) SystemInfoPublic() map[string]any {
return map[string]any{
"Id": embyServerID,
"ServerId": embyServerID,
"ServerName": "MediaStationGo",
"ServerName": "MMTL",
"Version": embyCompatVersion,
"ServerVersion": embyCompatVersion,
"ProductName": "Emby Server",
@@ -85,7 +85,7 @@ func (e *EmbyService) userPayload(u *model.User) map[string]any {
"Id": u.ID,
"Name": u.Username,
"ServerId": embyServerID,
"ServerName": "MediaStationGo",
"ServerName": "MMTL",
"HasPassword": true,
"HasConfiguredPassword": true,
"HasConfiguredEasyPassword": false,
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// SetFavorite 把 mediaID 标为 userID 的收藏。
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"testing"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func TestEmbyLatestItemsCollapsesMovieVersions(t *testing.T) {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func (e *EmbyService) applyUserMediaVisibility(ctx context.Context, q *gorm.DB, userID string) *gorm.DB {
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// pollutedEpisodeCleanupSettingKey marks that the one-time normalization has run.
@@ -6,8 +6,8 @@ import (
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func newCleanupTestContainer(t *testing.T) (*Container, *gorm.DB) {
+2 -2
View File
@@ -21,7 +21,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MMTL/internal/config"
)
// FanartProvider talks to https://webservice.fanart.tv.
@@ -133,7 +133,7 @@ func (f *FanartProvider) getJSON(ctx context.Context, u string, out any) error {
if err != nil {
return err
}
req.Header.Set("User-Agent", "MediaStationGo/0.1")
req.Header.Set("User-Agent", "MMTL/0.1")
resp, err := f.client.Do(req)
if err != nil {
return err
+2 -2
View File
@@ -12,7 +12,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MMTL/internal/config"
)
// AutoInstallFFmpeg is only called by the admin tool-install endpoint. The
@@ -91,7 +91,7 @@ func downloadFFmpegWindows(log *zap.Logger, installDir string) (bool, error) {
return false, fmt.Errorf("创建安装目录失败: %w", err)
}
tempDir, err := os.MkdirTemp("", "mediastationgo-ffmpeg-*")
tempDir, err := os.MkdirTemp("", "mmtl-ffmpeg-*")
if err != nil {
return false, fmt.Errorf("创建临时目录失败: %w", err)
}
+1 -1
View File
@@ -18,7 +18,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MMTL/internal/config"
)
// FFprobeService wraps the external ffprobe binary.
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MMTL/internal/config"
)
func TestFFprobeServiceDefaultsToSingleConcurrentProbe(t *testing.T) {
+2 -2
View File
@@ -16,8 +16,8 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/repository"
)
// FileManagerService browses and mutates the server-side filesystem.
+2 -2
View File
@@ -67,8 +67,8 @@ func (s *FileManagerService) allowedRoots() (map[string]string, error) {
add("movies", s.cfg.Media.MoviesDir)
add("tv", s.cfg.Media.TVDir)
add("anime", s.cfg.Media.AnimeDir)
add("downloads", envOrDefault("MEDIASTATION_DOWNLOAD_CONTAINER_DIR", "/downloads"))
add("media", envOrDefault("MEDIASTATION_MEDIA_CONTAINER_DIR", "/media"))
add("downloads", envOrDefault("MMTL_DOWNLOAD_CONTAINER_DIR", "/downloads"))
add("media", envOrDefault("MMTL_MEDIA_CONTAINER_DIR", "/media"))
if s.repo != nil && s.repo.Setting != nil {
addSetting := func(label, key string) {
if value, err := s.repo.Setting.Get(context.Background(), key); err == nil {
+3 -3
View File
@@ -8,9 +8,9 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func newFileManagerTestServiceWithRepo(t *testing.T, root string) (*FileManagerService, *repository.Container) {
+2 -2
View File
@@ -2,7 +2,7 @@
//
// Some deployments cannot reach image.tmdb.org directly (GFW, internal-only
// networks). ImageProxy fronts a remote image URL so the browser only ever
// talks to the MediaStationGo origin. The proxy:
// talks to the MMTL origin. The proxy:
//
// - validates the URL scheme is http/https,
// - streams bytes through with a small disk cache under cache/images,
@@ -20,7 +20,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MMTL/internal/config"
)
// ImageProxy fetches and caches remote images on behalf of the browser.
+1 -1
View File
@@ -14,7 +14,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MMTL/internal/config"
)
func TestImageProxyDoesNotNegativeCacheFailedRemoteImageFetch(t *testing.T) {
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MMTL/internal/config"
)
var testJPEG = []byte{
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"regexp"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
var availabilityNoiseRE = regexp.MustCompile(`(?i)(自动订阅|订阅|全集|合集|complete|batch|s\d{1,2}e\d{1,3}|season\s*\d+|s\d{1,2}|第\s*\d+\s*季|第\s*\d+\s*[集话話期]|\(\d{4}\)|\b\d{4}\b|2160p|1080p|720p|4k|uhd|bluray|blu-ray|web-?dl|hdtv|remux|x26[45]|h\.?26[45]|hevc|avc|hdr10?\+?|dovi|dv|atmos|aac|ddp?5\.1|truehd|flac)`)
+1 -1
View File
@@ -1,6 +1,6 @@
package service
import "github.com/ShukeBta/MediaStationGo/internal/model"
import "github.com/ShukeBta/MMTL/internal/model"
func applyLocalMetadata(m *model.Media, local *LocalMetadata) {
applyLocalIdentityMetadata(m, local)
@@ -3,7 +3,7 @@ package service
import (
"testing"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func TestApplyLocalMetadataPreservesPathHintAsPending(t *testing.T) {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"errors"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
type ManualScrapeRequest struct {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"context"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
type manualTMDbCandidate struct {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"errors"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func (s *ScraperService) ManualSearch(ctx context.Context, media *model.Media, query, provider, mediaType string) ([]ExternalMediaResult, error) {
+3 -3
View File
@@ -13,9 +13,9 @@ import (
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func TestManualRequestMatchFallsBackToCandidatePayload(t *testing.T) {
+3 -3
View File
@@ -4,9 +4,9 @@ package service
import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// MediaService offers high-level CRUD over libraries and media items.
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"sort"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
type mediaListCacheValue struct {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"regexp"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
var (
+2 -2
View File
@@ -4,8 +4,8 @@ import (
"context"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func (s *MediaService) attachLibraryMetadata(ctx context.Context, items []model.Media) {
+1 -1
View File
@@ -3,7 +3,7 @@ package service
import (
"context"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
"gorm.io/gorm"
)
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"path/filepath"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
type LibraryRootInput struct {
+3 -3
View File
@@ -6,9 +6,9 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func TestCreateLibraryWithRootsAppendsToExistingLogicalLibrary(t *testing.T) {
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// ListMedia paginates media items inside a library.
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"errors"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
type MediaMetadataUpdate struct {
+3 -3
View File
@@ -5,9 +5,9 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func TestUpdateMediaMetadataMarksManualMatch(t *testing.T) {
+10 -10
View File
@@ -69,8 +69,8 @@ func embeddedContainerMarkerCandidates(input string) []string {
part string
container string
}{
{part: "/media", container: envOrDefault("MEDIASTATION_MEDIA_CONTAINER_DIR", "/media")},
{part: "/downloads", container: envOrDefault("MEDIASTATION_DOWNLOAD_CONTAINER_DIR", "/downloads")},
{part: "/media", container: envOrDefault("MMTL_MEDIA_CONTAINER_DIR", "/media")},
{part: "/downloads", container: envOrDefault("MMTL_DOWNLOAD_CONTAINER_DIR", "/downloads")},
} {
part := strings.TrimRight(marker.part, "/")
container := strings.TrimRight(filepath.ToSlash(marker.container), "/")
@@ -83,17 +83,17 @@ func embeddedContainerMarkerCandidates(input string) []string {
// describeUnresolvedLibraryPath 把「路径解析失败」变成可操作的诊断信息:列出尝试过的
// 候选路径与当前的宿主机→容器映射状态。旧库存的是宿主机路径,在新版/容器内常因为缺少
// MEDIASTATION_MEDIA_DIR 映射而扫不出媒体——这条诊断帮助用户直接定位到底哪一步断了。
// MMTL_MEDIA_DIR 映射而扫不出媒体——这条诊断帮助用户直接定位到底哪一步断了。
// 仅用于日志与扫描错误提示,不改变解析逻辑本身。
func describeUnresolvedLibraryPath(rawPath string) string {
rawPath = strings.TrimSpace(rawPath)
candidates := mappedPathCandidates(rawPath)
mediaHost := strings.TrimSpace(os.Getenv("MEDIASTATION_MEDIA_DIR"))
mediaContainer := envOrDefault("MEDIASTATION_MEDIA_CONTAINER_DIR", "/media")
mediaHost := strings.TrimSpace(os.Getenv("MMTL_MEDIA_DIR"))
mediaContainer := envOrDefault("MMTL_MEDIA_CONTAINER_DIR", "/media")
var b strings.Builder
fmt.Fprintf(&b, "媒体库路径无法解析为可访问目录:%s(已尝试候选:%s)", rawPath, strings.Join(candidates, " | "))
if mediaHost == "" {
b.WriteString(";未配置 MEDIASTATION_MEDIA_DIR / MEDIASTATION_MEDIA_CONTAINER_DIR。若为 Docker 部署且此库为旧宿主机路径,请设置这两个变量把宿主机路径映射到容器内路径,并确认对应 volume 已挂载。")
b.WriteString(";未配置 MMTL_MEDIA_DIR / MMTL_MEDIA_CONTAINER_DIR。若为 Docker 部署且此库为旧宿主机路径,请设置这两个变量把宿主机路径映射到容器内路径,并确认对应 volume 已挂载。")
} else {
fmt.Fprintf(&b, ";当前映射 %s → %s。请确认该库路径位于此宿主机目录下,或补充对应的 volume 与路径映射。", mediaHost, mediaContainer)
}
@@ -204,8 +204,8 @@ func dockerVolumePathCandidates(path string) []string {
env string
container string
}{
{env: "MEDIASTATION_MEDIA_DIR", container: envOrDefault("MEDIASTATION_MEDIA_CONTAINER_DIR", "/media")},
{env: "MEDIASTATION_DOWNLOAD_DIR", container: envOrDefault("MEDIASTATION_DOWNLOAD_CONTAINER_DIR", "/downloads")},
{env: "MMTL_MEDIA_DIR", container: envOrDefault("MMTL_MEDIA_CONTAINER_DIR", "/media")},
{env: "MMTL_DOWNLOAD_DIR", container: envOrDefault("MMTL_DOWNLOAD_CONTAINER_DIR", "/downloads")},
} {
container := cleanPathForVolumeMapping(mapping.container)
if container == "." || container == "" || strings.HasPrefix(container, ".") {
@@ -247,8 +247,8 @@ func dockerVolumePathCandidates(path string) []string {
part string
container string
}{
{part: "/media", container: envOrDefault("MEDIASTATION_MEDIA_CONTAINER_DIR", "/media")},
{part: "/downloads", container: envOrDefault("MEDIASTATION_DOWNLOAD_CONTAINER_DIR", "/downloads")},
{part: "/media", container: envOrDefault("MMTL_MEDIA_CONTAINER_DIR", "/media")},
{part: "/downloads", container: envOrDefault("MMTL_DOWNLOAD_CONTAINER_DIR", "/downloads")},
} {
part := strings.TrimRight(marker.part, "/")
container := strings.TrimRight(filepath.ToSlash(marker.container), "/")
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
const maxRecycleBinRecords = 200
+3 -3
View File
@@ -9,9 +9,9 @@ import (
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func TestListRecycleBinPrunesOldRowsOverLimit(t *testing.T) {
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func mediaReleaseSortTime(media model.Media) time.Time {
+2 -2
View File
@@ -3,8 +3,8 @@ package service
import (
"context"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// SearchMedia performs a simple LIKE search across titles.
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"strings"
"time"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
type SeriesCard struct {
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"regexp"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
var episodicPathRE = regexp.MustCompile(`(?i)[\\/](?:电视剧|剧集|连续剧|短剧|国产剧|国剧|大陆剧|华语剧|国产电视剧|大陆电视剧|华语电视剧|欧美剧|欧美电视剧|美剧|英剧|日韩剧|日韩电视剧|日剧|韩剧|港剧|台剧|港台剧|泰剧|综艺|纪录片|儿童|动漫|番剧|国漫|日番|韩漫|美漫|欧美动漫|欧美动画|其他动漫|tv|series|shows?|season[\s._-]*\d|s\d{1,2}(?:[\s._-]|[\\/])|special[\s._-]*episodes?|specials?|sp|ovas?|oads?|extras?|bonus(?:es)?|omake|特别篇|特別篇|番外篇?|特典|外传|外傳|总集篇|總集篇)[\\/]`)
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"fmt"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
type mediaSeriesKeyResolver struct {
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func TestListRecentSeriesCardsCountsAllEpisodesInSeries(t *testing.T) {
+15 -15
View File
@@ -14,8 +14,8 @@ func TestResolveAccessibleLibraryPathMapsConfiguredHostMediaDir(t *testing.T) {
if err := os.MkdirAll(containerLibrary, 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("MEDIASTATION_MEDIA_DIR", hostRoot)
t.Setenv("MEDIASTATION_MEDIA_CONTAINER_DIR", containerRoot)
t.Setenv("MMTL_MEDIA_DIR", hostRoot)
t.Setenv("MMTL_MEDIA_CONTAINER_DIR", containerRoot)
got, err := resolveAccessibleLibraryPath(filepath.Join(hostRoot, "电视剧", "国产剧"))
if err != nil {
@@ -33,8 +33,8 @@ func TestResolveAccessibleLibraryPathMapsWindowsDriveBeforeLinuxAbs(t *testing.T
if err := os.MkdirAll(containerLibrary, 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("MEDIASTATION_MEDIA_DIR", `Q:\media`)
t.Setenv("MEDIASTATION_MEDIA_CONTAINER_DIR", containerRoot)
t.Setenv("MMTL_MEDIA_DIR", `Q:\media`)
t.Setenv("MMTL_MEDIA_CONTAINER_DIR", containerRoot)
for _, input := range []string{
`Q:\media\电视剧\国产剧`,
@@ -61,8 +61,8 @@ func TestResolveAccessibleLibraryPathRecoversDockerPollutedWindowsDrive(t *testi
if err := os.MkdirAll(containerLibrary, 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("MEDIASTATION_MEDIA_DIR", `F:\media`)
t.Setenv("MEDIASTATION_MEDIA_CONTAINER_DIR", containerRoot)
t.Setenv("MMTL_MEDIA_DIR", `F:\media`)
t.Setenv("MMTL_MEDIA_CONTAINER_DIR", containerRoot)
got, err := resolveAccessibleLibraryPath(`/app/F:\media\电视剧\国产剧`)
if err != nil {
@@ -95,7 +95,7 @@ func TestResolveAccessibleLibraryPathMapsRelativeDockerMediaMarker(t *testing.T)
if err := os.MkdirAll(containerLibrary, 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("MEDIASTATION_MEDIA_CONTAINER_DIR", containerRoot)
t.Setenv("MMTL_MEDIA_CONTAINER_DIR", containerRoot)
got, err := resolveAccessibleLibraryPath(filepath.Join("media", "电视剧", "国产剧"))
if err != nil {
@@ -116,7 +116,7 @@ func TestResolveAccessibleLibraryPathMapsEmbeddedHostMediaMarker(t *testing.T) {
if err := os.MkdirAll(containerLibrary, 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("MEDIASTATION_MEDIA_CONTAINER_DIR", containerRoot)
t.Setenv("MMTL_MEDIA_CONTAINER_DIR", containerRoot)
got, err := resolveAccessibleLibraryPath("/vol1/1000/Docker/moviepilot-v2/media/电视剧/国产剧")
if err != nil {
@@ -134,7 +134,7 @@ func TestResolveAccessibleMappedPathMapsEmbeddedHostDownloadMarker(t *testing.T)
if err := os.MkdirAll(containerItem, 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("MEDIASTATION_DOWNLOAD_CONTAINER_DIR", containerDownloads)
t.Setenv("MMTL_DOWNLOAD_CONTAINER_DIR", containerDownloads)
got, _, err := resolveAccessibleMappedPath("/vol1/1000/Docker/qbittorrent/downloads/国产剧")
if err != nil {
@@ -180,7 +180,7 @@ func TestMappedPathCandidatesMapWindowsDriveDownloadMarker(t *testing.T) {
root := t.TempDir()
containerDownloads := filepath.Join(root, "container", "downloads")
containerLibrary := filepath.Join(containerDownloads, "国产剧")
t.Setenv("MEDIASTATION_DOWNLOAD_CONTAINER_DIR", containerDownloads)
t.Setenv("MMTL_DOWNLOAD_CONTAINER_DIR", containerDownloads)
want := filepath.Clean(containerLibrary)
for _, got := range mappedPathCandidates(`F:\downloads\国产剧`) {
@@ -197,8 +197,8 @@ func TestResolveMappedDestinationPathPrefersConfiguredContainerMapping(t *testin
if err := os.MkdirAll(containerMedia, 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("MEDIASTATION_MEDIA_DIR", `Q:\media`)
t.Setenv("MEDIASTATION_MEDIA_CONTAINER_DIR", containerMedia)
t.Setenv("MMTL_MEDIA_DIR", `Q:\media`)
t.Setenv("MMTL_MEDIA_CONTAINER_DIR", containerMedia)
for _, input := range []string{`Q:\media`, `Q:/media`, `/app/Q:\media`} {
t.Run(input, func(t *testing.T) {
@@ -221,7 +221,7 @@ func TestResolveMappedDestinationPathPrefersContainerForRelativeMediaMarker(t *t
t.Fatal(err)
}
t.Chdir(workDir)
t.Setenv("MEDIASTATION_MEDIA_CONTAINER_DIR", containerMedia)
t.Setenv("MMTL_MEDIA_CONTAINER_DIR", containerMedia)
got := resolveMappedDestinationPath(filepath.Join("media", "电视剧", "国产剧"))
want := filepath.Join(containerMedia, "电视剧", "国产剧")
@@ -237,8 +237,8 @@ func TestResolveAccessibleMappedPathMapsWindowsDownloadVariants(t *testing.T) {
if err := os.MkdirAll(containerSource, 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("MEDIASTATION_DOWNLOAD_DIR", `Q:\downloads`)
t.Setenv("MEDIASTATION_DOWNLOAD_CONTAINER_DIR", containerDownloads)
t.Setenv("MMTL_DOWNLOAD_DIR", `Q:\downloads`)
t.Setenv("MMTL_DOWNLOAD_CONTAINER_DIR", containerDownloads)
for _, input := range []string{`Q:\downloads\国产剧`, `Q:/downloads/国产剧`, `/app/Q:\downloads\国产剧`} {
t.Run(input, func(t *testing.T) {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"sort"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
type MediaItem struct {
+3 -3
View File
@@ -6,9 +6,9 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
func TestGroupMediaVersionsMergesEpisodeByExternalIDAcrossLibraries(t *testing.T) {
+3 -3
View File
@@ -5,9 +5,9 @@ import (
"slices"
"testing"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
"go.uber.org/zap"
)
+1 -1
View File
@@ -273,7 +273,7 @@ func (p *MetaTubeProvider) applyAuthHeader(req *http.Request, token string) {
req.Header.Set("X-Token", token)
}
req.Header.Set("Accept", "application/json")
req.Header.Set("User-Agent", "MediaStationGo/1.0 (MetaTube Client)")
req.Header.Set("User-Agent", "MMTL/1.0 (MetaTube Client)")
}
func (p *MetaTubeProvider) convertSearchResultToMatch(query string, res *MetaTubeSearchResult) *Match {
+2 -2
View File
@@ -22,8 +22,8 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// NFOService is the entry point used by the admin "导出 NFO" action.
+3 -3
View File
@@ -6,13 +6,13 @@ import (
"strings"
"testing"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func TestWriteMediaNFOUsesMappedDestinationPath(t *testing.T) {
root := t.TempDir()
t.Setenv("MEDIASTATION_MEDIA_DIR", root)
t.Setenv("MEDIASTATION_MEDIA_CONTAINER_DIR", "/media")
t.Setenv("MMTL_MEDIA_DIR", root)
t.Setenv("MMTL_MEDIA_CONTAINER_DIR", "/media")
mediaPath := filepath.Join(root, "电影", "测试电影.mkv")
if err := os.MkdirAll(filepath.Dir(mediaPath), 0o755); err != nil {
t.Fatal(err)
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
)
// TestOrganizeNaming locks in the rename pipeline used by OrganizeDirectory:
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/repository"
)
type OrganizeScope string
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func organizeFatalResultError(res *OrganizeResult) error {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func (p *OrganizePipelineService) syncScrapedOrganizedNames(ctx context.Context, opts OrganizeOptions, res *OrganizeResult, path string) {
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
func TestOrganizeScanRootUsesActualOrganizedTarget(t *testing.T) {
+3 -3
View File
@@ -20,9 +20,9 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MediaStationGo/internal/repository"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/ShukeBta/MMTL/internal/repository"
)
// OrganizerService moves/renames files into library structures.
@@ -11,8 +11,8 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
)
func TestOrganizeDirectoryClassifiesScraperMatchBeforeRename(t *testing.T) {
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"path/filepath"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/model"
)
// isSmartClassifyEnabled checks database settings first, then config.yaml.
@@ -7,8 +7,8 @@ import (
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/model"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
)
func TestOrganizeDirectoryUsesDownloadCategoryLayout(t *testing.T) {

Some files were not shown because too many files have changed in this diff Show More