.redownlaod with suffix, isrc variable
This commit is contained in:
+17
-9
@@ -204,7 +204,7 @@ func (a *AmazonDownloader) DownloadFromService(amazonURL, outputDir, quality str
|
||||
return a.DownloadFromAfkarXYZ(amazonURL, outputDir, quality)
|
||||
}
|
||||
|
||||
func (a *AmazonDownloader) DownloadByURL(amazonURL, outputDir, quality, filenameFormat, playlistName, playlistOwner string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL string, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, embedMaxQualityCover bool, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, spotifyURL string, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) {
|
||||
func (a *AmazonDownloader) DownloadByURL(amazonURL, outputDir, quality, filenameFormat, playlistName, playlistOwner string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL string, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, embedMaxQualityCover bool, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) {
|
||||
|
||||
if outputDir != "." {
|
||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||
@@ -219,12 +219,14 @@ func (a *AmazonDownloader) DownloadByURL(amazonURL, outputDir, quality, filename
|
||||
filenameArtist = GetFirstArtist(spotifyArtistName)
|
||||
filenameAlbumArtist = GetFirstArtist(spotifyAlbumArtist)
|
||||
}
|
||||
expectedFilename := BuildExpectedFilename(spotifyTrackName, filenameArtist, spotifyAlbumName, filenameAlbumArtist, spotifyReleaseDate, filenameFormat, playlistName, playlistOwner, includeTrackNumber, position, spotifyDiscNumber, false)
|
||||
expectedFilename := BuildExpectedFilename(spotifyTrackName, filenameArtist, spotifyAlbumName, filenameAlbumArtist, spotifyReleaseDate, filenameFormat, playlistName, playlistOwner, includeTrackNumber, position, spotifyDiscNumber, false, isrcOverride)
|
||||
expectedPath := filepath.Join(outputDir, expectedFilename)
|
||||
|
||||
if fileInfo, err := os.Stat(expectedPath); err == nil && fileInfo.Size() > 0 {
|
||||
fmt.Printf("File already exists: %s (%.2f MB)\n", expectedPath, float64(fileInfo.Size())/(1024*1024))
|
||||
return "EXISTS:" + expectedPath, nil
|
||||
if !GetRedownloadWithSuffixSetting() {
|
||||
if fileInfo, err := os.Stat(expectedPath); err == nil && fileInfo.Size() > 0 {
|
||||
fmt.Printf("File already exists: %s (%.2f MB)\n", expectedPath, float64(fileInfo.Size())/(1024*1024))
|
||||
return "EXISTS:" + expectedPath, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,11 +273,13 @@ func (a *AmazonDownloader) DownloadByURL(amazonURL, outputDir, quality, filename
|
||||
return "", err
|
||||
}
|
||||
|
||||
var isrc string
|
||||
isrc := strings.TrimSpace(isrcOverride)
|
||||
var mbMeta Metadata
|
||||
if spotifyURL != "" {
|
||||
result := <-metaChan
|
||||
isrc = result.ISRC
|
||||
if isrc == "" {
|
||||
isrc = result.ISRC
|
||||
}
|
||||
mbMeta = result.Metadata
|
||||
}
|
||||
|
||||
@@ -309,6 +313,7 @@ func (a *AmazonDownloader) DownloadByURL(amazonURL, outputDir, quality, filename
|
||||
newFilename = strings.ReplaceAll(newFilename, "{album_artist}", safeAlbumArtist)
|
||||
newFilename = strings.ReplaceAll(newFilename, "{year}", year)
|
||||
newFilename = strings.ReplaceAll(newFilename, "{date}", SanitizeFilename(spotifyReleaseDate))
|
||||
newFilename = strings.ReplaceAll(newFilename, "{isrc}", SanitizeOptionalFilename(isrc))
|
||||
|
||||
if spotifyDiscNumber > 0 {
|
||||
newFilename = strings.ReplaceAll(newFilename, "{disc}", fmt.Sprintf("%d", spotifyDiscNumber))
|
||||
@@ -346,6 +351,9 @@ func (a *AmazonDownloader) DownloadByURL(amazonURL, outputDir, quality, filename
|
||||
}
|
||||
newFilename = newFilename + ext
|
||||
newFilePath := filepath.Join(outputDir, newFilename)
|
||||
if GetRedownloadWithSuffixSetting() {
|
||||
newFilePath, _ = ResolveOutputPathForDownload(newFilePath, true)
|
||||
}
|
||||
|
||||
if err := os.Rename(filePath, newFilePath); err != nil {
|
||||
fmt.Printf("Warning: Failed to rename file: %v\n", err)
|
||||
@@ -420,7 +428,7 @@ func (a *AmazonDownloader) DownloadByURL(amazonURL, outputDir, quality, filename
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
func (a *AmazonDownloader) DownloadBySpotifyID(spotifyTrackID, outputDir, quality, filenameFormat, playlistName, playlistOwner string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL string, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, embedMaxQualityCover bool, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, spotifyURL string,
|
||||
func (a *AmazonDownloader) DownloadBySpotifyID(spotifyTrackID, outputDir, quality, filenameFormat, playlistName, playlistOwner string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL string, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, embedMaxQualityCover bool, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string,
|
||||
useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool,
|
||||
) (string, error) {
|
||||
|
||||
@@ -429,5 +437,5 @@ func (a *AmazonDownloader) DownloadBySpotifyID(spotifyTrackID, outputDir, qualit
|
||||
return "", err
|
||||
}
|
||||
|
||||
return a.DownloadByURL(amazonURL, outputDir, quality, filenameFormat, playlistName, playlistOwner, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks, embedMaxQualityCover, spotifyTotalDiscs, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, spotifyURL, useFirstArtistOnly, useSingleGenre, embedGenre)
|
||||
return a.DownloadByURL(amazonURL, outputDir, quality, filenameFormat, playlistName, playlistOwner, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, spotifyCoverURL, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks, embedMaxQualityCover, spotifyTotalDiscs, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL, useFirstArtistOnly, useSingleGenre, embedGenre)
|
||||
}
|
||||
|
||||
@@ -69,6 +69,16 @@ func GetSpotFetchAPISettings() (bool, string) {
|
||||
return true, apiURL
|
||||
}
|
||||
|
||||
func GetRedownloadWithSuffixSetting() bool {
|
||||
settings, err := LoadConfigSettings()
|
||||
if err != nil || settings == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
enabled, _ := settings["redownloadWithSuffix"].(bool)
|
||||
return enabled
|
||||
}
|
||||
|
||||
func GetLinkResolverSetting() string {
|
||||
settings, err := LoadConfigSettings()
|
||||
if err != nil || settings == nil {
|
||||
|
||||
@@ -30,6 +30,7 @@ type AudioMetadata struct {
|
||||
TrackNumber int `json:"track_number"`
|
||||
DiscNumber int `json:"disc_number"`
|
||||
Year string `json:"year"`
|
||||
ISRC string `json:"isrc"`
|
||||
}
|
||||
|
||||
type RenamePreview struct {
|
||||
@@ -175,6 +176,8 @@ func readFlacMetadata(filePath string) (*AudioMetadata, error) {
|
||||
}
|
||||
case "DATE", "YEAR":
|
||||
metadata.Year = value
|
||||
case "ISRC", "TSRC":
|
||||
metadata.ISRC = value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,6 +224,12 @@ func readMp3Metadata(filePath string) (*AudioMetadata, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if frames := tag.GetFrames("TSRC"); len(frames) > 0 {
|
||||
if textFrame, ok := frames[0].(id3v2.TextFrame); ok {
|
||||
metadata.ISRC = textFrame.Text
|
||||
}
|
||||
}
|
||||
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
@@ -301,6 +310,8 @@ func readMetadataWithFFprobe(filePath string) (*AudioMetadata, error) {
|
||||
if metadata.Year == "" || len(value) > len(metadata.Year) {
|
||||
metadata.Year = value
|
||||
}
|
||||
case "isrc", "tsrc":
|
||||
metadata.ISRC = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,6 +344,7 @@ func GenerateFilename(metadata *AudioMetadata, format string, ext string) string
|
||||
result = strings.ReplaceAll(result, "{album_artist}", sanitizeFilenameForRename(metadata.AlbumArtist))
|
||||
result = strings.ReplaceAll(result, "{year}", sanitizeFilenameForRename(year))
|
||||
result = strings.ReplaceAll(result, "{date}", sanitizeFilenameForRename(metadata.Year))
|
||||
result = strings.ReplaceAll(result, "{isrc}", sanitizeFilenameForRename(metadata.ISRC))
|
||||
|
||||
if metadata.TrackNumber > 0 {
|
||||
result = strings.ReplaceAll(result, "{track}", fmt.Sprintf("%02d", metadata.TrackNumber))
|
||||
|
||||
+52
-3
@@ -2,6 +2,7 @@ package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -9,12 +10,12 @@ import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
func BuildExpectedFilename(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat, playlistName, playlistOwner string, includeTrackNumber bool, position, discNumber int, useAlbumTrackNumber bool) string {
|
||||
|
||||
func buildFormattedFilenameBase(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat, playlistName, playlistOwner, isrc string, includeTrackNumber bool, position, discNumber int, useAlbumTrackNumber bool) string {
|
||||
safeTitle := SanitizeFilename(trackName)
|
||||
safeArtist := SanitizeFilename(artistName)
|
||||
safeAlbum := SanitizeFilename(albumName)
|
||||
safeAlbumArtist := SanitizeFilename(albumArtist)
|
||||
safeISRC := SanitizeOptionalFilename(isrc)
|
||||
|
||||
safePlaylist := SanitizeFilename(playlistName)
|
||||
safeCreator := SanitizeFilename(playlistOwner)
|
||||
@@ -36,6 +37,7 @@ func BuildExpectedFilename(trackName, artistName, albumName, albumArtist, releas
|
||||
filename = strings.ReplaceAll(filename, "{date}", SanitizeFilename(releaseDate))
|
||||
filename = strings.ReplaceAll(filename, "{playlist}", safePlaylist)
|
||||
filename = strings.ReplaceAll(filename, "{creator}", safeCreator)
|
||||
filename = strings.ReplaceAll(filename, "{isrc}", safeISRC)
|
||||
|
||||
if discNumber > 0 {
|
||||
filename = strings.ReplaceAll(filename, "{disc}", fmt.Sprintf("%d", discNumber))
|
||||
@@ -67,7 +69,47 @@ func BuildExpectedFilename(trackName, artistName, albumName, albumArtist, releas
|
||||
}
|
||||
}
|
||||
|
||||
return filename + ".flac"
|
||||
return filename
|
||||
}
|
||||
|
||||
func BuildExpectedFilename(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat, playlistName, playlistOwner string, includeTrackNumber bool, position, discNumber int, useAlbumTrackNumber bool, extra ...string) string {
|
||||
isrc := ""
|
||||
if len(extra) > 0 {
|
||||
isrc = extra[0]
|
||||
}
|
||||
|
||||
return buildFormattedFilenameBase(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat, playlistName, playlistOwner, isrc, includeTrackNumber, position, discNumber, useAlbumTrackNumber) + ".flac"
|
||||
}
|
||||
|
||||
func ResolveOutputPathForDownload(path string, redownloadWithSuffix bool) (string, bool) {
|
||||
if !redownloadWithSuffix {
|
||||
if info, err := os.Stat(path); err == nil && info.Size() > 0 {
|
||||
return path, true
|
||||
}
|
||||
return path, false
|
||||
}
|
||||
|
||||
if info, err := os.Stat(path); err != nil || info.Size() == 0 {
|
||||
return path, false
|
||||
}
|
||||
|
||||
ext := filepath.Ext(path)
|
||||
base := strings.TrimSuffix(path, ext)
|
||||
|
||||
for i := 1; ; i++ {
|
||||
candidate := fmt.Sprintf("%s_%02d%s", base, i, ext)
|
||||
if info, err := os.Stat(candidate); err != nil || info.Size() == 0 {
|
||||
return candidate, false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mustFileSize(path string) int64 {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return info.Size()
|
||||
}
|
||||
|
||||
func SanitizeFilename(name string) string {
|
||||
@@ -188,3 +230,10 @@ func sanitizeFolderName(name string) string { return SanitizeFilename(name) }
|
||||
func sanitizeFilename(name string) string {
|
||||
return SanitizeFilename(name)
|
||||
}
|
||||
|
||||
func SanitizeOptionalFilename(name string) string {
|
||||
if strings.TrimSpace(name) == "" {
|
||||
return ""
|
||||
}
|
||||
return SanitizeFilename(name)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package backend
|
||||
|
||||
import "strings"
|
||||
|
||||
func ResolveTrackISRC(spotifyTrackID string) string {
|
||||
spotifyTrackID = strings.TrimSpace(spotifyTrackID)
|
||||
if spotifyTrackID == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
if cachedISRC, err := GetCachedISRC(spotifyTrackID); err == nil && cachedISRC != "" {
|
||||
return strings.ToUpper(strings.TrimSpace(cachedISRC))
|
||||
}
|
||||
|
||||
client := NewSongLinkClient()
|
||||
isrc, err := client.GetISRCDirect(spotifyTrackID)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return strings.ToUpper(strings.TrimSpace(isrc))
|
||||
}
|
||||
+11
-3
@@ -44,6 +44,7 @@ type LyricsDownloadRequest struct {
|
||||
AlbumName string `json:"album_name"`
|
||||
AlbumArtist string `json:"album_artist"`
|
||||
ReleaseDate string `json:"release_date"`
|
||||
ISRC string `json:"isrc"`
|
||||
OutputDir string `json:"output_dir"`
|
||||
FilenameFormat string `json:"filename_format"`
|
||||
TrackNumber bool `json:"track_number"`
|
||||
@@ -363,11 +364,12 @@ func msToLRCTimestamp(msStr string) string {
|
||||
return fmt.Sprintf("[%02d:%02d.%02d]", minutes, seconds, centiseconds)
|
||||
}
|
||||
|
||||
func buildLyricsFilename(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat string, includeTrackNumber bool, position, discNumber int) string {
|
||||
func buildLyricsFilename(trackName, artistName, albumName, albumArtist, releaseDate, filenameFormat, isrc string, includeTrackNumber bool, position, discNumber int) string {
|
||||
safeTitle := sanitizeFilename(trackName)
|
||||
safeArtist := sanitizeFilename(artistName)
|
||||
safeAlbum := sanitizeFilename(albumName)
|
||||
safeAlbumArtist := sanitizeFilename(albumArtist)
|
||||
safeISRC := SanitizeOptionalFilename(isrc)
|
||||
|
||||
year := ""
|
||||
if len(releaseDate) >= 4 {
|
||||
@@ -384,6 +386,7 @@ func buildLyricsFilename(trackName, artistName, albumName, albumArtist, releaseD
|
||||
filename = strings.ReplaceAll(filename, "{album_artist}", safeAlbumArtist)
|
||||
filename = strings.ReplaceAll(filename, "{year}", year)
|
||||
filename = strings.ReplaceAll(filename, "{date}", sanitizeFilename(releaseDate))
|
||||
filename = strings.ReplaceAll(filename, "{isrc}", safeISRC)
|
||||
|
||||
if discNumber > 0 {
|
||||
filename = strings.ReplaceAll(filename, "{disc}", fmt.Sprintf("%d", discNumber))
|
||||
@@ -485,10 +488,15 @@ func (c *LyricsClient) DownloadLyrics(req LyricsDownloadRequest) (*LyricsDownloa
|
||||
if filenameFormat == "" {
|
||||
filenameFormat = "title-artist"
|
||||
}
|
||||
filename := buildLyricsFilename(req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, filenameFormat, req.TrackNumber, req.Position, req.DiscNumber)
|
||||
resolvedISRC := strings.TrimSpace(req.ISRC)
|
||||
if resolvedISRC == "" && strings.Contains(filenameFormat, "{isrc}") {
|
||||
resolvedISRC = ResolveTrackISRC(req.SpotifyID)
|
||||
}
|
||||
filename := buildLyricsFilename(req.TrackName, req.ArtistName, req.AlbumName, req.AlbumArtist, req.ReleaseDate, filenameFormat, resolvedISRC, req.TrackNumber, req.Position, req.DiscNumber)
|
||||
filePath := filepath.Join(outputDir, filename)
|
||||
|
||||
if fileInfo, err := os.Stat(filePath); err == nil && fileInfo.Size() > 0 {
|
||||
filePath, alreadyExists := ResolveOutputPathForDownload(filePath, GetRedownloadWithSuffixSetting())
|
||||
if alreadyExists {
|
||||
return &LyricsDownloadResponse{
|
||||
Success: true,
|
||||
Message: "Lyrics file already exists",
|
||||
|
||||
+10
-5
@@ -326,8 +326,12 @@ func (q *QobuzDownloader) DownloadCoverArt(coverURL, filepath string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func buildQobuzFilename(title, artist, album, albumArtist, releaseDate string, trackNumber, discNumber int, format string, includeTrackNumber bool, position int, useAlbumTrackNumber bool) string {
|
||||
func buildQobuzFilename(title, artist, album, albumArtist, releaseDate string, trackNumber, discNumber int, format string, includeTrackNumber bool, position int, useAlbumTrackNumber bool, extra ...string) string {
|
||||
var filename string
|
||||
isrc := ""
|
||||
if len(extra) > 0 {
|
||||
isrc = SanitizeOptionalFilename(extra[0])
|
||||
}
|
||||
|
||||
numberToUse := position
|
||||
if useAlbumTrackNumber && trackNumber > 0 {
|
||||
@@ -347,6 +351,7 @@ func buildQobuzFilename(title, artist, album, albumArtist, releaseDate string, t
|
||||
filename = strings.ReplaceAll(filename, "{album_artist}", albumArtist)
|
||||
filename = strings.ReplaceAll(filename, "{year}", year)
|
||||
filename = strings.ReplaceAll(filename, "{date}", SanitizeFilename(releaseDate))
|
||||
filename = strings.ReplaceAll(filename, "{isrc}", isrc)
|
||||
|
||||
if discNumber > 0 {
|
||||
filename = strings.ReplaceAll(filename, "{disc}", fmt.Sprintf("%d", discNumber))
|
||||
@@ -467,11 +472,11 @@ func (q *QobuzDownloader) DownloadTrackWithISRC(isrc, outputDir, quality, filena
|
||||
safeTitle := sanitizeFilename(trackTitle)
|
||||
safeAlbum := sanitizeFilename(albumTitle)
|
||||
|
||||
filename := buildQobuzFilename(safeTitle, safeArtist, safeAlbum, safeAlbumArtist, spotifyReleaseDate, spotifyTrackNumber, spotifyDiscNumber, filenameFormat, includeTrackNumber, position, useAlbumTrackNumber)
|
||||
filename := buildQobuzFilename(safeTitle, safeArtist, safeAlbum, safeAlbumArtist, spotifyReleaseDate, spotifyTrackNumber, spotifyDiscNumber, filenameFormat, includeTrackNumber, position, useAlbumTrackNumber, isrc)
|
||||
filepath := filepath.Join(outputDir, filename)
|
||||
|
||||
if fileInfo, err := os.Stat(filepath); err == nil && fileInfo.Size() > 0 {
|
||||
fmt.Printf("File already exists: %s (%.2f MB)\n", filepath, float64(fileInfo.Size())/(1024*1024))
|
||||
filepath, alreadyExists := ResolveOutputPathForDownload(filepath, GetRedownloadWithSuffixSetting())
|
||||
if alreadyExists {
|
||||
fmt.Printf("File already exists: %s (%.2f MB)\n", filepath, float64(mustFileSize(filepath))/(1024*1024))
|
||||
return "EXISTS:" + filepath, nil
|
||||
}
|
||||
|
||||
|
||||
+26
-15
@@ -416,7 +416,7 @@ func (t *TidalDownloader) DownloadFromManifest(manifestB64, outputPath string) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TidalDownloader) DownloadByURL(tidalURL, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) {
|
||||
func (t *TidalDownloader) DownloadByURL(tidalURL, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) {
|
||||
if outputDir != "." {
|
||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||
return "", fmt.Errorf("directory error: %w", err)
|
||||
@@ -449,11 +449,12 @@ func (t *TidalDownloader) DownloadByURL(tidalURL, outputDir, quality, filenameFo
|
||||
trackTitleForFile := sanitizeFilename(trackTitle)
|
||||
albumTitleForFile := sanitizeFilename(albumTitle)
|
||||
|
||||
filename := buildTidalFilename(trackTitleForFile, artistNameForFile, albumTitleForFile, albumArtistForFile, spotifyReleaseDate, spotifyTrackNumber, spotifyDiscNumber, filenameFormat, includeTrackNumber, position, useAlbumTrackNumber)
|
||||
filename := buildTidalFilename(trackTitleForFile, artistNameForFile, albumTitleForFile, albumArtistForFile, spotifyReleaseDate, spotifyTrackNumber, spotifyDiscNumber, filenameFormat, includeTrackNumber, position, useAlbumTrackNumber, isrcOverride)
|
||||
outputFilename := filepath.Join(outputDir, filename)
|
||||
|
||||
if fileInfo, err := os.Stat(outputFilename); err == nil && fileInfo.Size() > 0 {
|
||||
fmt.Printf("File already exists: %s (%.2f MB)\n", outputFilename, float64(fileInfo.Size())/(1024*1024))
|
||||
outputFilename, alreadyExists := ResolveOutputPathForDownload(outputFilename, GetRedownloadWithSuffixSetting())
|
||||
if alreadyExists {
|
||||
fmt.Printf("File already exists: %s (%.2f MB)\n", outputFilename, float64(mustFileSize(outputFilename))/(1024*1024))
|
||||
return "EXISTS:" + outputFilename, nil
|
||||
}
|
||||
|
||||
@@ -511,11 +512,13 @@ func (t *TidalDownloader) DownloadByURL(tidalURL, outputDir, quality, filenameFo
|
||||
return "", err
|
||||
}
|
||||
|
||||
var isrc string
|
||||
isrc := strings.TrimSpace(isrcOverride)
|
||||
var mbMeta Metadata
|
||||
if spotifyURL != "" {
|
||||
result := <-metaChan
|
||||
isrc = result.ISRC
|
||||
if isrc == "" {
|
||||
isrc = result.ISRC
|
||||
}
|
||||
mbMeta = result.Metadata
|
||||
}
|
||||
|
||||
@@ -572,7 +575,7 @@ func (t *TidalDownloader) DownloadByURL(tidalURL, outputDir, quality, filenameFo
|
||||
return outputFilename, nil
|
||||
}
|
||||
|
||||
func (t *TidalDownloader) DownloadByURLWithFallback(tidalURL, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) {
|
||||
func (t *TidalDownloader) DownloadByURLWithFallback(tidalURL, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) {
|
||||
apis, err := t.GetAvailableAPIs()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("no APIs available for fallback: %w", err)
|
||||
@@ -610,11 +613,12 @@ func (t *TidalDownloader) DownloadByURLWithFallback(tidalURL, outputDir, quality
|
||||
trackTitleForFile := sanitizeFilename(trackTitle)
|
||||
albumTitleForFile := sanitizeFilename(albumTitle)
|
||||
|
||||
filename := buildTidalFilename(trackTitleForFile, artistNameForFile, albumTitleForFile, albumArtistForFile, spotifyReleaseDate, spotifyTrackNumber, spotifyDiscNumber, filenameFormat, includeTrackNumber, position, useAlbumTrackNumber)
|
||||
filename := buildTidalFilename(trackTitleForFile, artistNameForFile, albumTitleForFile, albumArtistForFile, spotifyReleaseDate, spotifyTrackNumber, spotifyDiscNumber, filenameFormat, includeTrackNumber, position, useAlbumTrackNumber, isrcOverride)
|
||||
outputFilename := filepath.Join(outputDir, filename)
|
||||
|
||||
if fileInfo, err := os.Stat(outputFilename); err == nil && fileInfo.Size() > 0 {
|
||||
fmt.Printf("File already exists: %s (%.2f MB)\n", outputFilename, float64(fileInfo.Size())/(1024*1024))
|
||||
outputFilename, alreadyExists := ResolveOutputPathForDownload(outputFilename, GetRedownloadWithSuffixSetting())
|
||||
if alreadyExists {
|
||||
fmt.Printf("File already exists: %s (%.2f MB)\n", outputFilename, float64(mustFileSize(outputFilename))/(1024*1024))
|
||||
return "EXISTS:" + outputFilename, nil
|
||||
}
|
||||
|
||||
@@ -673,11 +677,13 @@ func (t *TidalDownloader) DownloadByURLWithFallback(tidalURL, outputDir, quality
|
||||
return "", err
|
||||
}
|
||||
|
||||
var isrc string
|
||||
isrc := strings.TrimSpace(isrcOverride)
|
||||
var mbMeta Metadata
|
||||
if spotifyURL != "" {
|
||||
result := <-metaChan
|
||||
isrc = result.ISRC
|
||||
if isrc == "" {
|
||||
isrc = result.ISRC
|
||||
}
|
||||
mbMeta = result.Metadata
|
||||
}
|
||||
|
||||
@@ -734,14 +740,14 @@ func (t *TidalDownloader) DownloadByURLWithFallback(tidalURL, outputDir, quality
|
||||
return outputFilename, nil
|
||||
}
|
||||
|
||||
func (t *TidalDownloader) Download(spotifyTrackID, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) {
|
||||
func (t *TidalDownloader) Download(spotifyTrackID, outputDir, quality, filenameFormat string, includeTrackNumber bool, position int, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate string, useAlbumTrackNumber bool, spotifyCoverURL string, embedMaxQualityCover bool, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks int, spotifyTotalDiscs int, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL string, allowFallback bool, useFirstArtistOnly bool, useSingleGenre bool, embedGenre bool) (string, error) {
|
||||
|
||||
tidalURL, err := t.GetTidalURLFromSpotify(spotifyTrackID)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("songlink couldn't find Tidal URL: %w", err)
|
||||
}
|
||||
|
||||
return t.DownloadByURLWithFallback(tidalURL, outputDir, quality, filenameFormat, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, useAlbumTrackNumber, spotifyCoverURL, embedMaxQualityCover, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks, spotifyTotalDiscs, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, spotifyURL, allowFallback, useFirstArtistOnly, useSingleGenre, embedGenre)
|
||||
return t.DownloadByURLWithFallback(tidalURL, outputDir, quality, filenameFormat, includeTrackNumber, position, spotifyTrackName, spotifyArtistName, spotifyAlbumName, spotifyAlbumArtist, spotifyReleaseDate, useAlbumTrackNumber, spotifyCoverURL, embedMaxQualityCover, spotifyTrackNumber, spotifyDiscNumber, spotifyTotalTracks, spotifyTotalDiscs, spotifyCopyright, spotifyPublisher, spotifyComposer, metadataSeparator, isrcOverride, spotifyURL, allowFallback, useFirstArtistOnly, useSingleGenre, embedGenre)
|
||||
}
|
||||
|
||||
type SegmentTemplate struct {
|
||||
@@ -981,8 +987,12 @@ func getDownloadURLRotated(apis []string, trackID int64, quality string) (string
|
||||
return "", "", fmt.Errorf("all %d APIs failed. Last error: %v", len(apis), lastError)
|
||||
}
|
||||
|
||||
func buildTidalFilename(title, artist, album, albumArtist, releaseDate string, trackNumber, discNumber int, format string, includeTrackNumber bool, position int, useAlbumTrackNumber bool) string {
|
||||
func buildTidalFilename(title, artist, album, albumArtist, releaseDate string, trackNumber, discNumber int, format string, includeTrackNumber bool, position int, useAlbumTrackNumber bool, extra ...string) string {
|
||||
var filename string
|
||||
isrc := ""
|
||||
if len(extra) > 0 {
|
||||
isrc = SanitizeOptionalFilename(extra[0])
|
||||
}
|
||||
|
||||
numberToUse := position
|
||||
if useAlbumTrackNumber && trackNumber > 0 {
|
||||
@@ -1002,6 +1012,7 @@ func buildTidalFilename(title, artist, album, albumArtist, releaseDate string, t
|
||||
filename = strings.ReplaceAll(filename, "{album_artist}", albumArtist)
|
||||
filename = strings.ReplaceAll(filename, "{year}", year)
|
||||
filename = strings.ReplaceAll(filename, "{date}", SanitizeFilename(releaseDate))
|
||||
filename = strings.ReplaceAll(filename, "{isrc}", isrc)
|
||||
|
||||
if discNumber > 0 {
|
||||
filename = strings.ReplaceAll(filename, "{disc}", fmt.Sprintf("%d", discNumber))
|
||||
|
||||
Reference in New Issue
Block a user