diff --git a/config.yaml b/config.yaml index 35ba6a3..f5302e8 100644 --- a/config.yaml +++ b/config.yaml @@ -14,3 +14,9 @@ atmos-max: 2768 #2768 2448 #{AlbumId} {AlbumName} {ArtistName} {ReleaseDate} {UPC} {Copyright} #example: {ReleaseDate} - {ArtistName} - {AlbumName}({AlbumId}) album-folder-format: "{AlbumName}" +#{SongNumer} {SongName} {DiscNumber} {TrackNumber} +#example: Disk {DiscNumber} - Track {TrackNumber} {SongName}" +song-file-format: "{SongNumer}. {SongName}" +explicit-choice : "[E]" +clean-choice : "[C]" +apple-master-choice : "[M]" diff --git a/main.go b/main.go index 7370208..7e67990 100644 --- a/main.go +++ b/main.go @@ -46,6 +46,10 @@ type Config struct { AlacSaveFolder string `yaml:"alac-save-folder"` AtmosSaveFolder string `yaml:"atmos-save-folder"` AlbumFolderFormat string `yaml:"album-folder-format"` + SongFileFormat string `yaml:"song-file-format"` + ExplicitChoice string `yaml:"explicit-choice"` + CleanChoice string `yaml:"clean-choice"` + AppleMasterChoice string `yaml:"apple-master-choice"` ForceApi bool `yaml:"force-api"` Check string `yaml:"check"` GetM3u8FromDevice bool `yaml:"get-m3u8-from-device"` @@ -1172,6 +1176,21 @@ func rip(albumId string, token string, storefront string, userToken string) erro "{Copyright}", meta.Data[0].Attributes.Copyright, "{AlbumId}", albumId, ).Replace(config.AlbumFolderFormat) + if meta.Data[0].Attributes.IsMasteredForItunes{ + if config.AppleMasterChoice != ""{ + albumFolder = fmt.Sprintf("%s %s", albumFolder,config.AppleMasterChoice) + } + } + if meta.Data[0].Attributes.ContentRating=="explicit"{ + if config.ExplicitChoice != ""{ + albumFolder = fmt.Sprintf("%s %s", albumFolder,config.ExplicitChoice) + } + } + if meta.Data[0].Attributes.ContentRating=="clean"{ + if config.CleanChoice != ""{ + albumFolder = fmt.Sprintf("%s %s", albumFolder,config.CleanChoice) + } + } if strings.HasSuffix(albumFolder, ".") { albumFolder = strings.ReplaceAll(albumFolder, ".", "") } @@ -1198,8 +1217,30 @@ func rip(albumId string, token string, storefront string, userToken string) erro fmt.Println("Unavailable in ALAC.") continue } - filename := fmt.Sprintf("%02d. %s.m4a", trackNum, forbiddenNames.ReplaceAllString(track.Attributes.Name, "_")) - lrcFilename := fmt.Sprintf("%02d. %s.lrc", trackNum, forbiddenNames.ReplaceAllString(track.Attributes.Name, "_")) + songName := strings.NewReplacer( + "{SongNumer}", fmt.Sprintf("%02d", trackNum), + "{SongName}", track.Attributes.Name, + "{DiscNumber}", fmt.Sprintf("%0d", track.Attributes.DiscNumber), + "{TrackNumber}", fmt.Sprintf("%0d", track.Attributes.TrackNumber), + ).Replace(config.SongFileFormat) + if track.Attributes.IsAppleDigitalMaster{ + if config.AppleMasterChoice != ""{ + songName = fmt.Sprintf("%s %s", songName,config.AppleMasterChoice) + } + } + if track.Attributes.ContentRating=="explicit"{ + if config.ExplicitChoice != ""{ + songName = fmt.Sprintf("%s %s", songName,config.ExplicitChoice) + } + } + if track.Attributes.ContentRating=="clean"{ + if config.CleanChoice != ""{ + songName = fmt.Sprintf("%s %s", songName,config.CleanChoice) + } + } + fmt.Println(songName) + filename := fmt.Sprintf("%s.m4a", forbiddenNames.ReplaceAllString(songName, "_")) + lrcFilename := fmt.Sprintf("%s.lrc", forbiddenNames.ReplaceAllString(songName, "_")) trackPath := filepath.Join(sanAlbumFolder, filename) var lrc string = "" if userToken != "your-media-user-token" && (config.EmbedLrc || config.SaveLrcFile) { @@ -1778,6 +1819,8 @@ type SongAttributes struct { EnhancedHls string `json:"enhancedHls"` } `json:"extendedAssetUrls"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` Isrc string `json:"isrc"` @@ -1793,6 +1836,8 @@ type AlbumAttributes struct { GenreNames []string `json:"genreNames"` TrackCount int `json:"trackCount"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` RecordLabel string `json:"recordLabel"` @@ -1967,6 +2012,8 @@ type AutoGenerated struct { GenreNames []string `json:"genreNames"` TrackCount int `json:"trackCount"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` RecordLabel string `json:"recordLabel"` @@ -2022,6 +2069,8 @@ type AutoGenerated struct { GenreNames []string `json:"genreNames"` HasTimeSyncedLyrics bool `json:"hasTimeSyncedLyrics"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` DurationInMillis int `json:"durationInMillis"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` @@ -2083,6 +2132,8 @@ type AutoGeneratedTrack struct { GenreNames []string `json:"genreNames"` HasTimeSyncedLyrics bool `json:"hasTimeSyncedLyrics"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` DurationInMillis int `json:"durationInMillis"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` diff --git a/main_atmos.go b/main_atmos.go index 6f6f575..75caf86 100644 --- a/main_atmos.go +++ b/main_atmos.go @@ -45,6 +45,10 @@ type Config struct { AlacSaveFolder string `yaml:"alac-save-folder"` AtmosSaveFolder string `yaml:"atmos-save-folder"` AlbumFolderFormat string `yaml:"album-folder-format"` + SongFileFormat string `yaml:"song-file-format"` + ExplicitChoice string `yaml:"explicit-choice"` + CleanChoice string `yaml:"clean-choice"` + AppleMasterChoice string `yaml:"apple-master-choice"` AtmosMax int `yaml:"atmos-max"` } @@ -1130,6 +1134,21 @@ func rip(albumId string, token string, storefront string, userToken string) erro "{Copyright}", meta.Data[0].Attributes.Copyright, "{AlbumId}", albumId, ).Replace(config.AlbumFolderFormat) + if meta.Data[0].Attributes.IsMasteredForItunes{ + if config.AppleMasterChoice != ""{ + albumFolder = fmt.Sprintf("%s %s", albumFolder,config.AppleMasterChoice) + } + } + if meta.Data[0].Attributes.ContentRating=="explicit"{ + if config.ExplicitChoice != ""{ + albumFolder = fmt.Sprintf("%s %s", albumFolder,config.ExplicitChoice) + } + } + if meta.Data[0].Attributes.ContentRating=="clean"{ + if config.CleanChoice != ""{ + albumFolder = fmt.Sprintf("%s %s", albumFolder,config.CleanChoice) + } + } albumFolder = fmt.Sprintf("%s [Atmos]", albumFolder) if strings.HasSuffix(albumFolder, ".") { albumFolder = strings.ReplaceAll(albumFolder, ".", "") @@ -1157,9 +1176,31 @@ func rip(albumId string, token string, storefront string, userToken string) erro fmt.Println("Unavailable in ALAC.") continue } - filename := fmt.Sprintf("%02d. %s.ec3", trackNum, forbiddenNames.ReplaceAllString(track.Attributes.Name, "_")) - m4afilename := fmt.Sprintf("%02d. %s.m4a", trackNum, forbiddenNames.ReplaceAllString(track.Attributes.Name, "_")) - lrcFilename := fmt.Sprintf("%02d. %s.lrc", trackNum, forbiddenNames.ReplaceAllString(track.Attributes.Name, "_")) + songName := strings.NewReplacer( + "{SongNumer}", fmt.Sprintf("%02d", trackNum), + "{SongName}", track.Attributes.Name, + "{DiscNumber}", string(track.Attributes.DiscNumber), + "{TrackNumber}", fmt.Sprintf("%02d", track.Attributes.TrackNumber), + ).Replace(config.SongFileFormat) + if track.Attributes.IsAppleDigitalMaster{ + if config.AppleMasterChoice != ""{ + songName = fmt.Sprintf("%s %s", songName,config.AppleMasterChoice) + } + } + if track.Attributes.ContentRating=="explicit"{ + if config.ExplicitChoice != ""{ + songName = fmt.Sprintf("%s %s", songName,config.ExplicitChoice) + } + } + if track.Attributes.ContentRating=="clean"{ + if config.CleanChoice != ""{ + songName = fmt.Sprintf("%s %s", songName,config.CleanChoice) + } + } + fmt.Println(songName) + filename := fmt.Sprintf("%s.ec3", forbiddenNames.ReplaceAllString(songName, "_")) + m4afilename := fmt.Sprintf("%s.m4a", forbiddenNames.ReplaceAllString(songName, "_")) + lrcFilename := fmt.Sprintf("%s.lrc", forbiddenNames.ReplaceAllString(songName, "_")) trackPath := filepath.Join(sanAlbumFolder, filename) m4atrackPath := filepath.Join(sanAlbumFolder, m4afilename) exists, err := fileExists(trackPath) @@ -1240,6 +1281,7 @@ func rip(albumId string, token string, storefront string, userToken string) erro fmt.Sprintf("ISRC=%s", meta.Data[0].Relationships.Tracks.Data[index].Attributes.Isrc), fmt.Sprintf("UPC=%s", meta.Data[0].Attributes.Upc), fmt.Sprintf("track=%d/%d", trackNum, trackTotal), + fmt.Sprintf("disk=%d/%d", meta.Data[0].Relationships.Tracks.Data[index].Attributes.DiscNumber, meta.Data[0].Relationships.Tracks.Data[trackTotal - 1].Attributes.DiscNumber), } if config.EmbedCover { tags = append(tags, fmt.Sprintf("cover=%s/cover.%s", sanAlbumFolder, config.CoverFormat)) @@ -1650,6 +1692,8 @@ type SongAttributes struct { EnhancedHls string `json:"enhancedHls"` } `json:"extendedAssetUrls"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` Isrc string `json:"isrc"` @@ -1665,6 +1709,8 @@ type AlbumAttributes struct { GenreNames []string `json:"genreNames"` TrackCount int `json:"trackCount"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` RecordLabel string `json:"recordLabel"` @@ -1839,6 +1885,8 @@ type AutoGenerated struct { GenreNames []string `json:"genreNames"` TrackCount int `json:"trackCount"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` RecordLabel string `json:"recordLabel"` @@ -1894,6 +1942,8 @@ type AutoGenerated struct { GenreNames []string `json:"genreNames"` HasTimeSyncedLyrics bool `json:"hasTimeSyncedLyrics"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` DurationInMillis int `json:"durationInMillis"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` @@ -1955,6 +2005,8 @@ type AutoGeneratedTrack struct { GenreNames []string `json:"genreNames"` HasTimeSyncedLyrics bool `json:"hasTimeSyncedLyrics"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` DurationInMillis int `json:"durationInMillis"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` diff --git a/main_select.go b/main_select.go index 5381c3c..9047937 100644 --- a/main_select.go +++ b/main_select.go @@ -46,6 +46,10 @@ type Config struct { AlacSaveFolder string `yaml:"alac-save-folder"` AtmosSaveFolder string `yaml:"atmos-save-folder"` AlbumFolderFormat string `yaml:"album-folder-format"` + SongFileFormat string `yaml:"song-file-format"` + ExplicitChoice string `yaml:"explicit-choice"` + CleanChoice string `yaml:"clean-choice"` + AppleMasterChoice string `yaml:"apple-master-choice"` AlacMax int `yaml:"alac-max"` } @@ -1133,6 +1137,21 @@ func rip(albumId string, token string, storefront string, userToken string) erro "{Copyright}", meta.Data[0].Attributes.Copyright, "{AlbumId}", albumId, ).Replace(config.AlbumFolderFormat) + if meta.Data[0].Attributes.IsMasteredForItunes{ + if config.AppleMasterChoice != ""{ + albumFolder = fmt.Sprintf("%s %s", albumFolder,config.AppleMasterChoice) + } + } + if meta.Data[0].Attributes.ContentRating=="explicit"{ + if config.ExplicitChoice != ""{ + albumFolder = fmt.Sprintf("%s %s", albumFolder,config.ExplicitChoice) + } + } + if meta.Data[0].Attributes.ContentRating=="clean"{ + if config.CleanChoice != ""{ + albumFolder = fmt.Sprintf("%s %s", albumFolder,config.CleanChoice) + } + } if strings.HasSuffix(albumFolder, ".") { albumFolder = strings.ReplaceAll(albumFolder, ".", "") } @@ -1203,9 +1222,30 @@ func rip(albumId string, token string, storefront string, userToken string) erro fmt.Println("Unavailable in ALAC.") continue } - filename := fmt.Sprintf("%02d. %s.m4a", trackNum, forbiddenNames.ReplaceAllString(track.Attributes.Name, "_")) - fmt.Println(filename) - lrcFilename := fmt.Sprintf("%02d. %s.lrc", trackNum, forbiddenNames.ReplaceAllString(track.Attributes.Name, "_")) + songName := strings.NewReplacer( + "{SongNumer}", fmt.Sprintf("%02d", trackNum), + "{SongName}", track.Attributes.Name, + "{DiscNumber}", string(track.Attributes.DiscNumber), + "{TrackNumber}", fmt.Sprintf("%02d", track.Attributes.TrackNumber), + ).Replace(config.SongFileFormat) + if track.Attributes.IsAppleDigitalMaster{ + if config.AppleMasterChoice != ""{ + songName = fmt.Sprintf("%s %s", songName,config.AppleMasterChoice) + } + } + if track.Attributes.ContentRating=="explicit"{ + if config.ExplicitChoice != ""{ + songName = fmt.Sprintf("%s %s", songName,config.ExplicitChoice) + } + } + if track.Attributes.ContentRating=="clean"{ + if config.CleanChoice != ""{ + songName = fmt.Sprintf("%s %s", songName,config.CleanChoice) + } + } + fmt.Println(songName) + filename := fmt.Sprintf("%s.m4a", forbiddenNames.ReplaceAllString(songName, "_")) + lrcFilename := fmt.Sprintf("%s.lrc", forbiddenNames.ReplaceAllString(songName, "_")) trackPath := filepath.Join(sanAlbumFolder, filename) var lrc string = "" if userToken != "your-media-user-token" && (config.EmbedLrc || config.SaveLrcFile) { @@ -1698,6 +1738,8 @@ type SongAttributes struct { EnhancedHls string `json:"enhancedHls"` } `json:"extendedAssetUrls"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` Isrc string `json:"isrc"` @@ -1713,6 +1755,8 @@ type AlbumAttributes struct { GenreNames []string `json:"genreNames"` TrackCount int `json:"trackCount"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` RecordLabel string `json:"recordLabel"` @@ -1887,6 +1931,8 @@ type AutoGenerated struct { GenreNames []string `json:"genreNames"` TrackCount int `json:"trackCount"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` RecordLabel string `json:"recordLabel"` @@ -1942,6 +1988,8 @@ type AutoGenerated struct { GenreNames []string `json:"genreNames"` HasTimeSyncedLyrics bool `json:"hasTimeSyncedLyrics"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` DurationInMillis int `json:"durationInMillis"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"` @@ -2003,6 +2051,8 @@ type AutoGeneratedTrack struct { GenreNames []string `json:"genreNames"` HasTimeSyncedLyrics bool `json:"hasTimeSyncedLyrics"` IsMasteredForItunes bool `json:"isMasteredForItunes"` + IsAppleDigitalMaster bool `json:"isAppleDigitalMaster"` + ContentRating string `json:"contentRating"` DurationInMillis int `json:"durationInMillis"` ReleaseDate string `json:"releaseDate"` Name string `json:"name"`