def get_url_from_yandex_by_artist_and_title(artist, title):
    from yandex_music.utils.request import Request
    from yandex_music import Client

    request = Request(proxy_url='socks5://socks.zaborona.help:1488')
    client = Client(request=request)
    query = artist + " " + title
    search_result = client.search(query)

    if len(search_result['tracks']['results']) != 0:
        best = search_result['tracks']['results'][0]
        full_id = best.track_id.split(':')
        album_id = full_id[1]
        track_id = full_id[0]
        return "https://music.yandex.ru/album/" + album_id + "/track/" + track_id
    else:
        return "None"
Example #2
0
def text(message):
	if 'https://music.apple.com' in message.text:
		# print(message.text)
		resp = requests.get(message.text, verify=False).text
		soup = BeautifulSoup(resp, 'lxml')
		ex = 0
    # определяем музыканта [ ,альбом] [, название композиции]
		try:
			musician = ' '.join(soup.find('div', {'class': 'product-creator typography-large-title'}).text.strip().split())
		except: 
			musician = ' '.join(soup.find('h1', {'class': 'typography-header-emphasized artist-header__product-title-product-name artist-header__product-title-product-name--non-persistent-color'}).text.strip())
		try:
			album = ' '+soup.find('h1', {'class': 'product-name typography-large-title-semibold clamp-4'}).text.strip()
		except: album = ''
		try:
			select_track = ' '+soup.find('div', {'aria-checked': 'true'}).text.strip()
			tracks = soup.find_all('div', {'class': 'songs-list-row songs-list-row--selected selected songs-list-row--web-preview web-preview songs-list-row--song'})
			for i in tracks:
				if 'aria-checked="true"' in str(i):
					index = int(i['data-row'])
      #если мы даём ссылку на конкретную композицию, то скачаем и отправим в чат 1,5минутный отрывок
			example = soup.find('script', {'id': 'shoebox-media-api-cache-amp-music'}).text.replace('\\', '')
			example = re.findall('(https://audio-ssl.itunes.apple.com/[^"]+)', example)[index]
			example = requests.get(example, verify=False).content
			ex = 1
		except: select_track = ''
		# print(musician, album, select_track)

		#yandex
		ym_service = YMClient()
		search_result = ym_service.search(musician+album+select_track)
		if select_track!='':
			yalink = f"https://music.yandex.ru/track/{search_result['tracks']['results'][0]['id']}"
		elif album!='':
			yalink = f"https://music.yandex.ru/album/{search_result['albums']['results'][0]['id']}"
		else:
			yalink = f"https://music.yandex.ru/artist/{search_result['artists']['results'][0]['id']}"

		#spoty
		head = {
		'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"',
		'sec-ch-ua-mobile': '?0',
		'Upgrade-Insecure-Requests': '1',
		'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'
		}
		resp = requests.get(f'https://open.spotify.com/search/{musician}{album}{select_track}', headers=head, verify=False).text
		soup = BeautifulSoup(resp, 'lxml')
		bearer = eval(soup.find('script').text.replace('true', 'True').replace('false','False').replace('null','None').strip())['accessToken']
		head = {'authorization':f'Bearer {bearer}'}
		resp = requests.get(f'https://api.spotify.com/v1/search?type=album%2Cartist%2Cplaylist%2Ctrack%2Cshow_audio%2Cepisode_audio&q={musician}+{album}+{select_track}&decorate_restrictions=false&best_match=true&include_external=audio&limit=10&market=RU', headers=head, verify=False).json()
		try:
			if select_track!='':
				spoty = resp['tracks']['items'][0]['external_urls']['spotify']
			elif album!='':
				spoty = resp['albums']['items'][0]['external_urls']['spotify']
			else:
				spoty = resp['artists']['items'][0]['external_urls']['spotify']
		except: spoty = ''

		while True:
			try:
				if spoty!='':
					bot.reply_to(message, f"<a href='{yalink}'>ссылка на Яндекс.Музыку\n</a><a href='{spoty}'>ссылка на Spotify</a>", parse_mode='html', disable_web_page_preview=True)
				else:
          #spotify хуже справляется с поиском
					bot.reply_to(message, f"<a href='{yalink}'>ссылка на Яндекс.Музыку</a>", parse_mode='html', disable_web_page_preview=True)
				if ex==1:
					bot.send_audio(message.chat.id, example)
				break
			except: pass
