Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to get metadata of desired track #257

Open
808arc opened this issue May 12, 2023 · 9 comments
Open

Add option to get metadata of desired track #257

808arc opened this issue May 12, 2023 · 9 comments

Comments

@808arc
Copy link

808arc commented May 12, 2023

Firstly, I would like to extend my appreciation for the exceptional tool you have developed!

Could I ask you please to add a method that will return also who produced a track? (I highlighted area with blue color)
If it will be able to implement with return of producer names and their link_pages on Genius.com, I will be kindly appreciated!

Thank you for your attention to this matter and for creating such an impressive tool.

telegram-cloud-photo-size-2-5400194413306692971-y

@allerter
Copy link
Collaborator

You can get the producers of a song if you get the song info from their WebAPI:

genius = lyricsgenius.PublicAPI()

song = genius.song(1)["song"]
for artist in song["producer_artists"]:
    print(artist["name"], sep=", ")

There is a chance this might raise a HTTP 403 error which is referenced in #220

@808arc
Copy link
Author

808arc commented May 27, 2023

Thank you! Im trying to test this way ASAP

@808arc
Copy link
Author

808arc commented May 27, 2023

Hey @allerter,

Just wanted to drop a quick note to say thanks for showing me a way to tackle my idea. I gave it a try, and it worked like a charm!

By the way, I have a small question. It seems that when I set max_songs=10, the code crashes. It only works smoothly if I keep the value at 2 or below.

Here's the code snippet I'm referring to:

genius = lyricsgenius.PublicAPI()

# Search for 10 Drake songs using the 'search_artist' method
artist = genius.search_artist("Drake", max_songs=1)

# Iterate over the songs
for song in artist.songs:
    # Retrieve the information of the song
    song_info = genius.song(song.id)

    # Iterate over the producer artists of the song
    for artist in song_info["song"]["producer_artists"]:
        print(artist["name"], sep=", ")

If you have any tips or insights on how to overcome this issue, I'd really appreciate your help.
Thanks again for your support!

@allerter
Copy link
Collaborator

That is likely because of the timeout errors. You could try increasing the sleep time between each request:

genius = lyricsgenius.PublicAPI(sleep_time=2)

This way, the client waits 2 seconds between each request to the API.

@808arc
Copy link
Author

808arc commented May 29, 2023

Hey @allerter, exciting news! I've fixed my code and now it's returning the exact data I need. I can easily grab the names of the production team members. But here's the deal: I'm now facing a challenge where I want to fetch the producer's Instagram link. Do you reckon it's possible to get it solely using this API? Or should I turn to other tools like the 'scrapy' library? My thought is to search for the producer's page on the Genius website and scrape it smoothly. Your thoughts on this would be highly appreciated!

@allerter
Copy link
Collaborator

allerter commented May 29, 2023

Actually, the WebAPI already provides their Twitter and Instagram username. Try this:

genius = lyricsgenius.PublicAPI(sleep_time=2)
artist = genius.artist(264329)["artist"]
print(artist["instagram_name"])

@808arc
Copy link
Author

808arc commented May 30, 2023

Thank you, @allerter! It's really worked well on me! I will keep updating my code, because I feel I need to find first how to retrieve Genius Artist ID. In order to appreciate your time, does it possible to ask you where can I read more about work with WEB API?

@allerter
Copy link
Collaborator

The WebAPI is the API users use when browsing through the Genius's website. It has no documentation and isn't meant to be used by the developers. Genius has their own official Developer API, but it's very limited, so we resort to their unofficial WebAPI to get the info we want. You can explore the WebAPI by looking at the dictionary objects returned by the methods we use. We also have a reference docs that we've tried to implement all the WebAPI endpoints in.

@Lionheartxx
Copy link

Lionheartxx commented Feb 1, 2024

Hi dear @allerter
I have the same error!!!
If i deploy my telegram bot project to server i get 403 forbidden error but when i run local in PyCharm everything works
This my Code:

import numpy as np
from requests.exceptions import HTTPError, Timeout
import lyricsgenius

from aiogram import types
from data.config import GENIUS_ACCESS_TOKEN,GENIUS_CLIENT_ID,GENIUS_CLIENT_SECRET,GENIUS_REDIRECT_URI
from keyboards.inline.SelectButton import SelectSong
from aiogram.types import CallbackQuery
from aiogram.dispatcher.filters import Command
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.dispatcher import FSMContext

