Add more search options, and a temporal filter

This commit is contained in:
Bradlee Speice 2021-07-04 00:01:09 -04:00
parent 238c052668
commit bb1ae761be
5 changed files with 107 additions and 7 deletions

View File

@ -1,6 +1,4 @@
""" # pylint: disable=missing-module-docstring, missing-function-docstring
Find an album using the `spotify_actions` API and echo its contents.
"""
from argparse import ArgumentParser from argparse import ArgumentParser
@ -9,9 +7,9 @@ from spotify_actions.search import search_albums
from spotify_actions.util import read_credentials from spotify_actions.util import read_credentials
def main() -> None: # pylint: disable=missing-function-docstring def main() -> None:
parser = ArgumentParser() parser = ArgumentParser()
parser.add_argument("-f", "--config", required=True) parser.add_argument("-c", "--credentials", required=True)
parser.add_argument("search_string") parser.add_argument("search_string")
cmdline = parser.parse_args() cmdline = parser.parse_args()

View File

@ -0,0 +1,32 @@
# pylint: disable=missing-module-docstring, missing-function-docstring
from argparse import ArgumentParser
from datetime import date, timedelta
from spotify_actions.echo import echo_album
from spotify_actions.join import join_albums
from spotify_actions.search import search_albums_label
from spotify_actions.temporal import album_released_after
from spotify_actions.util import read_credentials
def main() -> None:
parser = ArgumentParser()
parser.add_argument("-c", "--credentials", required=True)
parser.add_argument("label", nargs="+")
cmdline = parser.parse_args()
today = date.today()
four_weeks = timedelta(days=28)
client = read_credentials(cmdline.credentials)
label_albums = [search_albums_label(client, l) for l in cmdline.label]
albums = join_albums(*label_albums)
albums_recent = album_released_after(albums, today - four_weeks)
echo_album(albums_recent)
if __name__ == "__main__":
main()

14
spotify_actions/join.py Normal file
View File

@ -0,0 +1,14 @@
"""
Join objects from multiple sources into a single stream
"""
from typing import Iterable
from spotify_model import SearchAlbum
def join_albums(*args: Iterable[SearchAlbum]) -> Iterable[SearchAlbum]:
"Join the results of many album producers by exhausting all albums from each producer"
for arg in args:
for album in arg:
yield album

View File

@ -23,8 +23,15 @@ def search_albums(client: Spotify, search_str: str) -> Iterable[SearchAlbum]:
yield SearchAlbum(**item) yield SearchAlbum(**item)
def search_label_albums(client: Spotify, search_str: str) -> Iterable[SearchAlbum]: def search_albums_artist(client: Spotify, artist_name: str) -> Iterable[SearchAlbum]:
"Display albums from a particular artist"
for item in exhaust(_search_albums(client, f'artist:"{artist_name}"')):
yield SearchAlbum(**item)
def search_albums_label(client: Spotify, label_name: str) -> Iterable[SearchAlbum]:
"Display albums from a particular label" "Display albums from a particular label"
for item in exhaust(_search_albums(client, f'label:"{search_str}"')): for item in exhaust(_search_albums(client, f'label:"{label_name}"')):
yield SearchAlbum(**item) yield SearchAlbum(**item)

View File

@ -0,0 +1,49 @@
"""
Actions for filtering based on temporal information
"""
from calendar import monthrange
from datetime import date, datetime
from logging import getLogger
from typing import Iterable
from spotify_model import ReleaseDatePrecision, SearchAlbum
def album_released_after(albums: Iterable[SearchAlbum], released_after: date) -> Iterable[SearchAlbum]:
"""
Filter albums to after a specific release date.
For albums that don't have date-level precision, the release date is treated as the final day within that period;
thus, albums released in "1981" are effectively released on 1981-12-31, and albums released in "1981-07" are
treated as "1981-07-31"
"""
logger = getLogger(__name__)
for album in albums:
if album.release_date_precision == ReleaseDatePrecision.YEAR:
actual_release = datetime.strptime(album.release_date, "%Y")
effective_release = date(actual_release.year, 12, 31)
elif album.release_date_precision == ReleaseDatePrecision.MONTH:
actual_release = datetime.strptime(album.release_date, "%Y-%m")
final_day = monthrange(actual_release.year, actual_release.month)[1] - 1
effective_release = date(actual_release.year, actual_release.month, final_day)
else:
effective_release = datetime.strptime(album.release_date, "%Y-%m-%d").date()
if effective_release >= released_after:
logger.debug(
"Including album=%s released on date=%s (prior to date=%s)",
album.name,
effective_release,
released_after,
)
yield album
else:
logger.debug(
"Skipping album=%s released on date=%s (prior to date=%s)",
album.name,
effective_release,
released_after,
)