Example #3
0
class YandexMusic(MusicService):
    name = "YandexMusic"

    def __init__(self):
        self.client = Client()
        self.url_regex = re.compile(
            r'((http|https)://)?(www\.)?music\.yandex\.(ru|com)\/album\/([0-9]+)\/track\/([0-9]+)'
        )
        self.url_without_album_regex = re.compile(
            r'((http|https)://)?(www\.)?music\.yandex\.(ru|com)\/track\/([0-9]+)'
        )
        self.url_artist_regex = re.compile(
            r'((http|https)://)?(www\.)?music\.yandex\.(ru|com)\/artist\/([0-9]+)'
        )
        self.url_album_regex = re.compile(
            r'((http|https)://)?(www\.)?music\.yandex\.(ru|com)\/album\/([0-9]+)'
        )

    # link example: https://music.yandex.ru/album/43233/track/418016
    # regex: ((http|https)://)?(www\.)?music\.yandex\.(ru|com)\/album\/([0-9]+)\/track\/([0-9]+)
    # link example: https://music.yandex.ru/track/418016
    # regex: ((http|https)://)?(www\.)?music\.yandex\.(ru|com)\/track\/([0-9]+)

    @staticmethod
    def get_track_id_from_match(match):
        return match[6] + ":" + match[5]

    @staticmethod
    def get_entity_id_from_match(match):
        return match[5]

    def search_track_by_link(self, link):
        match = self.url_regex.match(link)
        if not match is None:
            track_id = self.get_track_id_from_match(match)
        else:
            match = self.url_without_album_regex.match(link)
            if match is None:
                return None
            track_id = self.get_entity_id_from_match(match)
        tracks = self.client.tracks([track_id])
        if len(tracks) == 0:
            return None
        else:
            track = tracks[0].title
            artists = [artist.name for artist in tracks[0].artists]
            album = tracks[0].albums[0].title if len(
                tracks[0].albums) != 0 else None
            return track, artists, album, self._get_entity_id(
                track_id, self.Entity.Track)

    def search_track(self, track, artists, album=None):
        query = ', '.join(artists) + " - " + track
        result = self.client.search(text=query, type_='track')
        if not result.tracks or result.tracks.total == 0:
            return None
        id = result.tracks.results[0].track_id
        if id.find(":") != -1:
            track_id, album_id = id.split(':')
            return "https://music.yandex.ru/album/%s/track/%s" % (album_id,
                                                                  track_id)
        else:
            return "https://music.yandex.ru/track/%s" % id

    def search_track_by_query(self, query, limit=None):
        if not limit:
            limit = self.default_limit

        result = self.client.search(text=query, type_='track')
        if not result.tracks or result.tracks.total == 0:
            return []
        tracks = result.tracks.results[:limit]

        track_list = []
        for track in tracks:
            track_json = {
                'track': track.title,
                'artists': [artist.name for artist in track.artists],
            }
            if len(track.track_id.split(':')) == 2:
                track_id, album_id = track.track_id.split(':')
                track_json[
                    'url'] = "https://music.yandex.ru/album/%s/track/%s" % (
                        album_id, track_id)
            else:
                track_json[
                    'url'] = "https://music.yandex.ru/track/%s" % track.track_id
            if track.albums and len(track.albums) > 0:
                track_json['album'] = track.albums[0].title
            track_list.append(track_json)
        response = {'service_name': self.name, 'tracks': track_list}
        return response

    # https://music.yandex.ru/artist/41126
    def search_artist_by_link(self, link):
        match = self.url_artist_regex.match(link)
        if match:
            artist_id = self.get_entity_id_from_match(match)
        else:
            return None

        artists = self.client.artists(artist_id)
        if len(artists) == 0:
            return None
        else:
            return artists[0].name, self._get_entity_id(
                artist_id, self.Entity.Artist)

    def search_artist(self, name):
        result = self.client.search(text=name, type_='artist')
        if not result.artists or result.artists.total == 0:
            return None
        artist_id = result.artists.results[0].id
        return "https://music.yandex.ru/artist/%s" % artist_id

    # https://music.yandex.ru/album/14619914
    def search_album_by_link(self, link):
        match = self.url_album_regex.match(link)
        if match:
            album_id = self.get_entity_id_from_match(match)
        else:
            return None

        albums = self.client.albums(album_id)
        if len(albums) == 0:
            return None
        else:
            return albums[0].title, self._get_entity_id(
                album_id, self.Entity.Album)

    def search_album(self, name):
        result = self.client.search(text=name, type_='album')
        if not result.albums or result.albums.total == 0:
            return None
        album_id = result.albums.results[0].id
        return "https://music.yandex.ru/album/%s" % album_id

    def detect_entity_by_link(self, link):
        if link.find("track") != -1:
            return self.Entity.Track
        elif link.find('album') != -1:
            return self.Entity.Album
        elif link.find('artist') != -1:
            return self.Entity.Artist
        else:
            return None

    @staticmethod
    def _entity_type_to_string(entity: MusicService.Entity):
        if entity == MusicService.Entity.Album:
            return "album"
        elif entity == MusicService.Entity.Track:
            return "track"
        elif entity == MusicService.Entity.Artist:
            return "artist"
        else:
            return None

    @staticmethod
    def _extract_track_data(track_json):
        album = track_json.albums[0].title if track_json.albums and len(
            track_json.albums) > 0 else track_json.title
        return {
            'track': track_json.title,
            'album': album,
            'artists': [artist.name for artist in track_json.artists],
            'url': "https://music.yandex.ru/track/%s" % track_json.track_id
        }

    @staticmethod
    def _extract_album_data(album_json):
        return {
            'album': album_json.title,
            'artists': [artist.name for artist in album_json.artists],
            'url': "https://music.yandex.ru/album/%s" % album_json.id
        }

    @staticmethod
    def _extract_artist_data(artist_json):
        return {
            'artist': artist_json.name,
            'url': "https://music.yandex.ru/artist/%s" % artist_json.id
        }

    @staticmethod
    def _extract_search_data(data_json, entity):
        if entity == MusicService.Entity.Album:
            return YandexMusic._extract_album_data(data_json)
        elif entity == MusicService.Entity.Track:
            return YandexMusic._extract_track_data(data_json)
        elif entity == MusicService.Entity.Artist:
            return YandexMusic._extract_artist_data(data_json)
        else:
            return None

    def search_by_query(self,
                        query,
                        entity: MusicService.Entity,
                        limit=MusicService.default_limit):
        entity_str = self._entity_type_to_string(entity)
        if not entity_str:
            return None
        plural_entity_str = entity_str + "s"
        entity_list = []
        count = limit
        page = 0
        while count > 0:
            results = self.client.search(text=query,
                                         type_=entity_str,
                                         page=page)
            if results[plural_entity_str].results is None:
                return None
            results = results[plural_entity_str].results[:count]
            if len(results) == 0:
                break
            for result in results:
                entity_list.append(self._extract_search_data(result, entity))
                count -= 1
            page += 1
        response = {'service_name': self.name, plural_entity_str: entity_list}
        return response
Example #4
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("")