from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session

from loader import dp

class OAuth2Genius(StatesGroup):
    waiting_for_code = State()


GENIUS_API_BASE_URL = 'https://api.genius.com'

def create_genius_session(token=None, state=None):
    client = BackendApplicationClient(client_id=GENIUS_CLIENT_ID)
    genius3 = OAuth2Session(client=client, token=token, redirect_uri=GENIUS_REDIRECT_URI, state=state)
    return genius3

@dp.message_handler(Command("start"))
async def start_auth(message: types.Message):
    # Start the Genius OAuth2 flow
    genius3 = create_genius_session()
    authorization_url, state = genius3.authorization_url('https://api.genius.com/oauth/authorize')

    await message.answer("To authorize, click on this [link]({})".format(authorization_url), parse_mode='Markdown')
    await OAuth2Genius.waiting_for_code.set()

@dp.message_handler(state=OAuth2Genius.waiting_for_code)
async def receive_auth_code(message: types.Message, state: FSMContext):
    # Receive the Genius OAuth2 code and exchange it for a token
    genius3 = create_genius_session(state=state)
    token = genius3.fetch_token('https://api.genius.com/oauth/token', authorization_response=message.text,
                               client_secret=GENIUS_CLIENT_SECRET)

    # Save the token to use later in your requests
    await state.finish()
    await message.answer("Authorization successful! You can now use Genius API.")
    # Store the token somewhere secure for future use (e.g., a database)

    global genius2
    genius2 = create_genius_session(token=token)

genius = lyricsgenius.Genius(GENIUS_ACCESS_TOKEN)
numbered_songs = []

@dp.message_handler()
async def Send_List(message: types.Message):
    def ListOfSongs(search_songs):
        try:
            song = genius.search_songs(f"{search_songs}")

            list_of_artist = []
            list_of_song = []

            for hit in song['hits']:
                list_of_artist.append(hit['result']['primary_artist']['name'])
                list_of_song.append(hit['result']['title'])

            arr = np.dstack((list_of_artist, list_of_song))
            len_arr = len(arr[0])

            for res in arr[0][range(0, len_arr)]:
                numbered_songs.append(f"{res[0]} - {res[1]}")

        except HTTPError as e:
            print(e.errno)
            print(e.args[0])
            print(e.args[1])
        except Timeout:
            pass

    if len(numbered_songs) == 0:
        ListOfSongs(search_songs=message.text)
    else:
        numbered_songs.clear()
        ListOfSongs(search_songs=message.text)

    result_count = min(len(numbered_songs), 10)

    if result_count >= 1:
        await message.answer(
            f"<b>Результаты 1-{result_count}</b>\n\n"
            + "\n".join(f"{i + 1}.  {numbered_songs[i]}" for i in range(result_count)),
            reply_markup=SelectSong
        )
    else:
        await message.answer("Такой песен не найдено 🤔")

@dp.callback_query_handler(lambda call: call.data.isdigit())
async def Send_Lyric(call: CallbackQuery):
    index = int(call.data)

    if 1 <= index <= len(numbered_songs):
        await call.message.delete()
        await call.message.answer("🔎 Ищу тексты песен...")

        full_text = await GetText(numbered_songs[index - 1])

        if full_text:
            # Telegramning maksimal belgilar soni 4040 ta
            if len(full_text) <= 4020:
                await call.message.answer(full_text)
            else:
                short_text = full_text[:4020]
                await call.message.answer(short_text + f"...\n\n<i>через @MusixMBot</i>")
        else:
            await call.message.answer("Извините, такого текста не найдено 🫥")

async def GetText(song_name):
    artist_name, song_get_name = map(str.strip, song_name.split("-"))

    try:
        artist = genius.search_artist(artist_name, max_songs=1)
        song_text = artist.song(song_get_name)
        text = song_text.lyrics

        return f"<code>{artist_name} - {song_get_name}</code>\n\n{text[:-5]}\n\n<i>через @MusixMBot</i>"

    except HTTPError as e:
        print(e.errno)
        print(e.args[0])
        print(e.args[1])

    except Timeout:
        pass

    return None

image

I used the liyricsgenius package. But I don't know how to integrate Genius authentication method into Code. If anyone knows, please help!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants