user10863293
user10863293

Reputation: 876

How can I resolve the error 'str' object has no attribute 'is_paused' in discord.py?

[2023-02-19 05:14:12] [ERROR ] discord.ext.commands.bot: Ignoring exception in command play Traceback (most recent call last): File "C:\Users\toto\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\core.py", line 229, in wrapped ret = await coro(*args, **kwargs) File "C:\Users\toto\PycharmProjects\pythonProject\music_bot-main\main.py", line 101, in play elif self.is_paused: AttributeError: 'str' object has no attribute 'is_paused'

The above exception was the direct cause of the following exception:

Traceback (most recent call last): File "C:\Users\toto\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\bot.py", line 1349, in invoke await ctx.command.invoke(ctx) File "C:\Users\toto\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\core.py", line 1023, in invoke await injected(*ctx.args, **ctx.kwargs) # type: ignore File "C:\Users\toto\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\core.py", line 238, in wrapped raise CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'str' object has no attribute 'is_paused'

import discord
from discord.ext import commands
import os
import asyncio

# import all of the cogs
# from help_cog import help_cog
# from music_cog import music_cog

intents = discord.Intents.all()
client = commands.Bot(command_prefix='.', intents=intents)

@client.event
async def on_ready():
    print(f'Logged in as {client.user} (ID: {client.user.id})')
    print('------')


# remove the default help command so that we can write out own
client.remove_command('help')


# register the class with the bot
# bot.add_cog(help_cog(bot))
# client.add_cog(music_cog(client))
# code du bot
class music_cog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

        # all the music related stuff
        self.is_playing = False
        self.is_paused = False

        # 2d array containing [song, channel]
        self.music_queue = []
        self.YDL_OPTIONS = {'format': 'bestaudio', 'noplaylist': 'True'}
        self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
                               'options': '-vn'}

        self.vc = None

    # searching the item on youtube
    def search_yt(self, item):
        with YoutubeDL(self.YDL_OPTIONS) as ydl:
            try:
                info = ydl.extract_info("ytsearch:%s" % item, download=False)['entries'][0]
            except Exception:
                return False

        return {'source': info['formats'][0]['url'], 'title': info['title']}

    def play_next(self):
        if len(self.music_queue) > 0:
            self.is_playing = True

            # get the first url
            m_url = self.music_queue[0][0]['source']

            # remove the first element as you are currently playing it
            self.music_queue.pop(0)

            self.vc.play(discord.FFmpegPCMAudio(m_url, **self.FFMPEG_OPTIONS), after=lambda e: self.play_next())
        else:
            self.is_playing = False

    # infinite loop checking
    async def play_music(self, ctx):
        if len(self.music_queue) > 0:
            self.is_playing = True

            m_url = self.music_queue[0][0]['source']

            # try to connect to voice channel if you are not already connected
            if self.vc == None or not self.vc.is_connected():
                self.vc = await self.music_queue[0][1].connect()

                # in case we fail to connect
                if self.vc == None:
                    await ctx.send("Could not connect to the voice channel")
                    return
            else:
                await self.vc.move_to(self.music_queue[0][1])

            # remove the first element as you are currently playing it
            self.music_queue.pop(0)

            self.vc.play(discord.FFmpegPCMAudio(m_url, **self.FFMPEG_OPTIONS), after=lambda e: self.play_next())
        else:
            self.is_playing = False


@client.command(name="play", aliases=["p", "playing"], help="Plays a selected song from youtube")
async def play(ctx, self, *args):
    query = " ".join(args)

    voice_channel = ctx.author.voice.channel
    if voice_channel is None:
        # you need to be connected so that the bot knows where to go
        await ctx.send("Connect to a voice channel!")
    elif self.is_paused:
        self.vc.resume()
    else:
        song = self.search_yt(query)
        if type(song) == type(True):
            await ctx.send(
                "Could not download the song. Incorrect format try another keyword. This could be due to playlist or a livestream format.")
        else:
            await ctx.send("Song added to the queue")
            self.music_queue.append([song, voice_channel])

            if self.is_playing == False:
                await self.play_music(ctx)


@client.command(name="pause", help="Pauses the current song being played")
async def pause(self, ctx, *args):
    if self.is_playing:
        self.is_playing = False
        self.is_paused = True
        self.vc.pause()
    elif self.is_paused:
        self.is_paused = False
        self.is_playing = True
        self.vc.resume()


@client.command(name="resume", aliases=["r"], help="Resumes playing with the discord bot")
async def resume(self, ctx, *args):
    if self.is_paused:
        self.is_paused = False
        self.is_playing = True
        self.vc.resume()


@client.command(name="skip", aliases=["s"], help="Skips the current song being played")
async def skip(self, ctx):
    if self.vc != None and self.vc:
        self.vc.stop()
        # try to play next in the queue if it exists
        await self.play_music(ctx)


@client.command(name="queue", aliases=["q"], help="Displays the current songs in queue")
async def queue(self, ctx):
    retval = ""
    for i in range(0, len(self.music_queue)):
        # display a max of 5 songs in the current queue
        if (i > 4): break
        retval += self.music_queue[i][0]['title'] + "\n"

    if retval != "":
        await ctx.send(retval)
    else:
        await ctx.send("No music in queue")


@client.command(name="clear", aliases=["c", "bin"], help="Stops the music and clears the queue")
async def clear(self, ctx):
    if self.vc != None and self.is_playing:
        self.vc.stop()
    self.music_queue = []
    await ctx.send("Music queue cleared")


@client.command(name="leave", aliases=["disconnect", "l", "d"], help="Kick the bot from VC")
async def dc(self, ctx):
    self.is_playing = False
    self.is_paused = False
    await self.vc.disconnect()


@client.command()
async def bonjour(ctx):
    await ctx.send("Bonjour")


# start the bot with our token

client.run(os.getenv("TOKEN"))

Upvotes: 0

Views: 356

Answers (1)

ESloman
ESloman

Reputation: 2102

You've given lots of non-class methods the self parameter. So self ends up being your context object and ctx the command argument. Just remove self from the methods that don't need it. ie, every method that doesn't belong to a class.

async def play(ctx, *args):
    ...


async def pause(ctx, *args):
    ...


async def resume(ctx, *args):
    ...


async def skip(ctx):
    ...


async def queue(ctx):
    ...


async def clear(ctx):
    ...


async def dc(ctx):
    ...

Above are the ones that need changing.

Upvotes: 1

Related Questions