cool.gitter.not.me.again.duh 089cb3dc5a first commit
2025-05-31 15:51:18 -06:00
2025-05-31 15:51:18 -06:00
2025-05-31 15:51:18 -06:00
2025-05-31 15:51:18 -06:00
2025-05-31 15:51:18 -06:00
2025-05-31 15:51:18 -06:00
2025-05-31 15:51:18 -06:00
2025-05-31 15:51:18 -06:00

DeezSpot

DeezSpot is a Python library that enables downloading songs, albums, playlists, and podcasts from both Deezer and Spotify. This fork includes tweaks for use with the spotizerr project.

Features

  • Download tracks, albums, playlists, and podcasts from both Deezer and Spotify
  • Search for music by name or download directly using links
  • Support for different audio quality options
  • Download an artist's discography
  • Smart link detection to identify and process different types of content
  • Tag downloaded files with correct metadata
  • Customizable file and directory naming formats

Installation

pip install git+https://github.com/Xoconoch/deezspot-fork-again.git

From Source

git clone https://github.com/Xoconoch/deezspot-fork-again.git
cd deezspot-fork-again
pip install -e .

Configuration

Deezer Authentication

DeezSpot supports two methods of authentication for Deezer:

  1. Using ARL token:
from deezspot.deezloader import DeeLogin

# Authenticate with ARL
downloader = DeeLogin(arl="your_arl_token")
  1. Using email and password:
from deezspot.deezloader import DeeLogin

# Authenticate with email and password
downloader = DeeLogin(email="your_email", password="your_password")

Spotify Authentication

For Spotify, you'll need a credentials file:

from deezspot.spotloader import SpoLogin

# Authenticate with credentials file
downloader = SpoLogin(credentials_path="/path/to/credentials.json")

To create a credentials file, use a tool like librespot-java to generate it.

Usage

Downloading from Deezer

from deezspot.deezloader import DeeLogin

# Initialize with your credentials
downloader = DeeLogin(arl="your_arl_token")

# Download a track
track = downloader.download_trackdee(
    "https://www.deezer.com/track/123456789",
    output_dir="./downloads",
    quality_download="FLAC"  # Options: MP3_320, FLAC, MP3_128
)

# Download an album
album = downloader.download_albumdee(
    "https://www.deezer.com/album/123456789",
    output_dir="./downloads",
    quality_download="MP3_320",
    make_zip=True  # Create a zip archive of the album
)

# Download a playlist
playlist = downloader.download_playlistdee(
    "https://www.deezer.com/playlist/123456789",
    output_dir="./downloads",
    quality_download="MP3_320"
)

# Download an artist's top tracks
tracks = downloader.download_artisttopdee(
    "https://www.deezer.com/artist/123456789",
    output_dir="./downloads"
)

# Search and download by name
track = downloader.download_name(
    artist="Artist Name",
    song="Song Title",
    output_dir="./downloads"
)

Downloading from Spotify

from deezspot.spotloader import SpoLogin
import logging
from deezspot import set_log_level, enable_file_logging

# Configure logging
set_log_level(logging.INFO)
enable_file_logging("spotify_downloads.log")

# Custom progress callback
def spotify_progress_callback(progress_data):
    status = progress_data.get("status")
    if status == "real_time":
        song = progress_data.get("song", "Unknown")
        percentage = progress_data.get("percentage", 0) * 100
        print(f"Downloading '{song}': {percentage:.1f}%")
    elif status == "downloading":
        print(f"Starting download: {progress_data.get('song', 'Unknown')}")
    elif status == "done":
        print(f"Completed: {progress_data.get('song', 'Unknown')}")

# Initialize Spotify client with progress callback
spotify = SpoLogin(
    credentials_path="credentials.json",
    spotify_client_id="your_client_id",
    spotify_client_secret="your_client_secret",
    progress_callback=spotify_progress_callback
)

# Or use silent mode for background operations
spotify_silent = SpoLogin(
    credentials_path="credentials.json",
    spotify_client_id="your_client_id",
    spotify_client_secret="your_client_secret",
    silent=True
)

# Download a track
spotify.download_track(
    "https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT",
    output_dir="downloads",
    quality_download="HIGH",
    real_time_dl=True
)

# Download an album
album = spotify.download_album(
    "https://open.spotify.com/album/123456789",
    output_dir="./downloads",
    quality_download="HIGH",
    make_zip=True  # Create a zip archive of the album
)

# Download a playlist
playlist = spotify.download_playlist(
    "https://open.spotify.com/playlist/123456789",
    output_dir="./downloads"
)

