Search code examples
pythondiscorddiscord.py

discord.py button stops after reset


class buttonHandler(discord.ui.View): def init(self): super().init(timeout=None)

@discord.ui.button(label="Verify", style=discord.ButtonStyle.primary, custom_id='persistent_view:primary')
async def buttons_verify(self, interaction: discord.Interaction, button: discord.ui.Button):
    #interaction.response.send_message("you clicked me")
    db = self.client.mongoConnect["zbot"]
    collection = db["Verify"]
    verify_data = collection.find_one({"_id" : interaction.guild_id})
    
    role = discord.utils.get(interaction.guild.roles, id=verify_data['roles'])
    if role not in interaction.user.roles:
        await interaction.user.add_roles(role)
        await interaction.response.send_message("Welcome to the server", ephemeral=True)
    else:
        await interaction.response.send_message("Already Verified", ephemeral=True)
    

class rules(commands.Cog):

def __init__(self, client: commands.Bot):
    self.client = client  
#test the button function this code is confirmed to work in python 2.0
#@app_commands.commands.command(name="button", description="just a button")
#async def button1(self, interaction: Interaction):
#    view = buttonHandler()
#    await interaction.response.send_message("test", view=view)
 
 
 

 
@app_commands.command(name="rules", description="(Admin only)add rules and make a reaction please please add a role named Member for this to work")
async def self_role(self, interaction: discord.Interaction, channel: str, role: str):
    ##Gets the mongodb database
    db = self.client.mongoConnect["zbot"]
    collection = db["Verify"]
    
    
    
    ## turns the channel into a channel id
    role_new = re.sub(r'[^0-9]', '', role)
    role_id_int = int(role_new)
    channel_new = re.sub(r'[^0-9]', '', channel)
    channel_id_int = int(channel_new)
    channel_int_new = self.client.get_channel(channel_id_int)
    
    ##
    await interaction.response.send_message("enter your message")
    #message = ''
    def check(m):
        
        return m.author == interaction.user and m.channel == interaction.channel
    view = buttonHandler(role=role_id_int)
    msg = await self.client.wait_for('message',timeout=120.0, check=check)
    await channel_int_new.send(msg.content, view=view)
    if await collection.find_one({"_id" : interaction.guild_id}) == None:
        newData = {"_id" : interaction.guild_id, "roles": role_id_int}
        await collection.insert_one(newData)
    else:
        await collection.replace_one({"_id" : interaction.guild_id, "roles": role_id_int})
    
    
    

whenever I reset my bot the button stops working I tried to make it persistent with Rapptz/discord.py persistent.py but its not working


Solution

  • Explanation

    Since views are not automatically reinitialized when the bot restarts, you need to this yourself. This can be accomplished by calling Bot.add_view in your bot's setup_hook.

    Some important considerations:

    In order a view to persist between restarts it needs to meet the following conditions:

    1. The timeout of the View has to be set to None
    2. Every item in the View has to have a custom_id set

    Code

    import discord
    from discord.ext import commmands
    
    
    class PersistentView(discord.ui.View):
        def __init__(self):
            super().__init__(timeout=None)
    
        @discord.ui.button(label='Green', style=discord.ButtonStyle.green, custom_id='persistent_view:green')
        async def green(self, interaction: discord.Interaction, button: discord.ui.Button):
            await interaction.response.send_message('This is green.', ephemeral=True)
    
    
    class PersistentViewBot(commands.Bot):
        def __init__(self):
            intents = discord.Intents.default()
            intents.message_content = True
    
            super().__init__(command_prefix=commands.when_mentioned_or('$'), intents=intents)
    
        async def setup_hook(self) -> None:
            # Register the persistent view for listening here.
            # Note that this does not send the view to any message.
            # In order to do this you need to first send a message with the View, which is shown below.
            # If you have the message_id you can also pass it as a keyword argument, but for this example
            # we don't have one.
            self.add_view(PersistentView())
    
    bot = PersistentViewBot()
    
    bot.run("token")
    

    Reference

    discord.Client.add_view

    Code excerpt from discord.py github repo examples