1

我正在制作一个 Discord 歌词机器人并接收歌词。我正在使用天才 API(lyricsgeniusAPI 包装器)。但是当我收到歌词时,它以这样的方式结束:

“离开”是这首歌的最后一个词,但它伴随着EmbedShare URLCopyEmbedCopy。有时它只是没有EmbedShare文字的简单歌词。

用同一首歌:

有没有办法阻止这种情况?

命令的源代码lyrics

@commands.command(help="Gives the lyrics of the song XD! format //lyrics (author) (song name)")
async def lyrics(self, ctx, arg1, arg2):
    song = genius.search_song(arg1, arg2)
    print(song.lyrics)
    name = ("Lyrics for " + arg2.capitalize() + " by " + arg1.capitalize())
    gembed = discord.Embed(title=name.capitalize(), description=song.lyrics)
    await ctx.send(embed=gembed)
4

2 回答 2

0

这是一个已知的错误,lyricsgenius并且有一个开放的 PR 来解决这个问题:https ://github.com/johnwmillr/LyricsGenius/pull/215 。

这是因为lyricsgenius网络会从 Genius 网站上抓取歌词,这意味着如果他们的网站更新,lyricsgenius将无法获取歌词。此库已 6 个月未更新;本身是一个网络抓取库意味着这种不活动会导致库严重不稳定。由于该库在 MIT 下获得许可,因此您可以分叉该库并为您的项目/机器人维护最新版本。但是,最好使用专用的 API 来获取歌曲歌词以保证稳定性。

此外,lyricsgenius使用同步requests库,这意味着它会在获取歌词时“阻止”您的异步机器人。这对于 Discord Bot 来说绝对是不可取的,因为您的 bot 在获取歌词时将完全没有响应。考虑在调用阻塞函数时使用aiohttp或使用重写它。run_in_executor

于 2021-10-21T12:10:59.947 回答
0

当您创建将向您发送歌词的命令时,一些 Random API很容易处理。

这是使用一些随机 api 的方法,

# these imports are used for this particular lyrics command. the essential import here is aiohttp, which will be used to fetch the lyrics from the API
import textwrap
import urllib
import aiohttp
import datetime

@bot.command(aliases = ['l', 'lyrc', 'lyric']) # adding aliases to the command so they they can be triggered with other names
async def lyrics(ctx, *, search = None):
    """A command to find lyrics easily!"""
    if not search: # if user hasnt given an argument, throw a error and come out of the command
        embed = discord.Embed(
            title = "No search argument!",
            description = "You havent entered anything, so i couldnt find lyrics!"
        )
        return await ctx.reply(embed = embed)
        # ctx.reply is available only on discord.py version 1.6.0, if you have a version lower than that use ctx.send
    
    song = urllib.parse.quote(search) # url-encode the song provided so it can be passed on to the API
    
    async with aiohttp.ClientSession() as lyricsSession:
        async with lyricsSession.get(f'https://some-random-api.ml/lyrics?title={song}') as jsondata: # define jsondata and fetch from API
            if not 300 > jsondata.status >= 200: # if an unexpected HTTP status code is recieved from the website, throw an error and come out of the command
                return await ctx.send(f'Recieved poor status code of {jsondata.status}')

            lyricsData = await jsondata.json() # load the json data into its json form

    error = lyricsData.get('error')
    if error: # checking if there is an error recieved by the API, and if there is then throwing an error message and returning out of the command
        return await ctx.send(f'Recieved unexpected error: {error}')

    songLyrics = lyricsData['lyrics'] # the lyrics
    songArtist = lyricsData['author'] # the author's name
    songTitle = lyricsData['title'] # the song's title
    songThumbnail = lyricsData['thumbnail']['genius'] # the song's picture/thumbnail

    # sometimes the song's lyrics can be above 4096 characters, and if it is then we will not be able to send it in one single message on Discord due to the character limit
    # this is why we split the song into chunks of 4096 characters and send each part individually
    for chunk in textwrap.wrap(songLyrics, 4096, replace_whitespace = False):
        embed = discord.Embed(
            title = songTitle,
            description = chunk,
            color = discord.Color.blurple(),
            timestamp = datetime.datetime.utcnow()
        )
        embed.set_thumbnail(url = songThumbnail)
        await ctx.send(embed = embed)
于 2021-10-21T08:47:44.957 回答