class GoYandex(): def __init__(self, setting): self.client = Client() super().__init__() self.select_PL = None self.start_load_Pl = False self.start_download = False self.this = None self.list_track = [] self.setting = setting self.play_lists_info = dict() def generate_token(self, login, pas): try: token = self.client.generate_token_by_username_and_password( username=login, password=pas) self.setting.save('token', token) return False except Exception as e: if e.args[0].startswith('invalid_grant'): err = e.args[0][14:] logging.getLogger(err) else: err = e.args[0] logging.getLogger(err) return err def authorization_token(self, token): try: self.client = Client.from_token(token) except Exception as e: logging.getLogger(e.args[0]) def get_play_lists_info(self): # FIXME: убрать после теста долгой загрузки # time.sleep(5) # run in Thread try: personal_playlist_blocks = self.client.landing( blocks=['personalplaylists']).blocks[0] except Exception as e: logging.getLogger(e.args[0]) return False for plLst in personal_playlist_blocks.entities: if plLst.data.data.play_counter is not None: pc = plLst.data.data.play_counter pc.description = pc.description.replace(' ', ' ') pc.description = pc.description.replace('—', '–') self.play_lists_info[ plLst.data.data.generated_playlist_type] = plLst.data.data return True def get_play_list(self): # run in Thread if not self.get_play_lists_info(): return if self.this.play_list_type not in self.play_lists_info: # FIXME: выбрать поле для вывода информации print('Не удалось найти плейлист') logging.getLogger('Не удалось найти плейлист') self.start_load_Pl = False return daily_play_list = self.play_lists_info[self.this.play_list_type] self.list_track.clear() self.select_PL = self.client.users_playlists( user_id=daily_play_list.uid, kind=daily_play_list.kind) plTitle = self.select_PL[0].title plCount = self.select_PL[0].track_count self.this.set_title(plTitle) for counter, track in enumerate(self.select_PL[0].tracks, 1): self.list_track.append(track.track) self.this.set_title(f'{plTitle} - {counter}/{plCount}') if self.this.play_list_type != 'podcasts': try: artist = track.track.artists[0].name except IndexError: artist = '<BREAK>' else: artist = track.track.albums[0].title self.this.add_row(counter, track.track.title, artist, utils.timeStr(track.track.duration_ms)) if not self.start_load_Pl: self.this.set_title(f'{plTitle} - {counter}/{plCount} - BREAK') break else: duration = utils.timeStr(self.select_PL[0].duration_ms, 0) self.this.set_title(f'{plTitle} - {duration}') self.this.set_normal_status() self.start_load_Pl = False def save_tracks(self): ''' Скачивание треков и задание id3-тегов ''' # run in Thread self.this.show_prigress_bar() self.this.set_prigress_bar(0) for num, track in enumerate(self.list_track, 1): if self.this.play_list_type != 'podcasts': if len(track.artists): artist = track.artists[0].name else: artist = '' else: artist = track.albums[0].title path = self.this.get_path() file_name = f'[{track.real_id}] {artist} - {track.title}' file_name = utils.delSpecCh(file_name) file_name = f'{path}{file_name}.mp3' print(file_name) if os.path.isfile(file_name): # Трек уже скачан и находится в папке self.this.set_prigress_bar((num / len(self.list_track)) * 100) continue track.download(file_name) # FIXME add exception () mp3file = MetadataMP3(file_name) mp3file.set_tags( artist=artist, title=track.title, album=track.albums[0].title, # FIX track_num=track.albums[0].track_position.index, year=track.albums[0].year, genre=track.albums[0].genre) mp3file.set_image(track.og_image) mp3file.save() self.this.set_prigress_bar((num / len(self.list_track)) * 100) if not self.start_download: # Пользователь прервал скачивание break self.this.set_normal_status() self.this.hide_prigress_bar() self.start_download = False
class YamService(Service): def __init__(self, bot: Bot, config: YamModel): self.bot = bot self.config = config self.name = "yam" self.hostnames = ["music.yandex.ru"] self.is_enabled = self.config.enabled self.error_message = "" self.warning_message = "" self.help = "" self.hidden = False self.format = ".mp3" def initialize(self): self.api = Client(token=self.config.token) try: self.api.init() except (UnauthorizedError, NetworkError) as e: logging.error(e) raise errors.ServiceError(e) if not self.api.account_status().account.uid: self.warning_message = self.bot.translator.translate( "Token is not provided") elif not self.api.account_status().plus["has_plus"]: self.warning_message = self.bot.translator.translate( "You don't have Yandex Plus") def get( self, url: str, extra_info: Optional[Dict[str, Any]] = None, process: bool = False, ) -> List[Track]: if not process: parsed_data = urlparse(url) path = parsed_data.path if "/album/" in path and "/track/" in path: split_path = path.split("/") real_id = split_path[4] + ":" + split_path[2] return self.get(None, extra_info={"track_id": real_id}, process=True) elif "/album/" in path: tracks = [] album = self.api.albums_with_tracks(path.split("/")[2]) if len(album.volumes) == 0 or len(album.volumes[0]) == 0: raise errors.ServiceError() for volume in album.volumes: for track in volume: tracks.append( Track( service=self.name, extra_info={"track_id": track.track_id}, type=TrackType.Dynamic, )) return tracks if "/artist/" in path: tracks = [] artist_tracks = self.api.artists_tracks( path.split("/")[2]).tracks if len(artist_tracks) == 0: raise errors.ServiceError() for track in artist_tracks: tracks.append( Track( service=self.name, extra_info={"track_id": track.track_id}, type=TrackType.Dynamic, )) return tracks elif "users" in path and "playlist" in path: tracks = [] split_path = path.split("/") user_id = split_path[2] kind = split_path[4] playlist = self.api.users_playlists(kind=kind, user_id=user_id) if playlist.track_count == 0: raise errors.ServiceError() for track in playlist.tracks: tracks.append( Track( service=self.name, extra_info={"track_id": track.track_id}, type=TrackType.Dynamic, )) return tracks else: track = self.api.tracks(extra_info["track_id"])[0] return [ Track( service=self.name, name="{} - {}".format(" & ".join(track.artists_name()), track.title), url=track.get_download_info( get_direct_links=True)[0].direct_link, type=TrackType.Default, format=self.format, ) ] def search(self, query: str) -> List[Track]: tracks: List[Track] = [] found_tracks = self.api.search(text=query, nocorrect=True, type_="all").tracks if found_tracks: for track in found_tracks.results: tracks.append( Track( service=self.name, type=TrackType.Dynamic, extra_info={"track_id": track.track_id}, )) found_podcast_episodes = self.api.search( text=query, nocorrect=True, type_="podcast_episode").podcast_episodes if found_podcast_episodes: for podcast_episode in found_podcast_episodes.results: tracks.append( Track( service=self.name, type=TrackType.Dynamic, extra_info={"track_id": podcast_episode.track_id}, )) if tracks: return tracks else: raise errors.NothingFoundError("")