# Download a podcast episode
episode = spotify.download_episode(
    "https://open.spotify.com/episode/123456789",
    output_dir="./downloads"
)

# Download an artist's discography
spotify.download_artist(
    "https://open.spotify.com/artist/123456789",
    album_type="album,single",  # Options: album, single, compilation, appears_on
    limit=50,  # Number of albums to retrieve
    output_dir="./downloads"
)

Smart Download

Both the Deezer and Spotify interfaces provide a "smart" download function that automatically detects the type of content from the link:

# For Deezer
result = downloader.download_smart("https://www.deezer.com/track/123456789")

# For Spotify
result = downloader.download_smart("https://open.spotify.com/album/123456789")

DeezSpot can also convert Spotify links to Deezer for downloading with higher quality:

# Convert and download a Spotify track using Deezer
track = downloader.download_trackspo("https://open.spotify.com/track/123456789")

# Convert and download a Spotify album using Deezer
album = downloader.download_albumspo("https://open.spotify.com/album/123456789")

# Convert and download a Spotify playlist using Deezer
playlist = downloader.download_playlistspo("https://open.spotify.com/playlist/123456789")

Available Quality Options

Deezer

  • MP3_320: 320 kbps MP3
  • FLAC: Lossless audio
  • MP3_128: 128 kbps MP3

Spotify

  • VERY_HIGH: 320 kbps OGG
  • HIGH: 160 kbps OGG
  • NORMAL: 96 kbps OGG

Common Parameters

Most download methods accept these common parameters:

  • output_dir: Output directory for downloaded files (default: "Songs/")
  • quality_download: Quality of audio files (see options above)
  • recursive_quality: Try another quality if the selected one is not available (default: True)
  • recursive_download: Try another API if the current one fails (default: True)
  • not_interface: Hide download progress (default: False)
  • make_zip: Create a zip archive for albums/playlists (default: False)
  • method_save: How to save the downloads (default: varies by function)
  • custom_dir_format: Custom directory naming format
  • custom_track_format: Custom track naming format

Custom Naming Formats

You can customize the output directory and file naming patterns:

# Example of custom directory format
result = downloader.download_albumdee(
    "https://www.deezer.com/album/123456789",
    custom_dir_format="{artist}/{album} [{year}]"
)

# Example of custom track format
result = downloader.download_trackdee(
    "https://www.deezer.com/track/123456789",
    custom_track_format="{tracknumber} - {title}"
)

License

This project is licensed under the GNU Affero General Public License v3.0 - see the LICENSE file for details.

Credits

This project is a fork of the original deezspot library.

Deezspot Logging System

This document explains the enhanced logging system implemented in the Deezspot library, making it more suitable for production environments, Celery integrations, and other enterprise applications.

Overview

The logging system in Deezspot provides:

  • Standardized, structured log messages
  • Multiple logging levels for different verbosity needs
  • File logging capabilities for persistent logs
  • Console output for interactive use
  • JSON-formatted progress updates
  • Custom progress callbacks for integration with other systems
  • Silent mode for background operation

Basic Configuration

Setting Log Level

from deezspot import set_log_level
import logging

# Available log levels:
# - logging.DEBUG (most verbose)
# - logging.INFO (default)
# - logging.WARNING
# - logging.ERROR
# - logging.CRITICAL (least verbose)

set_log_level(logging.INFO)  # Default level shows important information
set_log_level(logging.DEBUG)  # For detailed debugging information
set_log_level(logging.WARNING)  # For warnings and errors only

Enabling File Logging

from deezspot import enable_file_logging

# Enable logging to a file (in addition to console)
enable_file_logging("/path/to/logs/deezspot.log")

# With custom log level
enable_file_logging("/path/to/logs/deezspot.log", level=logging.DEBUG)

Disabling Logging

from deezspot import disable_logging

# Completely disable logging (except critical errors)
disable_logging()

Progress Reporting

The library uses a structured JSON format for progress reporting, making it easy to integrate with other systems.

Progress JSON Structure

For tracks:

{
  "status": "downloading|progress|done|skipped|retrying",
  "type": "track",
  "album": "Album Name",
  "song": "Song Title",
  "artist": "Artist Name"
}

For real-time downloads:

{
  "status": "real_time",
  "song": "Song Title",
  "artist": "Artist Name",
  "time_elapsed": 1500,
  "percentage": 0.75
}

For albums:

{
  "status": "initializing|progress|done",
  "type": "album",
  "album": "Album Name",
  "artist": "Artist Name",
  "track": "Current Track Title",
  "current_track": "3/12"
}

