From d3b3d4a31b59c8b9576b53e6b32503c96fa3f96a Mon Sep 17 00:00:00 2001 From: Jonathan Huston Date: Sat, 9 Dec 2023 16:30:10 -0800 Subject: [PATCH 1/3] Fixed scripts in examples directory that didn't work, deleted any redundant examples. --- examples/follow_playlist.py | 21 +++++------- examples/playlist_add_items.py | 12 ------- examples/read_a_playlist.py | 2 +- examples/remove_tracks_from_playlist.py | 4 +-- examples/replace_tracks_in_playlist.py | 2 +- examples/{tracks.py => show_artist_tracks.py} | 0 examples/show_tracks.py | 34 +++++++++++-------- examples/test.py | 11 ------ examples/unfollow_playlist.py | 6 ++-- 9 files changed, 35 insertions(+), 57 deletions(-) delete mode 100644 examples/playlist_add_items.py rename examples/{tracks.py => show_artist_tracks.py} (100%) delete mode 100644 examples/test.py diff --git a/examples/follow_playlist.py b/examples/follow_playlist.py index 6973468c..20f4c32a 100644 --- a/examples/follow_playlist.py +++ b/examples/follow_playlist.py @@ -1,27 +1,22 @@ -import argparse +# Follow a playlist +import argparse import spotipy from spotipy.oauth2 import SpotifyOAuth +scope = 'playlist-modify-public' +sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) def get_args(): parser = argparse.ArgumentParser(description='Follows a playlist based on playlist ID') - parser.add_argument('-p', '--playlist', required=True, help='Playlist ID') - + # Default to Top 50 Global if no playlist is provided + parser.add_argument('-p', '--playlist', help='Playlist ID', nargs='?', default='37i9dQZEVXbMDoHDwVN2tF') return parser.parse_args() def main(): args = get_args() - - if args.playlist is None: - # Uses the Spotify Global Top 50 playlist - spotipy.Spotify(auth_manager=SpotifyOAuth()).current_user_follow_playlist( - '37i9dQZEVXbMDoHDwVN2tF') - - else: - spotipy.Spotify(auth_manager=SpotifyOAuth()).current_user_follow_playlist(args.playlist) - + sp.current_user_follow_playlist(args.playlist) if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/examples/playlist_add_items.py b/examples/playlist_add_items.py deleted file mode 100644 index 8d10c5b2..00000000 --- a/examples/playlist_add_items.py +++ /dev/null @@ -1,12 +0,0 @@ -# Add a list of items (URI) to a playlist (URI) - -import spotipy -from spotipy.oauth2 import SpotifyOAuth - -sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id="YOUR_APP_CLIENT_ID", - client_secret="YOUR_APP_CLIENT_SECRET", - redirect_uri="YOUR_APP_REDIRECT_URI", - scope="playlist-modify-private" - )) - -sp.playlist_add_items('playlist_id', ['list_of_items']) diff --git a/examples/read_a_playlist.py b/examples/read_a_playlist.py index 06cad008..a6b56762 100644 --- a/examples/read_a_playlist.py +++ b/examples/read_a_playlist.py @@ -5,6 +5,6 @@ client_credentials_manager = SpotifyClientCredentials() sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) -playlist_id = 'spotify:user:spotifycharts:playlist:37i9dQZEVXbJiZcmkrIHGU' +playlist_id = '37i9dQZEVXbJiZcmkrIHGU' results = sp.playlist(playlist_id) print(json.dumps(results, indent=4)) diff --git a/examples/remove_tracks_from_playlist.py b/examples/remove_tracks_from_playlist.py index 8a51c569..5474264f 100644 --- a/examples/remove_tracks_from_playlist.py +++ b/examples/remove_tracks_from_playlist.py @@ -7,8 +7,8 @@ if len(sys.argv) > 2: - playlist_id = sys.argv[2] - track_ids = sys.argv[3:] + playlist_id = sys.argv[1] + track_ids = sys.argv[2:] else: print("Usage: %s playlist_id track_id ..." % (sys.argv[0])) sys.exit() diff --git a/examples/replace_tracks_in_playlist.py b/examples/replace_tracks_in_playlist.py index 6d1c46fd..89e2208a 100644 --- a/examples/replace_tracks_in_playlist.py +++ b/examples/replace_tracks_in_playlist.py @@ -6,7 +6,7 @@ import spotipy from spotipy.oauth2 import SpotifyOAuth -if len(sys.argv) > 3: +if len(sys.argv) > 2: playlist_id = sys.argv[1] track_ids = sys.argv[2:] else: diff --git a/examples/tracks.py b/examples/show_artist_tracks.py similarity index 100% rename from examples/tracks.py rename to examples/show_artist_tracks.py diff --git a/examples/show_tracks.py b/examples/show_tracks.py index efee1d28..9ea31efa 100644 --- a/examples/show_tracks.py +++ b/examples/show_tracks.py @@ -3,21 +3,25 @@ given a list of track IDs show the artist and track name ''' -from spotipy.oauth2 import SpotifyClientCredentials -import sys +from spotipy.oauth2 import SpotifyOAuth import spotipy +import argparse + + +def get_args(): + parser = argparse.ArgumentParser(description='Print artist and track name given a list of track IDs') + parser.add_argument('-u', '--uris', nargs='+', + required=True, help='Track ids') + return parser.parse_args() -if __name__ == '__main__': - max_tracks_per_call = 50 - if len(sys.argv) > 1: - file = open(sys.argv[1]) - else: - file = sys.stdin - tids = file.read().split() - client_credentials_manager = SpotifyClientCredentials() - sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) - for start in range(0, len(tids), max_tracks_per_call): - results = sp.tracks(tids[start: start + max_tracks_per_call]) - for track in results['tracks']: - print(track['name'] + ' - ' + track['artists'][0]['name']) +def main(): + args = get_args() + sp = spotipy.Spotify(auth_manager=SpotifyOAuth()) + track_list = sp.tracks(args.uris) + for track in track_list['tracks']: + print(track['name'] + ' - ' + track['artists'][0]['name']) + + +if __name__ == '__main__': + main() diff --git a/examples/test.py b/examples/test.py deleted file mode 100644 index bffb19b6..00000000 --- a/examples/test.py +++ /dev/null @@ -1,11 +0,0 @@ -import spotipy -from spotipy.oauth2 import SpotifyOAuth - -scope = "user-library-read" - -sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) - -results = sp.current_user_saved_tracks() -for idx, item in enumerate(results['items']): - track = item['track'] - print(idx, track['artists'][0]['name'], " – ", track['name']) diff --git a/examples/unfollow_playlist.py b/examples/unfollow_playlist.py index bf0466fe..eebf216a 100644 --- a/examples/unfollow_playlist.py +++ b/examples/unfollow_playlist.py @@ -4,6 +4,8 @@ import spotipy from spotipy.oauth2 import SpotifyOAuth +scope = 'playlist-modify-public' + logger = logging.getLogger('examples.unfollow_playlist') logging.basicConfig(level='DEBUG') @@ -23,9 +25,9 @@ def get_args(): def main(): args = get_args() - sp = spotipy.Spotify(auth_manager=SpotifyOAuth()) + sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) sp.current_user_unfollow_playlist(args.playlist) if __name__ == '__main__': - main() + main() \ No newline at end of file From b211a1312d461f9c60693a28a6295122b3f0584b Mon Sep 17 00:00:00 2001 From: Jonathan Huston Date: Sun, 10 Dec 2023 14:41:47 -0800 Subject: [PATCH 2/3] Added examples for methods related to audiobooks, shows and episodes --- examples/add_saved_episodes.py | 28 ++++++++++++++++++++++ examples/add_saved_shows.py | 28 ++++++++++++++++++++++ examples/check_show_is_saved.py | 31 +++++++++++++++++++++++++ examples/delete_saved_episodes.py | 28 ++++++++++++++++++++++ examples/get_audiobook_chapters_info.py | 29 +++++++++++++++++++++++ examples/get_audiobooks_info.py | 29 +++++++++++++++++++++++ examples/user_saved_episodes.py | 29 +++++++++++++++++++++++ examples/user_saved_shows.py | 29 +++++++++++++++++++++++ 8 files changed, 231 insertions(+) create mode 100644 examples/add_saved_episodes.py create mode 100644 examples/add_saved_shows.py create mode 100644 examples/check_show_is_saved.py create mode 100644 examples/delete_saved_episodes.py create mode 100644 examples/get_audiobook_chapters_info.py create mode 100644 examples/get_audiobooks_info.py create mode 100644 examples/user_saved_episodes.py create mode 100644 examples/user_saved_shows.py diff --git a/examples/add_saved_episodes.py b/examples/add_saved_episodes.py new file mode 100644 index 00000000..5acc1772 --- /dev/null +++ b/examples/add_saved_episodes.py @@ -0,0 +1,28 @@ +""" +Add episodes to current user's library +Usage: add_saved_episodes.py -e episode_id episode_id ... +""" + +import argparse +import spotipy +from spotipy.oauth2 import SpotifyOAuth + +scope = 'user-library-modify' + +def get_args(): + parser = argparse.ArgumentParser(description='Add episodes to library') + # Default args set to This American Life episodes 814 and 815 + parser.add_argument('-e', '--eids', nargs='+', + default=['6rxg9Lpt2ywNHFea8LxEBO', '7q8or6oYYRFQFYlA0remoy'], + help='Episode ids') + return parser.parse_args() + +def main(): + args = get_args() + print('Adding following episode ids to library: ' + str(args.eids)) + sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) + sp.current_user_saved_episodes_add(episodes=args.eids) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/examples/add_saved_shows.py b/examples/add_saved_shows.py new file mode 100644 index 00000000..ef16258c --- /dev/null +++ b/examples/add_saved_shows.py @@ -0,0 +1,28 @@ +""" +Add shows to current user's library +Usage: add_saved_shows.py -s show_id show_id ... +""" + +import argparse +import spotipy +from spotipy.oauth2 import SpotifyOAuth + +scope = 'user-library-modify' + +def get_args(): + parser = argparse.ArgumentParser(description='Add shows to library') + # Default args set to Radiolab and 99% invisible + parser.add_argument('-s', '--sids', nargs='+', + default=['2hmkzUtix0qTqvtpPcMzEL', '2VRS1IJCTn2Nlkg33ZVfkM'], + help='Show ids') + return parser.parse_args() + +def main(): + args = get_args() + print('Adding following show ids to library: ' + str(args.sids)) + sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) + sp.current_user_saved_shows_add(shows=args.sids) + + +if __name__ == '__main__': + main() diff --git a/examples/check_show_is_saved.py b/examples/check_show_is_saved.py new file mode 100644 index 00000000..eeeb56d9 --- /dev/null +++ b/examples/check_show_is_saved.py @@ -0,0 +1,31 @@ +""" +Check if shows are saved in user's library +Usage: check_show_is_saved -s show_id show_id ... +""" + +import argparse +import spotipy +from spotipy.oauth2 import SpotifyOAuth + +scope = 'user-library-read' + +def get_args(): + parser = argparse.ArgumentParser(description='Check that a show is saved') + # Default args set to Radiolab and 99% invisible + parser.add_argument('-s', '--sids', nargs='+', + default=['2hmkzUtix0qTqvtpPcMzEL', '2VRS1IJCTn2Nlkg33ZVfkM'], + help='Show ids') + return parser.parse_args() + +def main(): + args = get_args() + sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) + results = sp.current_user_saved_episodes_contains(episodes=args.sids) + show_names = sp.shows(shows=args.sids) + # Print show names and if show is saved by current user + for i, show in enumerate(show_names['shows']): + print(show['name'] + ': ' + str(results[i])) + + +if __name__ == '__main__': + main() diff --git a/examples/delete_saved_episodes.py b/examples/delete_saved_episodes.py new file mode 100644 index 00000000..b62f4f04 --- /dev/null +++ b/examples/delete_saved_episodes.py @@ -0,0 +1,28 @@ +""" +Delete episodes from current user's library +Usage: delete_saved_episodes.py -e episode_id episode_id ... +""" + +import argparse +import spotipy +from spotipy.oauth2 import SpotifyOAuth + +scope = 'user-library-modify' + +def get_args(): + parser = argparse.ArgumentParser(description='Delete episodes from library') + # Default args set to This American Life episodes 814 and 815 + parser.add_argument('-e', '--eids', nargs='+', + default=['6rxg9Lpt2ywNHFea8LxEBO', '7q8or6oYYRFQFYlA0remoy'], + help='Episode ids') + return parser.parse_args() + +def main(): + args = get_args() + print('Deleting following episode ids from library: ' + str(args.eids)) + sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) + sp.current_user_saved_episodes_delete(episodes=args.eids) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/examples/get_audiobook_chapters_info.py b/examples/get_audiobook_chapters_info.py new file mode 100644 index 00000000..abbf37a5 --- /dev/null +++ b/examples/get_audiobook_chapters_info.py @@ -0,0 +1,29 @@ +""" +Print chapter titles and lengths for given audiobook +Usage: get_audiobooks_chapters_info.py -a audiobook_id +""" + +import argparse +import spotipy +from spotipy.oauth2 import SpotifyOAuth + + +def get_args(): + parser = argparse.ArgumentParser(description='Get chapter info for an audiobook') + # Default set to Dune + parser.add_argument('-a', '--audiobook', default='2h01INWMBvfpzNMpGFzhdF', help='Audiobook id') + return parser.parse_args() + + +def main(): + args = get_args() + print('Getting chapter info for follow audiobook id: ' + str(args.audiobook)) + sp = spotipy.Spotify(auth_manager=SpotifyOAuth()) + results = sp.get_audiobook_chapters(id=args.audiobook) + # Print chapter name and length + for item in results['items']: + print('Name: ' + item['name'] + ', length: ' + str(round(item['duration_ms']/60000,1)) + ' minutes') + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/examples/get_audiobooks_info.py b/examples/get_audiobooks_info.py new file mode 100644 index 00000000..72fe18d1 --- /dev/null +++ b/examples/get_audiobooks_info.py @@ -0,0 +1,29 @@ +""" +Print audiobook title and description for a list of audiobook ids +Usage: get_audiobooks_info.py -a audiobook_id audiobook_id ... +""" + +import argparse +import spotipy +from spotipy.oauth2 import SpotifyOAuth + +def get_args(): + parser = argparse.ArgumentParser(description='Get information for a list of audiobooks') + # Defaults set to The Great Gatsby, The Chronicles of Narnia and Dune + parser.add_argument('-a', '--aids', nargs='+', + default=['6qjpt1CUHhKXiNoeNoU7nu', '1ezmXd68LbDtxebvygEQ2U', '2h01INWMBvfpzNMpGFzhdF'], + help='Audiobook ids') + return parser.parse_args() + +def main(): + args = get_args() + print('Getting info for follow audiobook ids: ' + str(args.aids) + '\n') + sp = spotipy.Spotify(auth_manager=SpotifyOAuth()) + results = sp.get_audiobooks(ids=args.aids) + # Print book title and description + for book in results['audiobooks']: + print('Title: ' + book['name'] + '\n' + book['description'] + '\n') + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/examples/user_saved_episodes.py b/examples/user_saved_episodes.py new file mode 100644 index 00000000..4a106824 --- /dev/null +++ b/examples/user_saved_episodes.py @@ -0,0 +1,29 @@ +""" +List current user's saved episodes +Usage: user_saved_episodes -l -o +""" + +import argparse +import spotipy +from spotipy.oauth2 import SpotifyOAuth + +scope = 'user-library-read' + +def get_args(): + parser = argparse.ArgumentParser(description='Show user\'s saved episodes') + parser.add_argument('-l', '--limit', default=20, help='Num of episodes to return') + parser.add_argument('-o', '--offset', default=0, help='Index of first show to return') + + return parser.parse_args() + +def main(): + args = get_args() + sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) + results = sp.current_user_saved_episodes(limit=args.limit, offset=args.offset) + # Print episode names + for item in results['items']: + print(item['episode']['name']) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/examples/user_saved_shows.py b/examples/user_saved_shows.py new file mode 100644 index 00000000..ea60f4a0 --- /dev/null +++ b/examples/user_saved_shows.py @@ -0,0 +1,29 @@ +""" +List current user's saved shows +Usage: user_saved_shows -l -o +""" + +import argparse +import spotipy +from spotipy.oauth2 import SpotifyOAuth + +scope = 'user-library-read' + +def get_args(): + parser = argparse.ArgumentParser(description='Show user\'s saved shows') + parser.add_argument('-l', '--limit', default=20, help='Num of shows to return') + parser.add_argument('-o', '--offset', default=0, help='Index of first show to return') + + return parser.parse_args() + +def main(): + args = get_args() + sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) + results = sp.current_user_saved_shows(limit=args.limit, offset=args.offset) + # Print episode names + for item in results['items']: + print(item['show']['name']) + + +if __name__ == '__main__': + main() \ No newline at end of file From 65516f96d1624a14566708ffcdf345974d9876a5 Mon Sep 17 00:00:00 2001 From: Jonathan Huston Date: Sun, 10 Dec 2023 15:41:18 -0800 Subject: [PATCH 3/3] Updated changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99325b57..9dae832d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,11 +13,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added integration tests for audiobook endpoints. - Removed `python 2.7` from GitHub Actions CI workflow. Python v2.7 reached end of life support and is no longer supported by Ubuntu 20.04. - Removed `python 3.6` from GitHub Actions CI workflow. Ubuntu 20.04 is not available in GitHub Actions for `python 3.6`. +- Added examples for audiobooks, shows and episodes methods to examples directory ### Changed - Changes the YouTube video link for authentication tutorial (the old video was in low definition, the new one is in high definition) - Updated links to Spotify in documentation +### Fixed +- Fixed scripts in examples directory that didn't run correctly + ## [2.23.0] - 2023-04-07 ### Added