From 70259c757d34a75f30fa2eca87d15b85009bd586 Mon Sep 17 00:00:00 2001 From: Ak5cel Date: Mon, 15 Jan 2024 22:44:18 +0530 Subject: [PATCH] make a README for npm --- .github/README.md | 268 ++++++++++++++++++++++++++++++++++++++++++++++ README.md | 250 +++++------------------------------------- 2 files changed, 295 insertions(+), 223 deletions(-) create mode 100644 .github/README.md diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 0000000..f044514 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,268 @@ +# heartify-cli + +A CLI tool to export and filter out your Spotify liked songs into playlists. +With support for filters like ranges of date added, release date, genres, audio features, and more. + +## What does it solve? + +Around 2500 Liked songs in, I needed a way to organise the chaos without having to move away from 'liking' any more songs. +Hopefully, it's useful to more people out there with little time and a lot of liked songs :) + +### What you can do + +✔️ Export them to a playlist - you can now share your liked songs! + +✔️ Filter by the year you liked them - make a 'My Top Songs 2023' playlist, for example + +✔️ Filter by genre(s) to make genre-mixes out of your liked songs + +✔️ Make monthly playlists - no more adding songs manually to monthly playlists, simply filter by ranges of dates added + +✔️ Decade mixes - filter by release date + +✔️ Filter by audio features - make a workout playlist of songs in a certain bpm range, for example + +### No library size limits + +There's no (known) limit to the number of songs Heartify can fetch, so bring along your massive library of 7000 liked songs (or more?)! +Just be prepared for it to take a bit longer with the measures in place to account for Spotify's rate limits. + +## Getting Started + +### Installation + +Heartify is currently a work in progress, but you can install it by running: + +```sh +npm install -g heartify-cli +``` + +### Authorisation + +Run the following command from any directory, all data is stored locally where Heartify is installed. +Then follow the instructions to authorise access to your Spotify library. + +```sh + heartify init + +``` + +This command needs to be run just once, and you're logged in until you revoke permissions from your account page, +logout, or until Spotify automatically revokes permissions from time-to-time (in which case, run `heartify init` again). +Heartify uses the OAuth 2.0 Authorization Code with PKCE flow, and refreshes the access token automatically until it's revoked. + +### Basic Examples + +1. Export all liked songs to a playlist (replace 'My Liked Songs' for your playlist name, wrapped in quotes if it contains spaces) + + ```sh + heartify export 'My Liked Songs' + + ``` + + New playlists are not displayed on your profile by default. To display it on your profile, use the `--on-profile` flag or its short form `-p` + + ```sh + heartify export 'My Liked Songs' -p + + ``` + +1. Export your liked songs from a specific year (2023 in the example). You can use `--added-from` or `-f` + and `--added-to` or `-t`, but there's also a convenience option `--year` or `-Y` available, used here: + + ```sh + heartify export 'Liked Songs 2023' -Y 2023 + + ``` + +1. Filter by genre: There are several filters available, and one of them is `genre`. + To see all the genres detected in your liked songs that you can filter by, run + + ```sh + heartify show-genres + + ``` + + Then pick a genre and filter (replace '\'): + + ```sh + heartify export 'My mix' --filter 'genre=' + + ``` + + You can also filter by multiple genres: + + ```sh + heartify export 'My multi-genre mix' --filter 'genre=' 'genre=' + + ``` + + If genre names contain spaces or special characters, either wrap it in quotes, or wrap the entire field-value pair in quotes. + For example, this command would make (a rather interesting) playlist out of songs which fall into at least one of + the following genres: 'disco', 'conscious hip hop', 'k-indie', and 'escape room' + + ```sh + heartify export 'My multi-genre mix' --filter genre=disco 'genre=conscious hip hop' genre='k-indie' genre='escape room' + + ``` + +1. Filter by custom range of date added using the `--added-from` or `-f` option, the `--added-to` or `-t` option, or both + + ```sh + heartify export 'Liked Songs, November 2023' -f 2023-11-01 -t 2023-11-30 + + ``` + + ```sh + heartify export 'Liked Songs from July 1st 2023 onwards' -f 2023-07-01 + + ``` + + Some things to keep in mind about the dates: + + - Dates for the start of the range (the 'from' values) are converted to the timestamp at midnight at the start of the day + - Dates for the end of the range (the 'to' values) are converted to the timestamp at the last second before midnight at the end of the day + - Dates are taken with reference to the user's current time zone (machine time zone). They're internally converted to UTC, but respect time zones. + + Valid date formats include: + + - `YYYYMMDD`: 20230101, 20230730 + - `YYYY-MM-DD`: 2023-01-01, 2023-07-30 + - `YYYY`: 2023, 2022 (NOTE: this is converted to midnight at the start of the year if it's a 'from' value, and the timestamp + at the last second before midnight of January 1st if it's a 'to' value) + +1. Filter by other features of the tracks, like date released, key, or tempo (see the list of supported features [here](#string-fields)) + + ```sh + heartify export 'Liked Songs, 120bpm' --filter tempo=120 + + ``` + +1. Filter by ranges: DateTime filters and Number filters (TODO: link) support ranges. Ranges are written as `field=[from, to]`. + Either the 'from' or the 'to' value can be omitted for a range unbounded on one side + + ```sh + heartify export 'Liked Songs, 100-120bpm' --filter tempo=[100,120] + + ``` + +1. Combine options and filters + + ```sh + heartify export 'Liked Songs 2023, 100-120bpm, danceable' -Y 2023 --filter tempo=[100,120] danceability=[0.7,] + + ``` + +## Detailed Docs (TODO) + +### `--filter` + +Filters are of the form `field=value` and accept any field from the list of supported fields below. + +The value can be either individual values like in `genre=disco` and `time_signature=4`, or ranges like +in `tempo=[100,120]` (only DateTime and Number fields accept ranges at the time of writing) + +Ranges must have at least the start or the end specified. The search includes the end points. + +```sh +# songs with tempo from 100 BPM to 120 BPM (both inclusive) +--filter tempo=[100,120] + +# songs with tempo >= 100 BPM +--filter tempo=[100,] + +# songs with tempo <= 120 BPM +--filter tempo=[,120] + +``` + +If multiple filters are given for the same field, they are joined by OR in the search + +```sh +# songs in the genres 'pop' or 'rock' +--filter genre=pop genre=rock + +# songs released in the 60's or in the 80's +--filter release_date=[1960-01-01,1969-12-31] release_date=[1980-01-01,1989-12-31] + +``` + +Filters for different fields are joined by AND + +```sh +# songs in the genre 'pop' released in the year 1990 +--filter genre=pop release_date=[1990-01-01,1990-12-31] + +# songs by BTS released since 2020 +--filter artist=BTS release_date=[2020-01-01,] + +# the above search can also be written like this as 'from 2020' is parsed as 'from midnight of 2020-01-01' +--filter artist=BTS release_date=[2020,] + +``` + +Filters do not need to be wrapped in quotes as long as they do not contain ANY spaces. +Wrap them in single/double quotes when they contain whitespace. + +```sh +# without spaces +--filter artist=BTS genre=k-pop release_date=[2016-01-01,2018-12-31] + +# quotes can be around the whole field-value pair or just the string that has spaces +--filter artist='J. Cole' 'artist = BTS' 'artist = Epik High' + +# quotes are needed if you prefer writing ranges with a space before/after the comma or the brackets +# the following filters are valid and return the same result: +--filter 'tempo=[60, 80]' +--filter tempo='[60, 80]' +--filter tempo=[60,' 80'] +--filter tempo=[60, '80'] +--filter tempo=['60', '80'] +--filter 'tempo = [ 60, 80 ]' + +``` + +### String fields + +- `artist` +- `genre` + +String fields accept only individual values (and not ranges). + +For example, `--filter 'artist=[BTS,Epik High]'` would mean artists 'from BTS to Epik High' and is not a supported search + +### DateTime fields + +- `release_date` + +### Number fields + +These fields correspond to those returned by the Spotify Web API. The descriptions here are excerpts of the full descriptions, +which can be found in the [Spotify Web Api docs for Audio Features](https://developer.spotify.com/documentation/web-api/reference/get-audio-features). + +| field | description | range | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------- | +| `danceability` | How suitable a track is for dancing based on
a combination of musical elements including tempo,
rhythm stability, beat strength,and overall regularity | 0.0 to 1.0
(float) | +| `energy` | Represents a perceptual measure of intensity
and activity | 0.0 to 1.0
(float) | +| `key` | The key the track is in.
Integers map to pitches using standard Pitch Class
notation. E.g. 0 = C, 1 = C♯/D♭, 2 = D, and so on.
If no key was detected, the value is -1. | -1 to 11
(integer) | +| `loudness` | The overall loudness of a track in decibels (dB).
Loudness values are averaged across the entire track and
are useful for comparing relative loudness of tracks | -60 to 0
(float) | +| `mode` | Mode indicates the modality (major or minor) of a track.
Major is represented by 1 and minor is 0. | 1 or 0
(integer) | +| `speechiness` | Detects the presence of spoken words in a track | 0.0 to 1.0
(float) | +| `acousticness` | A confidence measure from 0.0 to 1.0 of whether the
track is acoustic | 0.0 to 1.0
(float) | +| `instrumentalness` | Predicts whether a track contains no vocals | 0.0 to 1.0
(float) | +| `liveness` | Detects the presence of an audience in the recording.
A value above 0.8 provides strong likelihood that the track
is live. | 0.0 to 1.0
(float) | +| `valence` | Tracks with high valence sound more positive
(e.g. happy, cheerful, euphoric), while tracks with
low valence sound more negative (e.g. sad, depressed, angry) | 0.0 to 1.0
(float) | +| `tempo` | The overall estimated tempo of a track in beats per minute (BPM) | -
(float) | +| `duration_ms` | The duration of the track in milliseconds | -
(integer) | +| `time_signature` | An estimated time signature. The time signature (meter)
is a notational convention to specify how many beats
are in each bar (or measure). The time signature ranges
from 3 to 7 indicating time signatures of "3/4", to "7/4". | 3 to 7
(integer) | + +
+ +--- + +## Feedback, suggestions, and bug reports welcome! 👐 + +This is a small project I've been making on the side as I'm learning JS. +Feel free to open an issue for a new feature you'd like to have, suggestions, bug reports, or anything else. + +💜 diff --git a/README.md b/README.md index f044514..762c34e 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,11 @@ With support for filters like ranges of date added, release date, genres, audio Around 2500 Liked songs in, I needed a way to organise the chaos without having to move away from 'liking' any more songs. Hopefully, it's useful to more people out there with little time and a lot of liked songs :) -### What you can do +### Features -✔️ Export them to a playlist - you can now share your liked songs! +✔️ Export to a playlist to share your liked songs -✔️ Filter by the year you liked them - make a 'My Top Songs 2023' playlist, for example +✔️ Filter by the year you liked the song - make a 'My Top Songs 2023' playlist, for example ✔️ Filter by genre(s) to make genre-mixes out of your liked songs @@ -27,242 +27,46 @@ Hopefully, it's useful to more people out there with little time and a lot of li There's no (known) limit to the number of songs Heartify can fetch, so bring along your massive library of 7000 liked songs (or more?)! Just be prepared for it to take a bit longer with the measures in place to account for Spotify's rate limits. -## Getting Started +### Fully local -### Installation +Heartify collects no data. All data is stored locally on your device where heartify is installed, and can be deleted by running `heartify logout`. You can also revoke access at any time from your Spotify account page at Spotify Account > Security and privacy > Manage apps. -Heartify is currently a work in progress, but you can install it by running: +## Quickstart ```sh +# install npm install -g heartify-cli -``` - -### Authorisation - -Run the following command from any directory, all data is stored locally where Heartify is installed. -Then follow the instructions to authorise access to your Spotify library. - -```sh - heartify init - -``` - -This command needs to be run just once, and you're logged in until you revoke permissions from your account page, -logout, or until Spotify automatically revokes permissions from time-to-time (in which case, run `heartify init` again). -Heartify uses the OAuth 2.0 Authorization Code with PKCE flow, and refreshes the access token automatically until it's revoked. - -### Basic Examples - -1. Export all liked songs to a playlist (replace 'My Liked Songs' for your playlist name, wrapped in quotes if it contains spaces) - - ```sh - heartify export 'My Liked Songs' - - ``` - - New playlists are not displayed on your profile by default. To display it on your profile, use the `--on-profile` flag or its short form `-p` - - ```sh - heartify export 'My Liked Songs' -p - - ``` - -1. Export your liked songs from a specific year (2023 in the example). You can use `--added-from` or `-f` - and `--added-to` or `-t`, but there's also a convenience option `--year` or `-Y` available, used here: - - ```sh - heartify export 'Liked Songs 2023' -Y 2023 - - ``` - -1. Filter by genre: There are several filters available, and one of them is `genre`. - To see all the genres detected in your liked songs that you can filter by, run - - ```sh - heartify show-genres - - ``` - - Then pick a genre and filter (replace '\'): - - ```sh - heartify export 'My mix' --filter 'genre=' - - ``` - - You can also filter by multiple genres: - - ```sh - heartify export 'My multi-genre mix' --filter 'genre=' 'genre=' - - ``` - - If genre names contain spaces or special characters, either wrap it in quotes, or wrap the entire field-value pair in quotes. - For example, this command would make (a rather interesting) playlist out of songs which fall into at least one of - the following genres: 'disco', 'conscious hip hop', 'k-indie', and 'escape room' - - ```sh - heartify export 'My multi-genre mix' --filter genre=disco 'genre=conscious hip hop' genre='k-indie' genre='escape room' - - ``` - -1. Filter by custom range of date added using the `--added-from` or `-f` option, the `--added-to` or `-t` option, or both - - ```sh - heartify export 'Liked Songs, November 2023' -f 2023-11-01 -t 2023-11-30 - - ``` - - ```sh - heartify export 'Liked Songs from July 1st 2023 onwards' -f 2023-07-01 - - ``` - - Some things to keep in mind about the dates: - - - Dates for the start of the range (the 'from' values) are converted to the timestamp at midnight at the start of the day - - Dates for the end of the range (the 'to' values) are converted to the timestamp at the last second before midnight at the end of the day - - Dates are taken with reference to the user's current time zone (machine time zone). They're internally converted to UTC, but respect time zones. - - Valid date formats include: - - - `YYYYMMDD`: 20230101, 20230730 - - `YYYY-MM-DD`: 2023-01-01, 2023-07-30 - - `YYYY`: 2023, 2022 (NOTE: this is converted to midnight at the start of the year if it's a 'from' value, and the timestamp - at the last second before midnight of January 1st if it's a 'to' value) - -1. Filter by other features of the tracks, like date released, key, or tempo (see the list of supported features [here](#string-fields)) - ```sh - heartify export 'Liked Songs, 120bpm' --filter tempo=120 +# authorise access, and fetch liked songs and metadata +heartify init - ``` +# create your first playlist! +# This command exports all songs to a playlist +# (-p, short for --on-profile, optionally adds it to your profile) +heartify export 'My Liked Songs' -p -1. Filter by ranges: DateTime filters and Number filters (TODO: link) support ranges. Ranges are written as `field=[from, to]`. - Either the 'from' or the 'to' value can be omitted for a range unbounded on one side +# export just the songs liked in 2023 +heartify export 'Liked Songs 2023' -Y 2023 - ```sh - heartify export 'Liked Songs, 100-120bpm' --filter tempo=[100,120] +# or the songs liked in any range of time +heartify export 'Liked Songs, November 2023' -f 2023-11-01 -t 2023-11-30 - ``` +# see all genres identified +heartify show-genres -1. Combine options and filters +# make a genre-mix (replace with a genre of your choice) +heartify export 'My mix' --filter 'genre=' - ```sh - heartify export 'Liked Songs 2023, 100-120bpm, danceable' -Y 2023 --filter tempo=[100,120] danceability=[0.7,] +# make a multi-genre mix +heartify export 'My multi-genre mix' --filter 'genre=' 'genre=' - ``` - -## Detailed Docs (TODO) - -### `--filter` - -Filters are of the form `field=value` and accept any field from the list of supported fields below. - -The value can be either individual values like in `genre=disco` and `time_signature=4`, or ranges like -in `tempo=[100,120]` (only DateTime and Number fields accept ranges at the time of writing) - -Ranges must have at least the start or the end specified. The search includes the end points. - -```sh -# songs with tempo from 100 BPM to 120 BPM (both inclusive) ---filter tempo=[100,120] - -# songs with tempo >= 100 BPM ---filter tempo=[100,] - -# songs with tempo <= 120 BPM ---filter tempo=[,120] - -``` - -If multiple filters are given for the same field, they are joined by OR in the search - -```sh -# songs in the genres 'pop' or 'rock' ---filter genre=pop genre=rock - -# songs released in the 60's or in the 80's ---filter release_date=[1960-01-01,1969-12-31] release_date=[1980-01-01,1989-12-31] - -``` - -Filters for different fields are joined by AND - -```sh -# songs in the genre 'pop' released in the year 1990 ---filter genre=pop release_date=[1990-01-01,1990-12-31] - -# songs by BTS released since 2020 ---filter artist=BTS release_date=[2020-01-01,] - -# the above search can also be written like this as 'from 2020' is parsed as 'from midnight of 2020-01-01' ---filter artist=BTS release_date=[2020,] - -``` - -Filters do not need to be wrapped in quotes as long as they do not contain ANY spaces. -Wrap them in single/double quotes when they contain whitespace. - -```sh -# without spaces ---filter artist=BTS genre=k-pop release_date=[2016-01-01,2018-12-31] - -# quotes can be around the whole field-value pair or just the string that has spaces ---filter artist='J. Cole' 'artist = BTS' 'artist = Epik High' - -# quotes are needed if you prefer writing ranges with a space before/after the comma or the brackets -# the following filters are valid and return the same result: ---filter 'tempo=[60, 80]' ---filter tempo='[60, 80]' ---filter tempo=[60,' 80'] ---filter tempo=[60, '80'] ---filter tempo=['60', '80'] ---filter 'tempo = [ 60, 80 ]' +# filter by properties of the track - like release date, audio features (tempo, key, etc), and more +heartify export 'Liked Songs, 100-120bpm' --filter tempo=[100,120] ``` -### String fields - -- `artist` -- `genre` - -String fields accept only individual values (and not ranges). - -For example, `--filter 'artist=[BTS,Epik High]'` would mean artists 'from BTS to Epik High' and is not a supported search - -### DateTime fields - -- `release_date` - -### Number fields - -These fields correspond to those returned by the Spotify Web API. The descriptions here are excerpts of the full descriptions, -which can be found in the [Spotify Web Api docs for Audio Features](https://developer.spotify.com/documentation/web-api/reference/get-audio-features). - -| field | description | range | -| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------- | -| `danceability` | How suitable a track is for dancing based on
a combination of musical elements including tempo,
rhythm stability, beat strength,and overall regularity | 0.0 to 1.0
(float) | -| `energy` | Represents a perceptual measure of intensity
and activity | 0.0 to 1.0
(float) | -| `key` | The key the track is in.
Integers map to pitches using standard Pitch Class
notation. E.g. 0 = C, 1 = C♯/D♭, 2 = D, and so on.
If no key was detected, the value is -1. | -1 to 11
(integer) | -| `loudness` | The overall loudness of a track in decibels (dB).
Loudness values are averaged across the entire track and
are useful for comparing relative loudness of tracks | -60 to 0
(float) | -| `mode` | Mode indicates the modality (major or minor) of a track.
Major is represented by 1 and minor is 0. | 1 or 0
(integer) | -| `speechiness` | Detects the presence of spoken words in a track | 0.0 to 1.0
(float) | -| `acousticness` | A confidence measure from 0.0 to 1.0 of whether the
track is acoustic | 0.0 to 1.0
(float) | -| `instrumentalness` | Predicts whether a track contains no vocals | 0.0 to 1.0
(float) | -| `liveness` | Detects the presence of an audience in the recording.
A value above 0.8 provides strong likelihood that the track
is live. | 0.0 to 1.0
(float) | -| `valence` | Tracks with high valence sound more positive
(e.g. happy, cheerful, euphoric), while tracks with
low valence sound more negative (e.g. sad, depressed, angry) | 0.0 to 1.0
(float) | -| `tempo` | The overall estimated tempo of a track in beats per minute (BPM) | -
(float) | -| `duration_ms` | The duration of the track in milliseconds | -
(integer) | -| `time_signature` | An estimated time signature. The time signature (meter)
is a notational convention to specify how many beats
are in each bar (or measure). The time signature ranges
from 3 to 7 indicating time signatures of "3/4", to "7/4". | 3 to 7
(integer) | - -
- ---- - -## Feedback, suggestions, and bug reports welcome! 👐 +## Docs -This is a small project I've been making on the side as I'm learning JS. -Feel free to open an issue for a new feature you'd like to have, suggestions, bug reports, or anything else. +Read the [full docs](https://github.com/Ak5cel/heartify-cli#readme) on GitHub. 💜