For playlists:

{
  "status": "initializing|progress|done",
  "type": "playlist",
  "name": "Playlist Name",
  "track": "Current Track Title",
  "current_track": "5/25",
  "total_tracks": 25
}

Custom Progress Callbacks

For integration with other systems (like Celery), you can provide a custom progress callback function when initializing the library.

Example with Custom Callback

from deezspot.deezloader import DeeLogin

def my_progress_callback(progress_data):
    """
    Custom callback function to handle progress updates
    
    Args:
        progress_data: Dictionary containing progress information
    """
    status = progress_data.get("status")
    track_title = progress_data.get("song", "")
    
    if status == "downloading":
        print(f"Starting download: {track_title}")
    elif status == "progress":
        current = progress_data.get("current_track", "")
        print(f"Progress: {current} - {track_title}")
    elif status == "done":
        print(f"Completed: {track_title}")
    elif status == "real_time":
        percentage = progress_data.get("percentage", 0) * 100
        print(f"Downloading: {track_title} - {percentage:.1f}%")

# Initialize with custom callback
deezer = DeeLogin(
    arl="your_arl_token",
    progress_callback=my_progress_callback
)

Silent Mode

If you want to disable progress reporting completely (for background operations), use silent mode:

deezer = DeeLogin(
    arl="your_arl_token",
    silent=True
)

Spotify Integration

For Spotify downloads, the same logging principles apply. Here's an example using the Spotify client:

from deezspot.spotloader import SpoLogin
import logging
from deezspot import set_log_level, enable_file_logging

# Configure logging
set_log_level(logging.INFO)
enable_file_logging("spotify_downloads.log")

# Custom progress callback
def spotify_progress_callback(progress_data):
    status = progress_data.get("status")
    if status == "real_time":
        song = progress_data.get("song", "Unknown")
        percentage = progress_data.get("percentage", 0) * 100
        print(f"Downloading '{song}': {percentage:.1f}%")
    elif status == "downloading":
        print(f"Starting download: {progress_data.get('song', 'Unknown')}")
    elif status == "done":
        print(f"Completed: {progress_data.get('song', 'Unknown')}")

# Initialize Spotify client with progress callback
spotify = SpoLogin(
    credentials_path="credentials.json",
    spotify_client_id="your_client_id",
    spotify_client_secret="your_client_secret",
    progress_callback=spotify_progress_callback
)

# Or use silent mode for background operations
spotify_silent = SpoLogin(
    credentials_path="credentials.json",
    spotify_client_id="your_client_id",
    spotify_client_secret="your_client_secret",
    silent=True
)

# Download a track
spotify.download_track(
    "https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT",
    output_dir="downloads",
    quality_download="HIGH",
    real_time_dl=True
)

Celery Integration Example

Here's how to integrate the logging system with Celery for task progress reporting:

from celery import Celery
from deezspot.deezloader import DeeLogin
import logging
from deezspot import enable_file_logging

# Configure Celery
app = Celery('tasks', broker='pyamqp://guest@localhost//')

# Configure logging
enable_file_logging("/path/to/logs/deezspot.log", level=logging.INFO)

@app.task(bind=True)
def download_music(self, link, output_dir):
    # Create a progress callback that updates the Celery task state
    def update_progress(progress_data):
        status = progress_data.get("status")
        
        if status == "downloading":
            self.update_state(
                state="DOWNLOADING",
                meta={
                    "track": progress_data.get("song", ""),
                    "progress": 0
                }
            )
        elif status == "progress":
            current, total = progress_data.get("current_track", "1/1").split("/")
            progress = int(current) / int(total)
            self.update_state(
                state="PROGRESS",
                meta={
                    "track": progress_data.get("track", ""),
                    "progress": progress
                }
            )
        elif status == "real_time":
            self.update_state(
                state="PROGRESS",
                meta={
                    "track": progress_data.get("song", ""),
                    "progress": progress_data.get("percentage", 0)
                }
            )
        elif status == "done":
            self.update_state(
                state="COMPLETED",
                meta={
                    "track": progress_data.get("song", ""),
                    "progress": 1.0
                }
            )
    
    # Initialize the client with the progress callback
    deezer = DeeLogin(
        arl="your_arl_token",
        progress_callback=update_progress
    )
    
    # Download the content
    result = deezer.download_smart(
        link=link,
        output_dir=output_dir,
        quality_download="MP3_320"
    )
    
    return {"status": "completed", "output": result.track.song_path}

