diff --git a/examples/player.py b/examples/player.py new file mode 100644 index 0000000..2fe913b --- /dev/null +++ b/examples/player.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +import sys +import argparse +import re +from time import sleep +from subprocess import call +from pathlib import Path +from typing import List + +# sys.path.append('../yandex-music-api/') +from yandex_music import Client + +DEFAULT_CACHE_FOLDER = Path(__file__).resolve().parent / '.YMcache' +CONFIG_NAME = 'config' +MAX_ERRORS = 3 + +parser = argparse.ArgumentParser() +parser.add_argument('playlist', choices=('likes', 'user'), help='playlist type') +# sub_parser = parser.add_subparsers(title='playlist type', +# dest='playlist', required=True) +# sub_parser.add_parser('likes') +# user_parser = sub_parser.add_parser('user') +parser.add_argument('--playlist-name', # required=True, + help='name of user playlist') + +parser.add_argument('--skip', metavar='N', type=int, + help='skip first %(metavar)s tracks') +parser.add_argument('--shuffle', action='store_true', + help='randomize tracks order') +parser.add_argument('--token', default=DEFAULT_CACHE_FOLDER / CONFIG_NAME, + help='YM API token as string or path to file') +parser.add_argument('--no-save-token', action='store_true', + help='do\'nt save token in cache folder') +parser.add_argument('--cache-folder', type=Path, default=DEFAULT_CACHE_FOLDER, + help='cached tracks folder') +parser.add_argument('--audio-player', default='cvlc', + help='player to use') +parser.add_argument('--audio-player-args', action='append', default=[], + help='args for --audio-player (can be specified multiple times)') +parser.add_argument('--print-args', action='store_true') +args = parser.parse_args() + +if args.audio_player is parser.get_default('audio_player')\ + and args.audio_player_args is parser.get_default('audio_player_args'): + args.audio_player_args = ['--play-and-exit', '--quiet'] +player_cmd: List[int] = args.audio_player_args +player_cmd.insert(0, args.audio_player) +player_cmd.append('') # will be replaced with filename + +if args.print_args: + print(args) + sys.exit() + +if type(args.token) is str and re.match(r'^[A-z0-9]{39}$', args.token): + if not args.no_save_token: + parser.get_default('token').write_text(args.token) + pass +else: + try: + args.token = Path(args.token).read_text() + except FileNotFoundError: + print('Config file not found. Use --token to create it') + sys.exit(2) + +client = Client.from_token(args.token, report_new_fields=False) + +print('Hello,', client.me.account.first_name) +if client.me.account.now and client.me.account.now.split('T')[0] == client.me.account.birthday: + print('Happy birthday!') + +if args.playlist == 'user': + user_playlists = client.users_playlists_list() + if not args.playlist_name: + print('specify --playlist-name', list(p.title for p in user_playlists)) + sys.exit(1) + playlist = next(p for p in user_playlists if p.title == args.playlist_name) + total_tracks = playlist.track_count + print(f'Playing {playlist.title} ({playlist.playlist_id}). {total_tracks} track(s).') + tracks = playlist.tracks if playlist.tracks else playlist.fetch_tracks() +elif args.playlist == 'likes': + tracks = client.users_likes_tracks() + total_tracks = len(tracks.tracks) + print(f'Playing liked tracks. {total_tracks} track(s).') + +if args.shuffle: + from random import shuffle + shuffle(tracks.tracks) + +error_count = 0 +for (i, short_track) in enumerate(tracks): + if args.skip and args.skip > i: + continue + + while error_count < MAX_ERRORS: + try: + track = short_track.track if short_track.track else short_track.fetchTrack() + + print(f'Now playing {i + 1}/{total_tracks}:', + '|'.join(a.name for a in track.artists), + f"[{'|'.join(a.title for a in track.albums)}]", '~', track.title) + + artist_dir = Path(f'{track.artists[0].name}_{track.artists[0].id}') + album_dir = Path(f'{track.albums[0].title}_{track.albums[0].id}') + file_path = args.cache_folder / artist_dir / album_dir / f'{track.title}_{track.id}.mp3' + + if not file_path.exists(): + print('Downloading...') + file_path.parent.mkdir(parents=True, exist_ok=True) + while error_count < MAX_ERRORS: + try: + track.download(file_path) + error_count = 0 + break + except Exception as e: + print('Error:', e) + error_count += 1 + sleep(1) + + + player_cmd[-1] = file_path + if call(player_cmd) == 0: + error_count = 0 + else: + error_count += 1 + break + except Exception as e: + print('Error:', e) + # sys.exc_info() + error_count += 1 + sleep(1)