From 9a722b1d24a2e64b7fb0212f4b5bcabd3c1ac7e3 Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 10 Jul 2025 09:38:12 +0300 Subject: [PATCH 01/10] trigger pipeline --- backend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 2cb042a..36894db 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -10,4 +10,4 @@ RUN pip install --no-cache-dir -r requirements.txt ENV MUSIC_DIR=/music -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] From 363337bcf8a1108d1edee814aea7f1b752da3dbe Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 10 Jul 2025 09:44:05 +0300 Subject: [PATCH 02/10] Add git clone to update backend tag step --- .woodpecker.yaml | 1 + backend/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.woodpecker.yaml b/.woodpecker.yaml index 0a993b8..6a15baf 100644 --- a/.woodpecker.yaml +++ b/.woodpecker.yaml @@ -37,6 +37,7 @@ steps: - apk add --no-cache git yq - git config --global user.name "woodpecker-bot" - git config --global user.email "ci@dvirlabs.com" + - git clone "https://$${GIT_USERNAME}:$${GIT_TOKEN}@git.dvirlabs.com/dvirlabs/my-apps.git" - cd my-apps - | TAG="${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:7}" diff --git a/backend/Dockerfile b/backend/Dockerfile index 36894db..2cb042a 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -10,4 +10,4 @@ RUN pip install --no-cache-dir -r requirements.txt ENV MUSIC_DIR=/music -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file From 9022952d1eb74ca3888a0e65cbdba465debf3c31 Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 10 Jul 2025 09:57:08 +0300 Subject: [PATCH 03/10] Add more pkgs to requierments.txt --- backend/Dockerfile | 1 + backend/requirements.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 2cb042a..ccd510e 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -6,6 +6,7 @@ RUN apt update && apt install -y curl ffmpeg && \ WORKDIR /app COPY . . + RUN pip install --no-cache-dir -r requirements.txt ENV MUSIC_DIR=/music diff --git a/backend/requirements.txt b/backend/requirements.txt index 24b4f82..e2c0f5a 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,4 +1,6 @@ fastapi uvicorn pydantic -requests \ No newline at end of file +requests +downloader +config \ No newline at end of file From 735b15e80a929e0ed46c05dc58d50fac25531012 Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 10 Jul 2025 10:02:33 +0300 Subject: [PATCH 04/10] Add more pkgs to requierments.txt --- backend/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index e2c0f5a..cb359d4 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -3,4 +3,5 @@ uvicorn pydantic requests downloader -config \ No newline at end of file +config +urllib2 \ No newline at end of file From 2c22ad59b75e23eecfa660b5ac3242c9d233d9fb Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 10 Jul 2025 10:11:40 +0300 Subject: [PATCH 05/10] Fix libs --- backend/downloader.py | 33 +++++++++++++++++++++++++++++++++ backend/main.py | 35 ----------------------------------- backend/requirements.txt | 3 --- 3 files changed, 33 insertions(+), 38 deletions(-) create mode 100644 backend/downloader.py diff --git a/backend/downloader.py b/backend/downloader.py new file mode 100644 index 0000000..7989718 --- /dev/null +++ b/backend/downloader.py @@ -0,0 +1,33 @@ +import subprocess +import os +from config import settings +import uuid +import requests + +def download_song(query: str): + output_template = os.path.join(settings.MUSIC_DIR, "%(title)s.%(ext)s") + + command = [ + "yt-dlp", + f"ytsearch1:{query}", + "--extract-audio", + "--audio-format", "mp3", + "--output", output_template + ] + + result = subprocess.run(command, capture_output=True, text=True) + + if result.returncode != 0: + raise Exception(f"Download failed: {result.stderr}") + + # Optional: trigger navidrome scan + if settings.NAVIDROME_SCAN_URL: + try: + requests.post(settings.NAVIDROME_SCAN_URL, timeout=5) + except Exception as e: + pass # non-critical + + return { + "query": query, + "log": result.stdout + } \ No newline at end of file diff --git a/backend/main.py b/backend/main.py index 69266a7..92755b8 100644 --- a/backend/main.py +++ b/backend/main.py @@ -12,38 +12,3 @@ def download(query: str = Query(..., description="Song name or YouTube search te return JSONResponse(content={"status": "success", **result}) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) - -# downloader.py -import subprocess -import os -from config import settings -import uuid -import requests - -def download_song(query: str): - output_template = os.path.join(settings.MUSIC_DIR, "%(title)s.%(ext)s") - - command = [ - "yt-dlp", - f"ytsearch1:{query}", - "--extract-audio", - "--audio-format", "mp3", - "--output", output_template - ] - - result = subprocess.run(command, capture_output=True, text=True) - - if result.returncode != 0: - raise Exception(f"Download failed: {result.stderr}") - - # Optional: trigger navidrome scan - if settings.NAVIDROME_SCAN_URL: - try: - requests.post(settings.NAVIDROME_SCAN_URL, timeout=5) - except Exception as e: - pass # non-critical - - return { - "query": query, - "log": result.stdout - } \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt index cb359d4..0ea73f9 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -2,6 +2,3 @@ fastapi uvicorn pydantic requests -downloader -config -urllib2 \ No newline at end of file From e64c55c5a986e03f3fccd2168518993a5eae6262 Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 10 Jul 2025 10:19:35 +0300 Subject: [PATCH 06/10] Fix libs --- backend/config.py | 15 ++++++++++++--- backend/requirements.txt | 3 ++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/backend/config.py b/backend/config.py index 8deafdd..f08b77a 100644 --- a/backend/config.py +++ b/backend/config.py @@ -1,5 +1,4 @@ -import os -from pydantic import BaseSettings +from from pydantic_settings import BaseSettings class Settings(BaseSettings): MUSIC_DIR: str = "/music" @@ -8,4 +7,14 @@ class Settings(BaseSettings): class Config: env_file = ".env" -settings = Settings() \ No newline at end of file +settings = Settings() + import BaseSettings + +class Settings(BaseSettings): + MUSIC_DIR: str = "/music" + NAVIDROME_SCAN_URL: str = "" + + class Config: + env_file = ".env" + +settings = Settings() diff --git a/backend/requirements.txt b/backend/requirements.txt index 0ea73f9..5c71624 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,4 +1,5 @@ fastapi uvicorn -pydantic requests +pydantic>=2.0 +pydantic-settings>=2.0 From 965e61f60690db0cf6d3e31c7a442aa0364b0937 Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 10 Jul 2025 11:51:40 +0300 Subject: [PATCH 07/10] Fix config.py --- backend/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index ccd510e..f72ce76 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -11,4 +11,4 @@ RUN pip install --no-cache-dir -r requirements.txt ENV MUSIC_DIR=/music -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] From d15223f2cbd0c98f8e4e30b7a94f37f69668826e Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 10 Jul 2025 12:35:23 +0300 Subject: [PATCH 08/10] Fix config.py --- backend/config.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/backend/config.py b/backend/config.py index f08b77a..ced148b 100644 --- a/backend/config.py +++ b/backend/config.py @@ -1,14 +1,4 @@ -from from pydantic_settings import BaseSettings - -class Settings(BaseSettings): - MUSIC_DIR: str = "/music" - NAVIDROME_SCAN_URL: str = "" - - class Config: - env_file = ".env" - -settings = Settings() - import BaseSettings +from pydantic_settings import BaseSettings class Settings(BaseSettings): MUSIC_DIR: str = "/music" From e5a151ce99b57037054e0c44fcfdb7e055d6674d Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:21:17 +0300 Subject: [PATCH 09/10] Fix config.py and downloader.py --- backend/config.py | 6 ++++-- backend/downloader.py | 21 ++++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/backend/config.py b/backend/config.py index ced148b..15700b7 100644 --- a/backend/config.py +++ b/backend/config.py @@ -1,10 +1,12 @@ from pydantic_settings import BaseSettings +from pydantic import Field class Settings(BaseSettings): - MUSIC_DIR: str = "/music" - NAVIDROME_SCAN_URL: str = "" + MUSIC_DIR: str = Field(default="/music", description="Path where songs are saved") + NAVIDROME_SCAN_URL: str = Field(default="", description="URL to trigger Navidrome rescan") class Config: env_file = ".env" + env_file_encoding = "utf-8" settings = Settings() diff --git a/backend/downloader.py b/backend/downloader.py index 7989718..83d567c 100644 --- a/backend/downloader.py +++ b/backend/downloader.py @@ -1,33 +1,36 @@ import subprocess import os from config import settings -import uuid import requests def download_song(query: str): output_template = os.path.join(settings.MUSIC_DIR, "%(title)s.%(ext)s") - + command = [ "yt-dlp", f"ytsearch1:{query}", "--extract-audio", "--audio-format", "mp3", - "--output", output_template + "--output", output_template, + "--no-playlist", + "--quiet" ] result = subprocess.run(command, capture_output=True, text=True) if result.returncode != 0: - raise Exception(f"Download failed: {result.stderr}") + raise Exception(f"❌ Download failed:\n{result.stderr}") - # Optional: trigger navidrome scan + # Optional: trigger Navidrome rescan if settings.NAVIDROME_SCAN_URL: try: - requests.post(settings.NAVIDROME_SCAN_URL, timeout=5) + res = requests.get(settings.NAVIDROME_SCAN_URL, timeout=5) + res.raise_for_status() except Exception as e: - pass # non-critical + print(f"⚠️ Failed to trigger Navidrome rescan: {e}") return { + "status": "success", "query": query, - "log": result.stdout - } \ No newline at end of file + "log": result.stdout + "\n" + result.stderr + } From 695ba0169c0efc821340feb155327ef5a328fba8 Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:40:38 +0300 Subject: [PATCH 10/10] Fix downloader.py output --- backend/downloader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/downloader.py b/backend/downloader.py index 83d567c..fc0c89e 100644 --- a/backend/downloader.py +++ b/backend/downloader.py @@ -4,7 +4,8 @@ from config import settings import requests def download_song(query: str): - output_template = os.path.join(settings.MUSIC_DIR, "%(title)s.%(ext)s") + output_template = os.path.join(settings.MUSIC_DIR, "%(artist)s/%(album)s/%(title)s.%(ext)s") + command = [ "yt-dlp",