mirror of
https://github.com/yaronzz/Tidal-Media-Downloader.git
synced 2026-06-13 04:05:07 +03:00
For playlist, remove TIDAL songs and redownload PL, the songs will be removed in the mirror image dl folder
This commit is contained in:
@@ -173,3 +173,5 @@ TIDALDL-PY/exe/resource
|
||||
TIDALDL-PY/exe/tidal_dl_win.tar.gz
|
||||
.github/workflows/continuous-integration-workflow copy.yml
|
||||
TIDALDL-PY/tidal-gui.spec
|
||||
.history/
|
||||
.gitignore
|
||||
|
||||
@@ -140,3 +140,19 @@ pip3 install -r requirements.txt --user
|
||||
python3 setup.py install
|
||||
```
|
||||
|
||||
## Fork changes - Scenario and comments:
|
||||
I would be content with TIDAL download feature, to give me off-line music on my device. I find playlists good for that.
|
||||
|
||||
But playlist changes are not done well. If I add 1 song to a 100 song playlist, the only way I can get it on my phone is: -
|
||||
delete all 100 songs - download 101 songs. It's the time, the wear and tear on my device sd card... nope... don't like it at all.
|
||||
|
||||
But I see tidal-dl can create a "mirror image" of that playlist. And has some smarts: if I add a song to the playlist, download again, it will ONLY download that song. Cool. But - what if I delete a song?
|
||||
|
||||
Background: I use PC MediaMonkey for my non-TIDAL mp3s... it will download a music folder to my device... with MediaMonkey for Android and my home Wifi. Of course, MM can also see tidal-dl that "mirror image" playlist. And crucially: if there are adds/deletes, MM makes just the changes on my phone. Other files are untouched. Deletes are done too, smart!
|
||||
|
||||
But... now tidal-dl is the weak link. If I add 1 file to a playlist, and delete 1 file... it gives me the add... but it doesn't handle the delete. And the "mirror image" is not a mirror image any more.
|
||||
|
||||
So this is to fill that gap in my scenario. But the effect seems useful for other use-cases. SUMMARY: Suppose you download a playlist, on top of a previous download. If files are deleted on the playlist, they will also be deleted in the mirror image.
|
||||
|
||||
Also: some improved handling of the "onlyM4A" flag. If files have been renamed from mp4 to m4a, the SKIP download logic wasn't working. Now it's handled for the simple case at least.
|
||||
|
||||
|
||||
@@ -113,12 +113,31 @@ def __playlist__(conf, obj):
|
||||
Printf.err(msg)
|
||||
return
|
||||
|
||||
dictNewFiles = {}
|
||||
for index, item in enumerate(tracks):
|
||||
mag, album = API.getAlbum(item.album.id)
|
||||
item.trackNumberOnPlaylist = index + 1
|
||||
downloadTrack(item, album, obj)
|
||||
downloadTrack(item, album, obj, dictNewFiles=dictNewFiles)
|
||||
if conf.saveCovers and not conf.usePlaylistFolder:
|
||||
__downloadCover__(conf, album)
|
||||
|
||||
if len(dictNewFiles) > 0:
|
||||
targetDir = aigpy.path.getDirName(dictNewFiles[list(dictNewFiles.keys())[0]]) # trick to get the target directory
|
||||
resFiles = aigpy.path.getFiles(targetDir)
|
||||
killFiles = []
|
||||
errFiles = []
|
||||
|
||||
for fname in resFiles:
|
||||
if not os.path.basename(fname) in dictNewFiles:
|
||||
try:
|
||||
os.remove(fname)
|
||||
killFiles.append(fname)
|
||||
except:
|
||||
errFiles.append(fname)
|
||||
|
||||
Printf.info("Orphan files deleted:\n" + "\n".join(killFiles))
|
||||
Printf.info("Orphan files failed to delete (read-only?):\n" + "\n".join(errFiles))
|
||||
|
||||
for item in videos:
|
||||
downloadVideo(item, None)
|
||||
|
||||
|
||||
@@ -341,8 +341,8 @@ def setCurVideoQuality(text):
|
||||
break
|
||||
Settings.save(CONF)
|
||||
|
||||
def skip(path, url):
|
||||
if CONF.checkExist and isNeedDownload(path, url) is False:
|
||||
def skip(finalpath, url):
|
||||
if CONF.checkExist and isNeedDownload(finalpath, url) is False:
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -353,7 +353,7 @@ def convert(srcPath, stream):
|
||||
return srcPath
|
||||
|
||||
|
||||
def downloadTrack(track: Track, album=None, playlist=None, userProgress=None, partSize=1048576):
|
||||
def downloadTrack(track: Track, album=None, playlist=None, userProgress=None, partSize=1048576, dictNewFiles=None):
|
||||
try:
|
||||
msg, stream = API.getStreamUrl(track.id, CONF.audioQuality)
|
||||
if not aigpy.string.isNull(msg) or stream is None:
|
||||
@@ -365,8 +365,16 @@ def downloadTrack(track: Track, album=None, playlist=None, userProgress=None, pa
|
||||
userProgress.updateStream(stream)
|
||||
path = getTrackPath(CONF, track, stream, album, playlist)
|
||||
|
||||
if CONF.onlyM4a:
|
||||
finalpath = path.replace(".mp4", ".m4a")
|
||||
else:
|
||||
finalpath = path
|
||||
|
||||
if not dictNewFiles is None:
|
||||
dictNewFiles[os.path.basename(finalpath)] = finalpath # preserve full path to be used by caller
|
||||
|
||||
# check exist
|
||||
if skip(path, stream.url):
|
||||
if skip(finalpath, stream.url):
|
||||
Printf.success(aigpy.path.getFileName(path) + " (skip:already exists!)")
|
||||
return True, ""
|
||||
|
||||
@@ -383,7 +391,8 @@ def downloadTrack(track: Track, album=None, playlist=None, userProgress=None, pa
|
||||
# encrypted -> decrypt and remove encrypted file
|
||||
encrypted(stream, path + '.part', path)
|
||||
|
||||
# convert
|
||||
# convert to M4a if configured
|
||||
# note from here to end, path will be = finalpath
|
||||
path = convert(path, stream)
|
||||
|
||||
# contributors
|
||||
|
||||
Reference in New Issue
Block a user