update
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -47,3 +47,4 @@ venv.bak/
|
|||||||
config/
|
config/
|
||||||
downloads/
|
downloads/
|
||||||
*.log
|
*.log
|
||||||
|
music/
|
||||||
@@ -2,6 +2,9 @@ import threading
|
|||||||
import queue
|
import queue
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import pathlib
|
||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
from tidal_dl_ng.download import Download
|
from tidal_dl_ng.download import Download
|
||||||
from tidal_dl_ng.config import Settings, Tidal
|
from tidal_dl_ng.config import Settings, Tidal
|
||||||
@@ -175,6 +178,10 @@ class DownloadManager:
|
|||||||
if not tidal.session.check_login():
|
if not tidal.session.check_login():
|
||||||
raise Exception("Not logged in")
|
raise Exception("Not logged in")
|
||||||
|
|
||||||
|
# Move any existing albums to destination before starting new download
|
||||||
|
if task["type"] in ["album", "artist"]:
|
||||||
|
self._move_albums_to_destination()
|
||||||
|
|
||||||
# Use environment variable for download path, default to /app/downloads
|
# Use environment variable for download path, default to /app/downloads
|
||||||
import os
|
import os
|
||||||
settings.data.download_base_path = os.getenv("DOWNLOAD_PATH", "/app/downloads")
|
settings.data.download_base_path = os.getenv("DOWNLOAD_PATH", "/app/downloads")
|
||||||
@@ -249,7 +256,7 @@ class DownloadManager:
|
|||||||
task["current_item"] = track.name
|
task["current_item"] = track.name
|
||||||
|
|
||||||
downloader.item(
|
downloader.item(
|
||||||
file_template=settings.data.format_track,
|
file_template=settings.data.format_album,
|
||||||
media=track,
|
media=track,
|
||||||
quality_audio=settings.data.quality_audio,
|
quality_audio=settings.data.quality_audio,
|
||||||
is_parent_album=True,
|
is_parent_album=True,
|
||||||
@@ -298,7 +305,7 @@ class DownloadManager:
|
|||||||
task["current_item"] = track.name
|
task["current_item"] = track.name
|
||||||
|
|
||||||
downloader.item(
|
downloader.item(
|
||||||
file_template=settings.data.format_track,
|
file_template=settings.data.format_album,
|
||||||
media=track,
|
media=track,
|
||||||
quality_audio=settings.data.quality_audio,
|
quality_audio=settings.data.quality_audio,
|
||||||
is_parent_album=True, # Treat as album tracks to keep folder structure
|
is_parent_album=True, # Treat as album tracks to keep folder structure
|
||||||
@@ -306,4 +313,45 @@ class DownloadManager:
|
|||||||
list_total=track.album.num_tracks
|
list_total=track.album.num_tracks
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Move albums to destination after download completes
|
||||||
|
if task["type"] in ["album", "artist"]:
|
||||||
|
self._move_albums_to_destination()
|
||||||
|
|
||||||
|
def _move_albums_to_destination(self):
|
||||||
|
"""Move all albums from downloads/Albums/ to destination path."""
|
||||||
|
dest_base = os.getenv("ALBUM_DESTINATION_PATH")
|
||||||
|
if not dest_base:
|
||||||
|
return
|
||||||
|
|
||||||
|
download_base = os.getenv("DOWNLOAD_PATH", "/app/downloads")
|
||||||
|
albums_path = pathlib.Path(download_base) / "Albums"
|
||||||
|
|
||||||
|
if not albums_path.exists():
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
moved_count = 0
|
||||||
|
# Move all album folders to destination
|
||||||
|
for album_dir in albums_path.iterdir():
|
||||||
|
if not album_dir.is_dir():
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Destination path: [ALBUM_DESTINATION_PATH]/[Album folder name]
|
||||||
|
dest_album_path = pathlib.Path(dest_base) / album_dir.name
|
||||||
|
|
||||||
|
logger.info(f"Moving {album_dir.name} to {dest_album_path}")
|
||||||
|
|
||||||
|
# Remove destination if it exists
|
||||||
|
if dest_album_path.exists():
|
||||||
|
shutil.rmtree(dest_album_path)
|
||||||
|
|
||||||
|
# Move the album
|
||||||
|
shutil.move(str(album_dir), str(dest_album_path))
|
||||||
|
moved_count += 1
|
||||||
|
|
||||||
|
if moved_count > 0:
|
||||||
|
logger.info(f"Successfully moved {moved_count} album(s) to {dest_base}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to move albums: {e}")
|
||||||
|
|
||||||
|
|||||||
@@ -14,13 +14,11 @@
|
|||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2>Search</h2>
|
<h2>Search</h2>
|
||||||
<input type="text" id="query" placeholder="Search for tracks, albums..." onkeypress="handleEnter(event)">
|
<input type="text" id="query" placeholder="Search for artists, albums..." onkeypress="handleEnter(event)">
|
||||||
<select id="type"
|
<select id="type"
|
||||||
style="padding: 10px; background: #2d2d2d; color: white; border: 1px solid #333; border-radius: 4px;">
|
style="padding: 10px; background: #2d2d2d; color: white; border: 1px solid #333; border-radius: 4px;">
|
||||||
<option value="track">Track</option>
|
|
||||||
<option value="album">Album</option>
|
|
||||||
<option value="artist">Artist</option>
|
<option value="artist">Artist</option>
|
||||||
<option value="playlist">Playlist</option>
|
<option value="album">Album</option>
|
||||||
</select>
|
</select>
|
||||||
<button onclick="search()">Search</button>
|
<button onclick="search()">Search</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
35
docker-compose.local.yml
Normal file
35
docker-compose.local.yml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
services:
|
||||||
|
gluetun:
|
||||||
|
image: qmcgaw/gluetun
|
||||||
|
container_name: gluetun
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
ports:
|
||||||
|
- "8002:8080" # Expose tidal-dl-web port via gluetun
|
||||||
|
restart: always
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
container_name: tidal-dl-web
|
||||||
|
network_mode: "service:gluetun"
|
||||||
|
volumes:
|
||||||
|
- ./downloads:/app/downloads
|
||||||
|
- ./config:/app/config
|
||||||
|
- ./music:/app/music
|
||||||
|
# Mount source for development
|
||||||
|
- ./app:/app/app
|
||||||
|
command: uvicorn app.main:app --host 0.0.0.0 --port 8080 --reload
|
||||||
|
environment:
|
||||||
|
- PYTHONUNBUFFERED=1
|
||||||
|
- DOWNLOAD_PATH=/app/downloads
|
||||||
|
- XDG_CONFIG_HOME=/app/config
|
||||||
|
- ALBUM_DESTINATION_PATH=${ALBUM_DESTINATION_PATH:-}
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
gluetun:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
networks:
|
||||||
|
proxy:
|
||||||
|
external: true
|
||||||
@@ -33,6 +33,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./downloads:/app/downloads
|
- ./downloads:/app/downloads
|
||||||
- ./config:/app/config
|
- ./config:/app/config
|
||||||
|
- ./music:/app/music
|
||||||
# Mount source for development
|
# Mount source for development
|
||||||
- ./app:/app/app
|
- ./app:/app/app
|
||||||
command: uvicorn app.main:app --host 0.0.0.0 --port 8080 --reload
|
command: uvicorn app.main:app --host 0.0.0.0 --port 8080 --reload
|
||||||
@@ -40,6 +41,7 @@ services:
|
|||||||
- PYTHONUNBUFFERED=1
|
- PYTHONUNBUFFERED=1
|
||||||
- DOWNLOAD_PATH=/app/downloads
|
- DOWNLOAD_PATH=/app/downloads
|
||||||
- XDG_CONFIG_HOME=/app/config
|
- XDG_CONFIG_HOME=/app/config
|
||||||
|
- ALBUM_DESTINATION_PATH=${ALBUM_DESTINATION_PATH:-}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
gluetun:
|
gluetun:
|
||||||
|
|||||||
Reference in New Issue
Block a user