Nextcord; Button is not showing - python

so I've been trying to make a bot that explains other bots economy system.
There's a message that comes up after you click a certain button and I want to add another button to that certain message. It doesn't work and I have no idea why.
Heres the code:
from nextcord.ext import commands
from nextcord.ui import view
def Sbdrugs(self, ctx):
embed = nextcord.Embed(title="Drugs", description="Drugs play an important role in Slotbot. So make sure to remember what they do.")
embed.set_author(name = ctx.author.display_name, icon_url = ctx.author.avatar_url)
embed.add_field(name = "Weed", value = "Weed can be smoked to restart cooldowns of almost everything including drink. (*Doesnt include drugs.*) Remember, weed is the currency of the black market.", inline = False)
embed.add_field(name = "Drink", value = "Drinking beers basically restarts every cooldown except drugs.", inline = False)
embed.add_field(name = "Steroids", value = "Dosing steroids makes you immune against the ~hex command and gives you access to the ~beatup command. Steroids even decrease the chance of getting scammed from 30% to 10%. It shortens the feed cooldown too.", inline = False)
embed.add_field(name = "Opioids", value = "Make you immune against gun shots, makes you immune against beatup too and resets all cooldowns (except drugs) including smoke and drink.", inline = False)
embed.add_field(name = "Anesthesia **AKA** Anes", value = "Stuns yourself but also makes others not possible to interact with your slotbot stats (bal, goose etc they cant check anything from you).", inline = False)
embed.add_field(name = "LSD", value = "Shortens every cooldown to 15 secs but makes it very hard to do other cooldowns like bal or farm for example. LSD is mostly used for pill farming, constantly shooting people and for some other things but i currently cant remember.", inline = False)
def Helpmeembed(self, ctx):
embed = nextcord.Embed(title = "You called me...?", description= "What do you need help with?")
#still working on this
class SbDrugs(nextcord.ui.View):
def __init__(self):
super().__init__()
self.value = None
#nextcord.ui.button(label = "1", style = nextcord.ButtonStyle.blurple)
async def helpb(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
await interaction.response.send_message({Sbdrugs}, ephemeral=False)
self.value = True
self.stop()
class Helpb(nextcord.ui.View):
def __init__(self):
super().__init__()
self.value = None
#nextcord.ui.button(label = "1", style = nextcord.ButtonStyle.blurple)
async def helpb(self, ctx, button: nextcord.ui.Button, interaction: nextcord.Interaction):
view = Sbdrugs()
await interaction.response.send_message("What do you need help with on Slotbot?\n**1. Drugs**", ephemeral=False, view = view)
self.value = True
self.stop()
class Help(commands.Cog, name="Help"):
def __init__(self, bot: commands.Bot):
self.bot = bot
#commands.command()
async def helpme(self, ctx):
view = Helpb()
await ctx.send("Hey, I'm here, what do you need help with?\n\n**Slotbot**\n*Press 1 for more information.*", view = view)
await view.wait()
if view.value is None:
await ctx.send("Ay, where you at bruh")
def setup(bot: commands.Bot):
bot.add_cog(Help(bot))
This is the Error im getting:
Ignoring exception in view <Helpb timeout=180.0 children=1> for item <Button style=<ButtonStyle.primary: 1> url=None disabled=False label='1' emoji=None row=None>:
Traceback (most recent call last):
File "C:\Users\Windows\AppData\Local\Programs\Python\Python39\lib\site-packages\nextcord\ui\view.py", line 359, in _scheduled_task
await item.callback(interaction)
TypeError: helpb() missing 1 required positional argument: 'interaction'

You set "ctx" to second param, you should remove it, like this
class Helpb(nextcord.ui.View):
def __init__(self):
super().__init__()
self.value = None
#nextcord.ui.button(label = "1", style = nextcord.ButtonStyle.blurple)
# async def helpb(self, ctx, button: nextcord.ui.Button, interaction: nextcord.Interaction):
async def helpb(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
view = Sbdrugs()
await interaction.response.send_message("What do you need help with on Slotbot?\n**1. Drugs**", ephemeral=False, view = view)
self.value = True
self.stop()

Related

Trouble defining a bot.get_channel() with Pycord when calling from a list - Printing "None"

I'm simply attempting to call this channel ID from a list after it is assigned by the command user. All of the print() commands that I do yield the proper ID including print(a_string) which comes RIGHT before the bot.get_channel call.
I cannot fathom why, but for some reason it consistantly returns "None" no matter how I try to assign the variable.
The part of the code in question is inside the class "EmbedConfirmButton" and the variable in question is "esendChannel", assigned by the slash command at the bottom of the code block.
This is a lot of code, but I wanted to be sure to include the entire thing for reference just in case
eEdit = ["blank"]
esendChannel = ["blank"]
eTitle = ["blank"]
eDescription = ["blank"]
channel = []
class EmbedSend(discord.ui.Modal):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
#self.title = kwargs.get("title")
#self.description = kwargs.get("description")
self.add_item(discord.ui.InputText(label="Title", value = eTitle[0]))
self.add_item(discord.ui.InputText(label="Message Content", style=discord.InputTextStyle.long, value = eDescription[0]))
async def callback(self, interaction: discord.Interaction):
eTitle[0] = self.children[0].value
eDescription[0] = self.children[1].value
esend = discord.Embed(title=''.join(eTitle), description=''.join(eDescription))
eEdit[0] = [esend]
print(eEdit)
await interaction.response.send_message(embed = esend, view = EmbedConfirmButton(), ephemeral=True)
class EmbedConfirmButton(discord.ui.View):
def __init__(self):
super().__init__(timeout=None)
#discord.ui.button(label="Send", custom_id="button-embededit", style=discord.ButtonStyle.blurple)
async def first_button_callback(self, button, interaction):
finalembed = discord.Embed(title=eTitle, description=eDescription)
finalembed.set_image(url="")
s = [str(integer) for integer in esendChannel]
a_string = "".join(s)
print(a_string)
await bot.get_channel(a_string).send(embed = finalembed)
await interaction.response.send_message("test", ephemeral = True)
#discord.ui.button(label="Edit", custom_id="button-embededit2", style=discord.ButtonStyle.blurple)
async def second_button_callback(self, button, interaction):
modal = EmbedSend(title=eTitle[0])
await interaction.response.send_modal(modal)
await interaction.followup.send("test")
#discord.ui.button(label="Cancel", custom_id="button-embedcancel", style=discord.ButtonStyle.blurple)
async def third_button_callback(self, button, interaction):
await interaction.response.send_message("Canceled Interaction", ephemeral = True)
return
#bot.slash_command()
#option("channel")
async def embedsend(ctx, channel:discord.TextChannel):
modal = EmbedSend(title = "Embed Create")
await ctx.send_modal(modal)
await ctx.respond("Success", ephemeral = True)
esendChannel[0] = str(channel.id)
print(esendChannel)
I've tried assigning the variable in several different ways to the point I've completely no clue why it would be returning "None" only when passed to bot.get_channel()
Are you saying that bot.get_channel is returning None when calling it with a_string?
Have you tried using await bot.fetch_channel(a_string) instead? It's possible that that channel isn't in the cache so get_channel isn't returning anything.

Discord.py UI send selectionOption when clicking button. (Version = DPY 2.0a)

#client.tree.command(name = "roles", description = "Role Test Menu.", guild =TEST_GUILD)
async def roles(interaction: discord.Interaction):
await interaction.response.send_message(view=RoleButton(), ephemeral = True)
##################################################################################################
class RoleButton(discord.ui.View):
def __init__(self):
super().__init__(timeout=None)
#discord.ui.button(label='Role Menu', style=discord.ButtonStyle.green, custom_id='Role Menu')
async def rolebutton(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.defer()
test1 = discord.utils.get(interaction.guild.roles, name='Test1')
test2 = discord.utils.get(interaction.guild.roles, name='Test2')
if test1 in interaction.user.roles:
df = True
elif test2 in interaction.user.roles:
df = True
else:
df = False
options = [
discord.SelectOption(label="Test 1", value="Test 1", default = df),
discord.SelectOption(label="Test 2", value="Test 2", default = df)
]
#discord.ui.select(placeholder="Select",custom_id="test",max_values=2, options=options)
async def _action_select(self, interaction: discord.Interaction, select: discord.ui.Select):
await interaction.response.send_message("Done!", ephemeral = True)
##################################################################################################
So, this obviously doesn't work, and I know that. But this is an example of what I am trying to do; essentially, I want the slash command to send the "Role Menu" button. Then when it it clicked by a user, check if the user has "test1" and "test2" roles. If they do/don't, then set the default selectionOption to T/F, then send the select. How can I change this to have it work how I want it to?
To add a ui.Button or a ui.Select to a message, you need a ui.View to which you add those things. The view then gets added to the message.
Solution:
import discord
from discord import ui
bot = commands.Bot()
class Select(ui.Select):
def __init__(self, options):
# placeholder: Will be shown when no option is chosen
# custom_id: The id of the select menu
# options: The dropdown options which can be chosen
# max_values: Indicates that max. 2 options can be picked
super().__init__(placeholder="Select", custom_id="test", options=options, max_values=2)
# This function is called when the user has chosen an option
async def callback(self, interaction: discord.Interaction):
# With the interaction parameter, you can send a response message.
# With self.values you get a list of the user's selected options.
print(self.values)
await interaction.response.send_message(f"Done!", ephemeral=True)
class ViewButton(ui.View):
# label: The label of the button which is displayed
# style: The background color of the button
#ui.button(label="Role Menu", style=discord.ButtonStyle.blurple)
async def role_menu_btn(self, interaction: discord.Interaction, button_obj: ui.Button):
# This function is called when a user clicks on the button
# get the roles
test1_role = interaction.guild.get_role(1007237710295081020)
test2_role = interaction.guild.get_role(1007237773230620728)
# check if user has the role or not
df1 = True if test1_role in interaction.user.roles else False
df2 = True if test2_role in interaction.user.roles else False
options = [
discord.SelectOption(label="Test 1", value="Test 1", default=df1),
discord.SelectOption(label="Test 2", value="Test 2", default=df2)
]
# create ui.Select instance and add it to a new view
select = Select(options=options)
view_select = ui.View()
view_select.add_item(select)
# edit the message with the new view
await interaction.response.edit_message(content="Choose an option", view=view_select)
#bot.tree.command(name="btn", description="Wonderful button")
async def btn(interaction: discord.Interaction):
await interaction.response.send_message("Click it!", view=ViewButton())
References:
ui.View
ui.button
ui.Select

Nextcord send a message to a specific channel (discord.py fork)

So, I've been trying to make a suggestion discord bot, so it sends a message to a specific channel when prompted and verified with a button, but I can't seem to make it work.
My code is here:
import nextcord
import os
import requests
import asyncio
import random
import catapi
import json
import nest_asyncio
nest_asyncio.apply()
apicat = catapi.CatApi(api_key=os.environ['CAT_API_KEY'])
loop = asyncio.new_event_loop()
intents = nextcord.Intents.default()
intents.members = True
client = commands.Bot(command_prefix = '$', intents=intents)
colors = [0x00ffee,0x32a852,0x4287f5,0xcc2af5,0xf7e7a6,0xdea4a2]
def run_coro(coroutine):
return loop.run_until_complete(coroutine)
class YesOrNo(nextcord.ui.View):
def __init__(self):
super().__init__()
self.value = None
#nextcord.ui.button(emoji="✔", style=nextcord.ButtonStyle.success)
async def yes(self, button: nextcord.ui.Button, interaction: Interaction):
channel = client.get_channel(950111018405748746)
embed = nextcord.Embed(title="Suggestion was sent!", color=0x51ff00)
await channel.send("test")
await interaction.edit(embed=embed, view=None)
self.value = True
self.stop()
#nextcord.ui.button(emoji="✖️", style=nextcord.ButtonStyle.danger)
async def no(self, button: nextcord.ui.Button, interaction: Interaction):
embed = nextcord.Embed(title="Suggestion was discarded!", color=0xff0000)
await interaction.edit(embed=embed, view=None)
self.value = False
self.stop()
But I receive this error:
AttributeError: 'YesOrNo' object has no attribute 'client'
Any ideas how to fix it?
I've tried changing all the clients and stuff to bot, I've tried putting client inside the init, super init, class, ui.button, async def, and I STILL DO NOT KNOW WHAT'S WRONG!
Pass client and then define it with self.client, like this:
class YesOrNo(nextcord.ui.View):
#pass `client` here
↓
def __init__(self):
super().__init__()
self.value = None
self.client = client # ← then define self.client
Your code will look like this:
class YesOrNo(nextcord.ui.View):
def __init__(client, self):
super().__init__()
self.value = None
self.client = client
#nextcord.ui.button(emoji="✔", style=nextcord.ButtonStyle.success)
async def yes(self, button: nextcord.ui.Button, interaction: Interaction):
channel = client.get_channel(950111018405748746)
embed = nextcord.Embed(title="Suggestion was sent!", color=0x51ff00)
await channel.send("test")
await interaction.edit(embed=embed, view=None)
self.value = True
self.stop()
#nextcord.ui.button(emoji="✖️", style=nextcord.ButtonStyle.danger)
async def no(self, button: nextcord.ui.Button, interaction: Interaction):
embed = nextcord.Embed(title="Suggestion was discarded!", color=0xff0000)
await interaction.edit(embed=embed, view=None)
self.value = False
self.stop()
This is probably it.
• Sxviaat

How to change the disabled parameter of a button, depending on instance variables. Nextcord.py

I want to disable the button when the product store reaches one of the bounds and you can no longer click on the "Next Page" or "Past Page" button. But since you can't pass instance variables to decorators, I can't compare values and pass them to #nextcord.ui.button. Can you help with this problem? Here is my code:
import nextcord
from nextcord.ext import commands
from SupportClasses import BuildShop as bd
from SupportClasses import Build
class ShopBuildings(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
#commands.command()
async def ShopBuild(self, ctx, numberPage=1):
shopBuildings = bd.getBuildShop()
view = ShopPages(shopBuildings, int(numberPage))
await ctx.send(embed=createEmded('ShopBuildings', shopBuildings[int(numberPage)-1], view=view))
class ShopPages(nextcord.ui.View):
def __init__(self, shop, numberPage):
super().__init__()
self.__shop = shop
self.__numberPage = numberPage-1
#nextcord.ui.button(label='Past Page', style=nextcord.ButtonStyle.primary)
async def BackPage(self, button: nextcord.ui.button, interaction: nextcord.Interaction):
self.__numberPage-=1
await interaction.response.edit_message(embed=embed=createEmded('ShopBuildings', self.__shop[self.__numberPage]))
#nextcord.ui.button(label='Next Page', style=nextcord.ButtonStyle.primary)
async def NextPage(self, button: nextcord.ui.button, interaction: nextcord.Interaction):
self.__numberPage+=1
await interaction.response.edit_message(embed=createEmded('ShopBuildings', self.__shop[self.__numberPage]))
You can disable buttons with self.mybutton.disabled = True.
So for your code it would be something like:
def __init__(self, shop, numberPage):
super().__init__()
self.__shop = shop
self.__numberPage = numberPage-1
if __numberPage == 0:
self.BackPage.disabled == True
if __numberPage == __maxPage:
self.NextPage.disabled == True

discord.py - edit the interaction message after a timeout in discord.ui.Select

How can I access the interaction message and edit it?
discord.ui.Select
class SearchMenu(discord.ui.Select):
def __init__(self, ctx, bot, data):
self.ctx = ctx
self.bot = bot
self.data = data
self.player = Player
values = []
for index, track in enumerate(self.data[:9]):
values.append(
discord.SelectOption(
label=track.title,
value=index + 1,
description=track.author,
emoji=f"{index + 1}\U0000fe0f\U000020e3"
)
)
values.append(discord.SelectOption(label='Cancel', description='Exit the search menu.', emoji="🔒"))
super().__init__(placeholder='Click on the Dropdown.', min_values=1, max_values=1, options=values)
async def callback(self, interaction: discord.Interaction):
if self.values[0] == "Cancel":
embed = Embed(emoji=self.ctx.emoji.whitecheck, description="This interaction has been deleted.")
return await interaction.message.edit(embed=embed, view=None)
discord.ui.View
class SearchMenuView(discord.ui.View):
def __init__(self, options, ctx, bot):
super().__init__(timeout=60.0)
self.ctx = ctx
self.add_item(SearchMenu(ctx, bot, options))
async def interaction_check(self, interaction: discord.Interaction):
if interaction.user != self.ctx.author:
embed = Embed(description=f"Sorry, but this interaction can only be used by {self.ctx.author.name}.")
await interaction.response.send_message(embed=embed, ephemeral=True)
return False
else:
return True
async def on_timeout(self):
embed = Embed(emoji=self.ctx.emoji.whitecross, description="Interaction has timed out. Please try again.")
await self.message.edit(embed=embed, view=None)
If I try to edit the interaction like this I am getting
-> AttributeError: 'SearchMenuView' object has no attribute 'message'
After 60 seconds the original message should be replaced with the embed in the timeout.
You're trying to ask the View to send a message, which is not a method in discord.ui.View.
You could defer the response and don't let it timeout and allow the user to try again?
async def interaction_check(self, interaction: discord.Interaction):
if interaction.user != self.ctx.author:
embed = Embed(description=f"Sorry, but this interaction can only be used by {self.ctx.author.name}.")
await interaction.channel.send(embed=embed, delete_after=60)
await interaction.response.defer()
return True
view = MyView()
view.message = await channel.send('...', view=view)
After that you can use self.message in on_timeout (or somewhere else you don't have access to interaction.message) to edit it.
Source: https://discord.com/channels/336642139381301249/669155775700271126/860883838657495040

Categories

Resources