Direct Logger Access

For advanced use cases, you can directly access and use the logger:

from deezspot.libutils.logging_utils import logger

# Use the logger directly
logger.debug("Detailed debugging information")
logger.info("General information")
logger.warning("Warning message")
logger.error("Error message")
logger.critical("Critical error message")

# Log structured data
import json
logger.info(json.dumps({
    "custom_event": "download_started",
    "metadata": {
        "source": "spotify",
        "track_id": "1234567890"
    }
}))

Log Format

The default log format is:

%(asctime)s - %(name)s - %(levelname)s - %(message)s

Example:

2023-10-15 12:34:56,789 - deezspot - INFO - {"status": "downloading", "type": "track", "album": "Album Name", "song": "Song Title", "artist": "Artist Name"}

Console vs File Logging

  • By default, the library is configured to log at WARNING level to the console only
  • You can enable file logging in addition to console logging
  • File and console logging can have different log levels

Using the Logger in Your Code

If you're extending the library or integrating it deeply into your application, you can use the logger directly:

from deezspot.libutils.logging_utils import logger, ProgressReporter

# Create a custom progress reporter
my_reporter = ProgressReporter(
    callback=my_callback_function,
    silent=False,
    log_level=logging.INFO
)

# Report progress
my_reporter.report({
    "status": "custom_status",
    "message": "Custom progress message",
    "progress": 0.5
})

# Log directly
logger.info("Processing started")

Test Script Example

Here's a complete example script that tests the Spotify functionality with logging enabled:

#!/usr/bin/env python3

import os
import logging
from deezspot import set_log_level, enable_file_logging
from deezspot.spotloader import SpoLogin

def main():
    # Configure logging
    set_log_level(logging.INFO)  # Set to logging.DEBUG for more detailed output
    enable_file_logging("deezspot.log")

    # Spotify API credentials
    SPOTIFY_CLIENT_ID = "your_client_id"
    SPOTIFY_CLIENT_SECRET = "your_client_secret"
    
    # Path to your Spotify credentials file (from librespot)
    CREDENTIALS_PATH = "credentials.json"
    
    # Output directory for downloads
    OUTPUT_DIR = "downloads"
    os.makedirs(OUTPUT_DIR, exist_ok=True)

    try:
        # Initialize the Spotify client
        spotify = SpoLogin(
            credentials_path=CREDENTIALS_PATH,
            spotify_client_id=SPOTIFY_CLIENT_ID,
            spotify_client_secret=SPOTIFY_CLIENT_SECRET
        )

        # Test track download
        print("\nTesting track download...")
        track_url = "https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT"
        spotify.download_track(
            track_url,
            output_dir=OUTPUT_DIR,
            quality_download="HIGH",
            real_time_dl=True,
            custom_dir_format="{artist}/{album}",
            custom_track_format="{tracknum} - {title}"
        )

    except Exception as e:
        print(f"Error: {str(e)}")
        logging.error(f"Test failed: {str(e)}", exc_info=True)

if __name__ == "__main__":
    main()

This logging system provides flexibility for both simple scripts and complex production applications, making it easier to monitor and integrate Deezspot in any environment.

Callback Functionality

Both the Deezer and Spotify components of the deezspot library now support progress callbacks, allowing you to integrate download progress into your applications. This feature enables:

  1. Real-time Progress Tracking: Monitor download progress for tracks, albums, playlists, and episodes
  2. Custom UI Integration: Update your application's UI with download status
  3. Background Processing: Run downloads silently in background tasks
  4. Task Management: Integrate with task systems like Celery for distributed processing

Common Callback Events

The progress callback function receives a dictionary with the following common fields:

  • status: The current status of the operation (initializing, downloading, progress, done, skipped, retrying, real_time)
  • type: The type of content (track, album, playlist, episode)
  • Additional fields depending on the status and content type

Usage in Both Components

Both the Deezer and Spotify components use the same callback system:

# For Deezer
deezer = DeeLogin(
    arl="your_arl_token",
    progress_callback=my_callback_function,
    silent=False  # Set to True to disable progress reporting
)

# For Spotify
spotify = SpoLogin(
    credentials_path="credentials.json",
    spotify_client_id="your_client_id",
    spotify_client_secret="your_client_secret",
    progress_callback=my_callback_function,
    silent=False  # Set to True to disable progress reporting
)

The standardized callback system ensures that your application can handle progress updates consistently regardless of whether the content is being downloaded from Deezer or Spotify.

Description
No description provided
Readme AGPL-3.0 462 KiB
Languages
Python 100%