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"
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
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
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("")