Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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("")