mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-25 02:50:43 +02:00
refactor(bridge): remove dead cross-layer platform bridge methods
This commit is contained in:
@@ -19,7 +19,6 @@ const (
|
||||
deezerTrackURL = deezerBaseURL + "/track/%s"
|
||||
deezerAlbumURL = deezerBaseURL + "/album/%s"
|
||||
deezerArtistURL = deezerBaseURL + "/artist/%s"
|
||||
deezerArtistRelatedURL = deezerBaseURL + "/artist/%s/related"
|
||||
deezerPlaylistURL = deezerBaseURL + "/playlist/%s"
|
||||
|
||||
deezerCacheTTL = 10 * time.Minute
|
||||
@@ -846,66 +845,6 @@ func (c *DeezerClient) fetchAlbumTrackCounts(ctx context.Context, albums []Artis
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (c *DeezerClient) GetRelatedArtists(ctx context.Context, artistID string, limit int) ([]SearchArtistResult, error) {
|
||||
normalizedArtistID := strings.TrimSpace(strings.TrimPrefix(artistID, "deezer:"))
|
||||
if normalizedArtistID == "" {
|
||||
return nil, fmt.Errorf("invalid Deezer artist ID")
|
||||
}
|
||||
|
||||
effectiveLimit := limit
|
||||
if effectiveLimit <= 0 {
|
||||
effectiveLimit = 12
|
||||
}
|
||||
|
||||
relatedURL := fmt.Sprintf("%s?limit=%d", fmt.Sprintf(deezerArtistRelatedURL, normalizedArtistID), effectiveLimit)
|
||||
var relatedResp struct {
|
||||
Data []struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Picture string `json:"picture"`
|
||||
PictureMedium string `json:"picture_medium"`
|
||||
PictureBig string `json:"picture_big"`
|
||||
PictureXL string `json:"picture_xl"`
|
||||
NbFan int `json:"nb_fan"`
|
||||
} `json:"data"`
|
||||
Error *struct {
|
||||
Type string `json:"type"`
|
||||
Message string `json:"message"`
|
||||
Code int `json:"code"`
|
||||
} `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
if err := c.getJSON(ctx, relatedURL, &relatedResp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if relatedResp.Error != nil {
|
||||
return nil, fmt.Errorf("deezer related artists error: %s", relatedResp.Error.Message)
|
||||
}
|
||||
|
||||
result := make([]SearchArtistResult, 0, len(relatedResp.Data))
|
||||
for _, artist := range relatedResp.Data {
|
||||
imageURL := artist.PictureXL
|
||||
if imageURL == "" {
|
||||
imageURL = artist.PictureBig
|
||||
}
|
||||
if imageURL == "" {
|
||||
imageURL = artist.PictureMedium
|
||||
}
|
||||
if imageURL == "" {
|
||||
imageURL = artist.Picture
|
||||
}
|
||||
|
||||
result = append(result, SearchArtistResult{
|
||||
ID: fmt.Sprintf("deezer:%d", artist.ID),
|
||||
Name: artist.Name,
|
||||
Images: imageURL,
|
||||
Followers: artist.NbFan,
|
||||
Popularity: 0,
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *DeezerClient) GetPlaylist(ctx context.Context, playlistID string) (*PlaylistResponsePayload, error) {
|
||||
playlistURL := fmt.Sprintf(deezerPlaylistURL, playlistID)
|
||||
|
||||
|
||||
@@ -78,17 +78,6 @@ func TestDeezerClientWithFakeHTTP(t *testing.T) {
|
||||
t.Fatalf("cached artist = %#v/%v", cachedArtist, err)
|
||||
}
|
||||
|
||||
related, err := client.GetRelatedArtists(ctx, "deezer:301", 3)
|
||||
if err != nil {
|
||||
t.Fatalf("GetRelatedArtists: %v", err)
|
||||
}
|
||||
if len(related) != 1 || related[0].ID != "deezer:302" {
|
||||
t.Fatalf("related = %#v", related)
|
||||
}
|
||||
if _, err := client.GetRelatedArtists(ctx, "", 0); err == nil {
|
||||
t.Fatal("expected invalid related artist ID")
|
||||
}
|
||||
|
||||
playlist, err := client.GetPlaylist(ctx, "401")
|
||||
if err != nil {
|
||||
t.Fatalf("GetPlaylist: %v", err)
|
||||
|
||||
+10
-11
@@ -63,6 +63,16 @@ func SetSongLinkNetworkOptions(allowHTTP, insecureTLS bool) {
|
||||
SetNetworkCompatibilityOptions(allowHTTP, insecureTLS)
|
||||
}
|
||||
|
||||
// GetTrackPlatformLinksJSON returns {"platforms": {platformID: url}} for a
|
||||
// track, resolved via song.link (memory-cached; either ID may be empty).
|
||||
func GetTrackPlatformLinksJSON(spotifyTrackID string, isrc string) (string, error) {
|
||||
links, err := NewSongLinkClient().GetTrackPlatformLinks(spotifyTrackID, isrc)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return marshalJSONString(map[string]any{"platforms": links})
|
||||
}
|
||||
|
||||
func SetDownloadDirectory(path string) error {
|
||||
return setDownloadDir(path)
|
||||
}
|
||||
@@ -74,17 +84,6 @@ func AllowDownloadDir(path string) {
|
||||
AddAllowedDownloadDir(path)
|
||||
}
|
||||
|
||||
func CheckDuplicate(outputDir, isrc string) (string, error) {
|
||||
existingFile, exists := CheckISRCExists(outputDir, isrc)
|
||||
|
||||
result := map[string]any{
|
||||
"exists": exists,
|
||||
"filepath": existingFile,
|
||||
}
|
||||
|
||||
return marshalJSONString(result)
|
||||
}
|
||||
|
||||
func CheckDuplicatesBatch(outputDir, tracksJSON string) (string, error) {
|
||||
return CheckFilesExistParallel(outputDir, tracksJSON)
|
||||
}
|
||||
|
||||
@@ -17,22 +17,6 @@ func GetTrackCacheSize() int {
|
||||
func ClearTrackIDCache() {
|
||||
}
|
||||
|
||||
func GetDeezerRelatedArtists(artistID string, limit int) (string, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
defer cancel()
|
||||
|
||||
client := GetDeezerClient()
|
||||
artists, err := client.GetRelatedArtists(ctx, artistID, limit)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resp := map[string]any{
|
||||
"artists": artists,
|
||||
}
|
||||
return marshalJSONString(resp)
|
||||
}
|
||||
|
||||
func GetDeezerMetadata(resourceType, resourceID string) (string, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -383,12 +383,6 @@ func DownloadByStrategy(requestJSON string) (string, error) {
|
||||
return errorResponse("Extension providers are disabled; built-in download providers have been retired")
|
||||
}
|
||||
|
||||
func GetDownloadProgress() string {
|
||||
progress := getProgress()
|
||||
jsonBytes, _ := json.Marshal(progress)
|
||||
return string(jsonBytes)
|
||||
}
|
||||
|
||||
func GetAllDownloadProgress() string {
|
||||
return GetMultiProgress()
|
||||
}
|
||||
@@ -401,10 +395,6 @@ func InitItemProgress(itemID string) {
|
||||
StartItemProgress(itemID)
|
||||
}
|
||||
|
||||
func FinishItemProgress(itemID string) {
|
||||
CompleteItemProgress(itemID)
|
||||
}
|
||||
|
||||
func ClearItemProgress(itemID string) {
|
||||
RemoveItemProgress(itemID)
|
||||
}
|
||||
|
||||
@@ -432,16 +432,6 @@ func SetExtensionSettingsJSON(extensionID, settingsJSON string) error {
|
||||
return manager.InitializeExtension(extensionID, settings)
|
||||
}
|
||||
|
||||
func SearchTracksWithExtensionsJSON(query string, limit int) (string, error) {
|
||||
manager := getExtensionManager()
|
||||
tracks, err := manager.SearchTracksWithExtensions(query, limit)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return marshalJSONString(tracks)
|
||||
}
|
||||
|
||||
func SearchTracksWithMetadataProvidersJSON(query string, limit int, includeExtensions bool) (string, error) {
|
||||
manager := getExtensionManager()
|
||||
tracks, err := manager.SearchTracksWithMetadataProviders(query, limit, includeExtensions)
|
||||
@@ -821,24 +811,6 @@ func CustomSearchWithExtensionJSONWithRequestID(extensionID, query string, optio
|
||||
return marshalJSONString(result)
|
||||
}
|
||||
|
||||
func GetSearchProvidersJSON() (string, error) {
|
||||
manager := getExtensionManager()
|
||||
providers := manager.GetSearchProviders()
|
||||
|
||||
result := make([]map[string]any, 0, len(providers))
|
||||
for _, p := range providers {
|
||||
result = append(result, map[string]any{
|
||||
"id": p.extension.ID,
|
||||
"display_name": p.extension.Manifest.DisplayName,
|
||||
"placeholder": p.extension.Manifest.SearchBehavior.Placeholder,
|
||||
"primary": p.extension.Manifest.SearchBehavior.Primary,
|
||||
"icon": p.extension.Manifest.SearchBehavior.Icon,
|
||||
})
|
||||
}
|
||||
|
||||
return marshalJSONString(result)
|
||||
}
|
||||
|
||||
func HandleURLWithExtensionJSON(url string) (string, error) {
|
||||
manager := getExtensionManager()
|
||||
resultWithID, err := manager.HandleURLWithExtension(url)
|
||||
@@ -1025,39 +997,6 @@ func FindURLHandlerJSON(url string) string {
|
||||
return handler.extension.ID
|
||||
}
|
||||
|
||||
func GetURLHandlersJSON() (string, error) {
|
||||
manager := getExtensionManager()
|
||||
handlers := manager.GetURLHandlers()
|
||||
|
||||
result := make([]map[string]any, 0, len(handlers))
|
||||
for _, h := range handlers {
|
||||
result = append(result, map[string]any{
|
||||
"id": h.extension.ID,
|
||||
"display_name": h.extension.Manifest.DisplayName,
|
||||
"patterns": h.extension.Manifest.URLHandler.Patterns,
|
||||
})
|
||||
}
|
||||
|
||||
return marshalJSONString(result)
|
||||
}
|
||||
|
||||
func RunPostProcessingJSON(filePath, metadataJSON string) (string, error) {
|
||||
var metadata map[string]any
|
||||
if metadataJSON != "" {
|
||||
if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil {
|
||||
metadata = make(map[string]any)
|
||||
}
|
||||
}
|
||||
|
||||
manager := getExtensionManager()
|
||||
result, err := manager.RunPostProcessing(filePath, metadata)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return marshalJSONString(result)
|
||||
}
|
||||
|
||||
func RunPostProcessingV2JSON(inputJSON, metadataJSON string) (string, error) {
|
||||
var metadata map[string]any
|
||||
if metadataJSON != "" {
|
||||
@@ -1082,33 +1021,6 @@ func RunPostProcessingV2JSON(inputJSON, metadataJSON string) (string, error) {
|
||||
return marshalJSONString(result)
|
||||
}
|
||||
|
||||
func GetPostProcessingProvidersJSON() (string, error) {
|
||||
manager := getExtensionManager()
|
||||
providers := manager.GetPostProcessingProviders()
|
||||
|
||||
result := make([]map[string]any, 0, len(providers))
|
||||
for _, p := range providers {
|
||||
hooks := make([]map[string]any, 0)
|
||||
for _, h := range p.extension.Manifest.GetPostProcessingHooks() {
|
||||
hooks = append(hooks, map[string]any{
|
||||
"id": h.ID,
|
||||
"name": h.Name,
|
||||
"description": h.Description,
|
||||
"default_enabled": h.DefaultEnabled,
|
||||
"supported_formats": h.SupportedFormats,
|
||||
})
|
||||
}
|
||||
|
||||
result = append(result, map[string]any{
|
||||
"id": p.extension.ID,
|
||||
"display_name": p.extension.Manifest.DisplayName,
|
||||
"hooks": hooks,
|
||||
})
|
||||
}
|
||||
|
||||
return marshalJSONString(result)
|
||||
}
|
||||
|
||||
func callExtensionFunctionJSON(extensionID, functionName string, timeout time.Duration) (string, error) {
|
||||
return callExtensionFunctionJSONWithRequestID(extensionID, functionName, timeout, "")
|
||||
}
|
||||
@@ -1187,10 +1099,6 @@ func GetExtensionHomeFeedJSONWithRequestID(extensionID, requestID string) (strin
|
||||
return callExtensionFunctionJSONWithRequestID(extensionID, "getHomeFeed", 60*time.Second, requestID)
|
||||
}
|
||||
|
||||
func GetExtensionBrowseCategoriesJSON(extensionID string) (string, error) {
|
||||
return callExtensionFunctionJSON(extensionID, "getBrowseCategories", 30*time.Second)
|
||||
}
|
||||
|
||||
func CancelExtensionRequestJSON(requestID string) {
|
||||
cancelExtensionRequest(requestID)
|
||||
}
|
||||
|
||||
@@ -7,25 +7,6 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func FetchLyrics(spotifyID, trackName, artistName string, durationMs int64) (string, error) {
|
||||
client := NewLyricsClient()
|
||||
durationSec := float64(durationMs) / 1000.0
|
||||
lyrics, err := client.FetchLyricsAllSources(spotifyID, trackName, artistName, durationSec)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result := map[string]any{
|
||||
"success": true,
|
||||
"source": lyrics.Source,
|
||||
"sync_type": lyrics.SyncType,
|
||||
"lines": lyrics.Lines,
|
||||
"instrumental": lyrics.Instrumental,
|
||||
}
|
||||
|
||||
return marshalJSONString(result)
|
||||
}
|
||||
|
||||
func GetLyricsLRC(spotifyID, trackName, artistName string, filePath string, durationMs int64) (string, error) {
|
||||
if filePath != "" {
|
||||
lyrics, err := ExtractLyrics(filePath)
|
||||
|
||||
@@ -20,9 +20,6 @@ func TestLyricsExportWrappersWithoutNetwork(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if jsonText, err := FetchLyrics("spotify-1", "Song Instrumental", "Artist", 180000); err != nil || !strings.Contains(jsonText, `"instrumental":true`) {
|
||||
t.Fatalf("FetchLyrics instrumental = %q/%v", jsonText, err)
|
||||
}
|
||||
if lrc, err := GetLyricsLRC("spotify-1", "Song Instrumental", "Artist", "", 180000); err != nil || lrc != "[instrumental:true]" {
|
||||
t.Fatalf("GetLyricsLRC instrumental = %q/%v", lrc, err)
|
||||
}
|
||||
@@ -112,6 +109,19 @@ func TestSongLinkExportWrappersWithFakeClient(t *testing.T) {
|
||||
t.Fatal("songLinkExtractDeezerTrackID mismatch")
|
||||
}
|
||||
|
||||
if linksJSON, err := GetTrackPlatformLinksJSON("spotify-1", ""); err != nil ||
|
||||
!strings.Contains(linksJSON, `"tidal":"https://listen.tidal.com/track/202"`) ||
|
||||
!strings.Contains(linksJSON, `"spotify":`) {
|
||||
t.Fatalf("GetTrackPlatformLinksJSON = %q/%v", linksJSON, err)
|
||||
}
|
||||
// Second call must come from the links cache, not a new request.
|
||||
if cached, hit, cachedErr := trackPlatformLinksCacheLookup(GetSongLinkRegion() + "|spotify:spotify-1"); !hit || cachedErr || cached["tidal"] == "" {
|
||||
t.Fatalf("trackPlatformLinksCacheLookup = %#v hit=%v err=%v", cached, hit, cachedErr)
|
||||
}
|
||||
if _, err := GetTrackPlatformLinksJSON("", ""); err == nil {
|
||||
t.Fatal("GetTrackPlatformLinksJSON with empty IDs should error")
|
||||
}
|
||||
|
||||
deezerClient = &DeezerClient{
|
||||
httpClient: &http.Client{Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) {
|
||||
body := fakeDeezerResponse(req.URL.Path, req.URL.RawQuery)
|
||||
|
||||
@@ -134,10 +134,9 @@ func TestExportsJSONWrappersAndExtensionManagerSurface(t *testing.T) {
|
||||
}
|
||||
|
||||
InitItemProgress("item-1")
|
||||
FinishItemProgress("item-1")
|
||||
ClearItemProgress("item-1")
|
||||
CancelDownload("item-1")
|
||||
if GetDownloadProgress() == "" || GetAllDownloadProgress() == "" || GetAllDownloadProgressDelta(0) == "" {
|
||||
if GetAllDownloadProgress() == "" || GetAllDownloadProgressDelta(0) == "" {
|
||||
t.Fatal("expected progress JSON")
|
||||
}
|
||||
CleanupConnections()
|
||||
@@ -194,9 +193,6 @@ func TestExportsJSONWrappersAndExtensionManagerSurface(t *testing.T) {
|
||||
if err := SetDownloadDirectory(dir); err != nil {
|
||||
t.Fatalf("SetDownloadDirectory: %v", err)
|
||||
}
|
||||
if duplicateJSON, err := CheckDuplicate(dir, ""); err != nil || !strings.Contains(duplicateJSON, "exists") {
|
||||
t.Fatalf("CheckDuplicate = %q/%v", duplicateJSON, err)
|
||||
}
|
||||
if batchJSON, err := CheckDuplicatesBatch(dir, `[{"isrc":"","track_name":"Song","artist_name":"Artist"}]`); err != nil || !strings.Contains(batchJSON, "Song") {
|
||||
t.Fatalf("CheckDuplicatesBatch = %q/%v", batchJSON, err)
|
||||
}
|
||||
@@ -262,9 +258,6 @@ func TestExportsJSONWrappersAndExtensionManagerSurface(t *testing.T) {
|
||||
t.Fatal("expected settings JSON error")
|
||||
}
|
||||
|
||||
if jsonText, err := SearchTracksWithExtensionsJSON("song", 5); err != nil || !strings.Contains(jsonText, "search-1") {
|
||||
t.Fatalf("SearchTracksWithExtensionsJSON = %q/%v", jsonText, err)
|
||||
}
|
||||
if jsonText, err := SearchTracksWithMetadataProvidersJSON("song", 5, true); err != nil || !strings.Contains(jsonText, "search-1") {
|
||||
t.Fatalf("SearchTracksWithMetadataProvidersJSON = %q/%v", jsonText, err)
|
||||
}
|
||||
@@ -362,9 +355,6 @@ func TestExportsJSONWrappersAndExtensionManagerSurface(t *testing.T) {
|
||||
if _, err := GetDeezerMetadata("bad", "1"); err == nil {
|
||||
t.Fatal("expected unsupported Deezer metadata type")
|
||||
}
|
||||
if jsonText, err := GetDeezerRelatedArtists("301", 2); err != nil || !strings.Contains(jsonText, "Related") {
|
||||
t.Fatalf("GetDeezerRelatedArtists = %q/%v", jsonText, err)
|
||||
}
|
||||
if jsonText, err := GetDeezerExtendedMetadata("101"); err != nil || !strings.Contains(jsonText, "Label") {
|
||||
t.Fatalf("GetDeezerExtendedMetadata = %q/%v", jsonText, err)
|
||||
}
|
||||
@@ -385,37 +375,22 @@ func TestExportsJSONWrappersAndExtensionManagerSurface(t *testing.T) {
|
||||
if customJSON, err := CustomSearchWithExtensionJSONWithRequestID(ext.ID, "needle", `not-json`, "req-custom"); err != nil || !strings.Contains(customJSON, "custom-1") {
|
||||
t.Fatalf("CustomSearchWithExtensionJSONWithRequestID = %q/%v", customJSON, err)
|
||||
}
|
||||
if providersJSON, err := GetSearchProvidersJSON(); err != nil || !strings.Contains(providersJSON, "coverage-ext") {
|
||||
t.Fatalf("GetSearchProvidersJSON = %q/%v", providersJSON, err)
|
||||
}
|
||||
if found := FindURLHandlerJSON("https://example.test/track/1"); found != ext.ID {
|
||||
t.Fatalf("FindURLHandlerJSON = %q", found)
|
||||
}
|
||||
if handlersJSON, err := GetURLHandlersJSON(); err != nil || !strings.Contains(handlersJSON, "coverage-ext") {
|
||||
t.Fatalf("GetURLHandlersJSON = %q/%v", handlersJSON, err)
|
||||
}
|
||||
if handledJSON, err := HandleURLWithExtensionJSON("https://example.test/track/1"); err != nil || !strings.Contains(handledJSON, "url-track") {
|
||||
t.Fatalf("HandleURLWithExtensionJSON = %q/%v", handledJSON, err)
|
||||
}
|
||||
if postJSON, err := RunPostProcessingJSON(filepath.Join(dir, "song.flac"), `{"title":"Song"}`); err != nil || !strings.Contains(postJSON, "success") {
|
||||
t.Fatalf("RunPostProcessingJSON = %q/%v", postJSON, err)
|
||||
}
|
||||
v2Input := `{"path":"` + escapeJSONPath(filepath.Join(dir, "song.flac")) + `","uri":"content://song","name":"song.flac","mime_type":"audio/flac","size":10}`
|
||||
if postJSON, err := RunPostProcessingV2JSON(v2Input, `not-json`); err != nil || !strings.Contains(postJSON, "success") {
|
||||
t.Fatalf("RunPostProcessingV2JSON = %q/%v", postJSON, err)
|
||||
}
|
||||
if postProviders, err := GetPostProcessingProvidersJSON(); err != nil || !strings.Contains(postProviders, "hook") {
|
||||
t.Fatalf("GetPostProcessingProvidersJSON = %q/%v", postProviders, err)
|
||||
}
|
||||
if feedJSON, err := GetExtensionHomeFeedJSON(ext.ID); err != nil || !strings.Contains(feedJSON, "home-1") {
|
||||
t.Fatalf("GetExtensionHomeFeedJSON = %q/%v", feedJSON, err)
|
||||
}
|
||||
if feedJSON, err := GetExtensionHomeFeedJSONWithRequestID(ext.ID, "req-home"); err != nil || !strings.Contains(feedJSON, "home-1") {
|
||||
t.Fatalf("GetExtensionHomeFeedJSONWithRequestID = %q/%v", feedJSON, err)
|
||||
}
|
||||
if categoriesJSON, err := GetExtensionBrowseCategoriesJSON(ext.ID); err != nil || !strings.Contains(categoriesJSON, "cat-1") {
|
||||
t.Fatalf("GetExtensionBrowseCategoriesJSON = %q/%v", categoriesJSON, err)
|
||||
}
|
||||
CancelExtensionRequestJSON("req-home")
|
||||
|
||||
storeDir := filepath.Join(dir, "store")
|
||||
|
||||
@@ -92,9 +92,9 @@ func TestExtensionProviderWrapperFullSurface(t *testing.T) {
|
||||
t.Fatalf("url result = %#v", urlResult)
|
||||
}
|
||||
|
||||
post, err := provider.PostProcess(filepath.Join(t.TempDir(), "song.flac"), map[string]any{"title": "Song"}, "hook")
|
||||
post, err := provider.PostProcessV2(PostProcessInput{Path: filepath.Join(t.TempDir(), "song.flac")}, map[string]any{"title": "Song"}, "hook")
|
||||
if err != nil {
|
||||
t.Fatalf("PostProcess: %v", err)
|
||||
t.Fatalf("PostProcessV2: %v", err)
|
||||
}
|
||||
if !post.Success || post.BitDepth != 24 || post.SampleRate != 96000 {
|
||||
t.Fatalf("post = %#v", post)
|
||||
|
||||
@@ -847,11 +847,9 @@ func postProcessInputMap(input PostProcessInput) map[string]any {
|
||||
|
||||
const PostProcessTimeout = 2 * time.Minute
|
||||
|
||||
// postProcessCommon backs both PostProcess (V1) and PostProcessV2. V1 probes
|
||||
// only extension.postProcess (its original contract: V2-only extensions are
|
||||
// not invoked via V1); V2 probes postProcessV2 first, then falls back to
|
||||
// postProcess.
|
||||
func (p *extensionProviderWrapper) postProcessCommon(input PostProcessInput, metadata map[string]any, hookID string, preferV2 bool) (*PostProcessResult, error) {
|
||||
// PostProcessV2 probes extension.postProcessV2 first, then falls back to the
|
||||
// legacy extension.postProcess contract.
|
||||
func (p *extensionProviderWrapper) PostProcessV2(input PostProcessInput, metadata map[string]any, hookID string) (*PostProcessResult, error) {
|
||||
if !p.extension.Manifest.HasPostProcessing() {
|
||||
return nil, fmt.Errorf("extension '%s' does not support post-processing", p.extension.ID)
|
||||
}
|
||||
@@ -861,19 +859,13 @@ func (p *extensionProviderWrapper) postProcessCommon(input PostProcessInput, met
|
||||
|
||||
filePath := input.Path
|
||||
|
||||
perfName := "postProcess"
|
||||
var invoke func(*goja.Runtime) (goja.Value, error)
|
||||
if preferV2 {
|
||||
perfName = "postProcessV2"
|
||||
inputMap := postProcessInputMap(input)
|
||||
invoke = func(vm *goja.Runtime) (goja.Value, error) {
|
||||
if hasExtensionMethod(vm, "postProcessV2") {
|
||||
return invokeExtensionMethod(vm, "postProcessV2", inputMap, metadata, hookID)
|
||||
}
|
||||
return invokeExtensionMethod(vm, "postProcess", filePath, metadata, hookID)
|
||||
perfName := "postProcessV2"
|
||||
inputMap := postProcessInputMap(input)
|
||||
invoke := func(vm *goja.Runtime) (goja.Value, error) {
|
||||
if hasExtensionMethod(vm, "postProcessV2") {
|
||||
return invokeExtensionMethod(vm, "postProcessV2", inputMap, metadata, hookID)
|
||||
}
|
||||
} else {
|
||||
invoke = extensionMethodInvocation("postProcess", filePath, metadata, hookID)
|
||||
return invokeExtensionMethod(vm, "postProcess", filePath, metadata, hookID)
|
||||
}
|
||||
|
||||
result, err := callExtension(p, extCallOpts{
|
||||
@@ -898,14 +890,6 @@ func (p *extensionProviderWrapper) postProcessCommon(input PostProcessInput, met
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (p *extensionProviderWrapper) PostProcess(filePath string, metadata map[string]any, hookID string) (*PostProcessResult, error) {
|
||||
return p.postProcessCommon(PostProcessInput{Path: filePath}, metadata, hookID, false)
|
||||
}
|
||||
|
||||
func (p *extensionProviderWrapper) PostProcessV2(input PostProcessInput, metadata map[string]any, hookID string) (*PostProcessResult, error) {
|
||||
return p.postProcessCommon(input, metadata, hookID, true)
|
||||
}
|
||||
|
||||
type ExtLyricsResult struct {
|
||||
Lines []ExtLyricsLine `json:"lines"`
|
||||
SyncType string `json:"syncType"`
|
||||
|
||||
@@ -34,49 +34,6 @@ func (m *extensionManager) GetDownloadProviders() []*extensionProviderWrapper {
|
||||
return providers
|
||||
}
|
||||
|
||||
func (m *extensionManager) SearchTracksWithExtensions(query string, limit int) ([]ExtTrackMetadata, error) {
|
||||
providers := m.GetMetadataProviders()
|
||||
if len(providers) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
providerByID := make(map[string]*extensionProviderWrapper, len(providers))
|
||||
orderedProviders := make([]*extensionProviderWrapper, 0, len(providers))
|
||||
for _, provider := range providers {
|
||||
providerByID[provider.extension.ID] = provider
|
||||
}
|
||||
for _, providerID := range GetMetadataProviderPriority() {
|
||||
if provider := providerByID[providerID]; provider != nil {
|
||||
orderedProviders = append(orderedProviders, provider)
|
||||
delete(providerByID, providerID)
|
||||
}
|
||||
}
|
||||
if len(providerByID) > 0 {
|
||||
remainingIDs := make([]string, 0, len(providerByID))
|
||||
for providerID := range providerByID {
|
||||
remainingIDs = append(remainingIDs, providerID)
|
||||
}
|
||||
sort.Strings(remainingIDs)
|
||||
for _, providerID := range remainingIDs {
|
||||
orderedProviders = append(orderedProviders, providerByID[providerID])
|
||||
}
|
||||
}
|
||||
|
||||
var allTracks []ExtTrackMetadata
|
||||
for _, provider := range orderedProviders {
|
||||
result, err := provider.SearchTracks(query, limit)
|
||||
if err != nil {
|
||||
GoLog("[Extension] Search error from %s: %v\n", provider.extension.ID, err)
|
||||
continue
|
||||
}
|
||||
if result != nil {
|
||||
allTracks = append(allTracks, result.Tracks...)
|
||||
}
|
||||
}
|
||||
|
||||
return allTracks, nil
|
||||
}
|
||||
|
||||
func metadataTrackDedupKey(track ExtTrackMetadata) string {
|
||||
if isrc := strings.TrimSpace(track.ISRC); isrc != "" {
|
||||
return "isrc:" + strings.ToUpper(isrc)
|
||||
@@ -176,32 +133,6 @@ func (m *extensionManager) SearchTracksWithMetadataProvidersForItemID(query stri
|
||||
return tracks, nil
|
||||
}
|
||||
|
||||
func (m *extensionManager) GetSearchProviders() []*extensionProviderWrapper {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
|
||||
var providers []*extensionProviderWrapper
|
||||
for _, ext := range m.extensions {
|
||||
if ext.Enabled && ext.Manifest.HasCustomSearch() && ext.Error == "" {
|
||||
providers = append(providers, newExtensionProviderWrapper(ext))
|
||||
}
|
||||
}
|
||||
return providers
|
||||
}
|
||||
|
||||
func (m *extensionManager) GetURLHandlers() []*extensionProviderWrapper {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
|
||||
var providers []*extensionProviderWrapper
|
||||
for _, ext := range m.extensions {
|
||||
if ext.Enabled && ext.Manifest.HasURLHandler() && ext.Error == "" {
|
||||
providers = append(providers, newExtensionProviderWrapper(ext))
|
||||
}
|
||||
}
|
||||
return providers
|
||||
}
|
||||
|
||||
func (m *extensionManager) FindURLHandler(url string) *extensionProviderWrapper {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
@@ -252,21 +183,13 @@ func (m *extensionManager) GetPostProcessingProviders() []*extensionProviderWrap
|
||||
return providers
|
||||
}
|
||||
|
||||
// runPostProcessingCommon backs both RunPostProcessing (V1) and
|
||||
// RunPostProcessingV2. V1 delegates into this shared loop with an equivalent
|
||||
// PostProcessInput; preferV2 controls whether each hook is invoked via
|
||||
// provider.PostProcessV2 or provider.PostProcess, so V1 keeps calling
|
||||
// PostProcess (not PostProcessV2) exactly as it did before.
|
||||
func (m *extensionManager) runPostProcessingCommon(input PostProcessInput, metadata map[string]any, preferV2 bool) (*PostProcessResult, error) {
|
||||
func (m *extensionManager) RunPostProcessingV2(input PostProcessInput, metadata map[string]any) (*PostProcessResult, error) {
|
||||
providers := m.GetPostProcessingProviders()
|
||||
if len(providers) == 0 {
|
||||
return &PostProcessResult{Success: true, NewFilePath: input.Path, NewFileURI: input.URI}, nil
|
||||
}
|
||||
|
||||
logTag := "[PostProcess]"
|
||||
if preferV2 {
|
||||
logTag = "[PostProcessV2]"
|
||||
}
|
||||
logTag := "[PostProcessV2]"
|
||||
|
||||
currentInput := input
|
||||
for _, provider := range providers {
|
||||
@@ -295,13 +218,7 @@ func (m *extensionManager) runPostProcessingCommon(input PostProcessInput, metad
|
||||
|
||||
GoLog("%s Running hook %s from %s on %s\n", logTag, hook.ID, provider.extension.ID, currentInput.Path)
|
||||
|
||||
var result *PostProcessResult
|
||||
var err error
|
||||
if preferV2 {
|
||||
result, err = provider.PostProcessV2(currentInput, metadata, hook.ID)
|
||||
} else {
|
||||
result, err = provider.PostProcess(currentInput.Path, metadata, hook.ID)
|
||||
}
|
||||
result, err := provider.PostProcessV2(currentInput, metadata, hook.ID)
|
||||
if err != nil {
|
||||
GoLog("%s Hook %s failed: %v\n", logTag, hook.ID, err)
|
||||
continue
|
||||
@@ -360,18 +277,6 @@ func validatePostProcessResult(ext *loadedExtension, input PostProcessInput, res
|
||||
return fmt.Errorf("replacement file path is outside allowed directories")
|
||||
}
|
||||
|
||||
func (m *extensionManager) RunPostProcessing(filePath string, metadata map[string]any) (*PostProcessResult, error) {
|
||||
result, err := m.runPostProcessingCommon(PostProcessInput{Path: filePath}, metadata, false)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return &PostProcessResult{Success: result.Success, NewFilePath: result.NewFilePath}, nil
|
||||
}
|
||||
|
||||
func (m *extensionManager) RunPostProcessingV2(input PostProcessInput, metadata map[string]any) (*PostProcessResult, error) {
|
||||
return m.runPostProcessingCommon(input, metadata, true)
|
||||
}
|
||||
|
||||
func (m *extensionManager) GetLyricsProviders() []*extensionProviderWrapper {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
|
||||
@@ -108,25 +108,6 @@ func markMultiProgressDirtyIfChangedLocked(item *ItemProgress, before progressBr
|
||||
}
|
||||
}
|
||||
|
||||
func getProgress() DownloadProgress {
|
||||
multiMu.RLock()
|
||||
defer multiMu.RUnlock()
|
||||
|
||||
for _, item := range multiProgress.Items {
|
||||
return DownloadProgress{
|
||||
CurrentFile: item.ItemID,
|
||||
Progress: item.Progress * 100,
|
||||
BytesTotal: item.BytesTotal,
|
||||
BytesReceived: item.BytesReceived,
|
||||
IsDownloading: item.IsDownloading,
|
||||
Status: item.Status,
|
||||
Stage: item.Stage,
|
||||
}
|
||||
}
|
||||
|
||||
return DownloadProgress{}
|
||||
}
|
||||
|
||||
func GetMultiProgress() string {
|
||||
multiMu.RLock()
|
||||
if !multiProgressDirty {
|
||||
|
||||
Reference in New Issue
Block a user