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
5 changes: 4 additions & 1 deletion BeatPrints/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from BeatPrints.spotify import *
from BeatPrints.api.spotify import *
from BeatPrints.api.yt_music import *
from BeatPrints.api.api_client import *
from BeatPrints.metadata import *
from BeatPrints.lyrics import *
from BeatPrints.poster import *
from BeatPrints.errors import *
82 changes: 82 additions & 0 deletions BeatPrints/api/api_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""
Module: api_client.py

Provides functionality related to interacting with any API.
"""

from typing import List
from BeatPrints.api.spotify import Spotify
from BeatPrints.api.yt_music import YtMusic
from BeatPrints.metadata import AlbumMetadata, TrackMetadata
from BeatPrints.consts import Logos


class Client:
"""
A class for interacting with any API. Currently supports Spotify and YT Music.
"""

def __init__(self):
self.l = Logos()
self.client = YtMusic()
self.logo = self.l.YT_MUSIC
self.use_scannable_code = False

def set_spotify_client(self, CLIENT_ID: str, CLIENT_SECRET: str) -> None:
"""
Sets a spotify API client as the client in use.

Args:
CLIENT_ID (str): Spotify API client ID.
CLIENT_SECRET (str): Spotify API client secret.
"""
self.client = Spotify(CLIENT_ID, CLIENT_SECRET)
self.use_scannable_code = True
self.logo = None

def set_yt_music_client(self) -> None:
"""
Sets a YouTube Music API client as the client in use.
"""
self.client = YtMusic()
self.use_scannable_code = False
self.logo = self.l.YT_MUSIC

def get_track(self, query: str, limit: int = 6) -> List[TrackMetadata]:
"""
Searches for tracks based on a query and retrieves their metadata.

Args:
query (str): The search query for the track (e.g. track name - artist).
limit (int, optional): Maximum number of tracks to retrieve. Defaults to 6.

Returns:
List[TrackMetadata]: A list of track metadata.

Raises:
InvalidSearchLimit: If the limit is less than 1.
NoMatchingTrackFound: If no matching tracks are found.
"""
track = self.client.get_track(query, limit)
return track

def get_album(
self, query: str, limit: int = 6, shuffle: bool = False
) -> List[AlbumMetadata]:
"""
Searches for albums based on a query and retrieves their metadata, including track listing.

Args:
query (str): The search query for the album (e.g. album name - artist).
limit (int, optional): Maximum number of albums to retrieve. Defaults to 6.
shuffle (bool, optional): Shuffle the tracks in the tracklist. Defaults to False.

Returns:
List[AlbumMetadata]: A list of album metadata with track listings.

Raises:
InvalidSearchLimit: If the limit is less than 1.
NoMatchingAlbumFound: If no matching albums are found.
"""
album = self.client.get_album(query, limit, shuffle)
return album
78 changes: 7 additions & 71 deletions BeatPrints/spotify.py → BeatPrints/api/spotify.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
Provides functionality related to interacting with the Spotify API.
"""

import spotipy
from typing import List
import random
import datetime
import spotipy

from typing import List
from dataclasses import dataclass

from spotipy.oauth2 import SpotifyClientCredentials
from spotipy.cache_handler import MemoryCacheHandler
Expand All @@ -20,36 +18,8 @@
InvalidSearchLimit,
)


@dataclass
class TrackMetadata:
"""
Data structure to store metadata for a track.
"""

name: str
artist: str
album: str
released: str
duration: str
image: str
label: str
id: str


@dataclass
class AlbumMetadata:
"""
Data structure to store metadata for an album, including a track list.
"""

name: str
artist: str
released: str
image: str
label: str
id: str
tracks: List[str]
from BeatPrints.metadata import AlbumMetadata, TrackMetadata
from BeatPrints.utils import format_released, format_duration


class Spotify:
Expand All @@ -73,40 +43,6 @@ def __init__(self, CLIENT_ID: str, CLIENT_SECRET: str) -> None:

self.spotify = spotipy.Spotify(client_credentials_manager=authorization)

def _format_released(self, release_date: str, precision: str) -> str:
"""
Formats the release date of a track or album.

Args:
release_date (str): Release date string from Spotify API.
precision (str): Precision of the release date ('day', 'month', 'year').

Returns:
str: Formatted release date in 'Month Day, Year' format.
"""
# Format the release date based on the precision
date_format = {"day": "%Y-%m-%d", "month": "%Y-%m", "year": "%Y"}.get(
precision, ""
)
return datetime.datetime.strptime(release_date, date_format).strftime(
"%B %d, %Y"
)

def _format_duration(self, duration_ms: int) -> str:
"""
Formats the duration of a track from milliseconds to MM:SS format.

Args:
duration_ms (int): Duration of the track in milliseconds.

Returns:
str: Formatted duration in MM:SS format.
"""
# Convert milliseconds to minutes and seconds
minutes = duration_ms // 60000
seconds = (duration_ms // 1000) % 60
return f"{minutes:02d}:{seconds:02d}"

def get_track(self, query: str, limit: int = 6) -> List[TrackMetadata]:
"""
Searches for tracks based on a query and retrieves their metadata.
Expand Down Expand Up @@ -152,8 +88,8 @@ def get_track(self, query: str, limit: int = 6) -> List[TrackMetadata]:
# If the label name is too long, use the artist's name
label = album["label"] if len(album["label"]) < 35 else artist

duration = self._format_duration(track["duration_ms"])
released = self._format_released(
duration = format_duration(track["duration_ms"])
released = format_released(
track["album"]["release_date"],
track["album"]["release_date_precision"],
)
Expand Down Expand Up @@ -225,7 +161,7 @@ def get_album(
# If the label name is too long, use the artist's name
label = album["label"] if len(album["label"]) < 35 else artist

released = self._format_released(
released = format_released(
album["release_date"],
album["release_date_precision"],
)
Expand Down
Loading