Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,21 @@ follow these instructions

## Usage

There are different **operations** spotDL can perform. For example `download`, which simply downloads the songs from YouTube and embeds metadata.

The **query** for spotDL is usually a list of Spotify URLs, but for some operations like **sync**, only a single link or file is required.
For a list of all **options** use ```spotdl -h```

Using SpotDL without options:

```sh
spotdl [urls]
spotdl [operation] [urls]
```

You can run _spotDL_ as a package if running it as a script doesn't work:

```sh
python -m spotdl [urls]
python -m spotdl [operation] [urls]
```

General usage:
Expand All @@ -95,11 +100,6 @@ General usage:
spotdl [operation] [options] QUERY
```

There are different **operations** spotDL can perform. The _default_ is `download`, which simply downloads the songs from YouTube and embeds metadata.

The **query** for spotDL is usually a list of Spotify URLs, but for some operations like **sync**, only a single link or file is required.
For a list of all **options** use ```spotdl -h```

### Refer to [Usage](usage.md) for more info.

## Music Sourcing and Audio Quality
Expand Down
32 changes: 32 additions & 0 deletions spotdl/console/entry_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
Module that holds the entry point for the console.
"""

import csv
import cProfile
import logging
import pstats
import signal
import sys
import time

from pathlib import Path

from spotdl.console.download import download
from spotdl.console.meta import meta
from spotdl.console.save import save
Expand Down Expand Up @@ -138,6 +141,35 @@ def entry_point():
"Log in by adding the --user-auth flag"
)

# Check if we expect extra songs from Exportify
# csv and append them to the query
if arguments.load_exportify:

csv_path = Path(arguments.load_exportify)

if not csv_path.exists():
raise FileNotFoundError(
"Exportify csv not found." "Please specify an existing file path."
)

with open(csv_path, "r", encoding="utf-8") as csv_file:
reader = csv.reader(csv_file)

# skip the first row
next(reader, None)

for row in reader:
if row:

# first column is the track URI, which
# is formatted as spotify:track:[track_id]
# https://github.com/watsonbox/exportify/blob/master/README.md#export-format
# here we only want the track id part
track_id = row[0].split(":")[-1]
track_url = f"https://open.spotify.com/track/{track_id}"

arguments.query.append(track_url)

# Initialize the downloader
# for download, load and preload operations
downloader = Downloader(downloader_settings)
Expand Down
21 changes: 16 additions & 5 deletions spotdl/utils/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ def parse_main_options(parser: _ArgumentGroup):
operation = parser.add_argument(
"operation",
choices=OPERATIONS,
default="download",
const="download",
nargs="?",
help=(
"N|The operation to perform.\n"
"download: Download the songs to the disk and embed metadata.\n"
Expand All @@ -67,7 +64,7 @@ def parse_main_options(parser: _ArgumentGroup):
# Add query argument
query = parser.add_argument(
"query",
nargs="+",
nargs="*",
type=str,
help=(
"N|Spotify/YouTube URL for a song/playlist/album/artist/etc. to download.\n\n"
Expand Down Expand Up @@ -177,6 +174,12 @@ def parse_main_options(parser: _ArgumentGroup):
help="Use only verified results. (Not all providers support this)",
)

# Add songs from Exportify csv to the query
parser.add_argument(
"--load-exportify",
help="Load songs from an Exportify csv. (Can be used together with normal query)",
)


def parse_spotify_options(parser: _ArgumentGroup):
"""
Expand Down Expand Up @@ -873,4 +876,12 @@ def parse_arguments() -> Namespace:
parser = create_parser()

# Parse arguments
return parser.parse_args()
arguments = parser.parse_args()

# ensure at least one of the two (query or exportify list) are given
if not any((arguments.query, arguments.load_exportify)):
parser.error(
"one of the following arguments are required: query, --load-exportify"
)

return arguments