Discord.py: This interaction failed - python

I'm trying to create a ticket bot using discord buttons. However, whenever I click on the button- which should create a ticket just responds with a prompt saying: "This interaction failed".
#commands.command(pass_context = True)
#commands.has_permissions(administrator=True)
async def ticket(self, ctx):
if self.channelId == 0:
embed_var = discord.Embed(title="", description="No channel set up [.ticketSet]", color=0xffffff)
await ctx.send(embed=embed_var)
else:
await self.bot.wait_until_ready()
embed_var = discord.Embed(title="Tickets", description=self.ticketDesc, color=0xffffff)
channel = self.bot.get_channel(int(self.channelId))
await channel.send(embed=embed_var,components = [Button(label = "📩 Create Ticket", custom_id = "button1")])
while True:
event = await self.bot.wait_for('button_click')
await self.on_button_click()
#commands.Cog.listener()
async def on_button_click(self, interaction):
admin = discord.utils.get(interaction.guild.roles, name=self.manageRole)
category = discord.utils.get(interaction.guild.categories, name="INFO / HELP")
print("Button 'ticket' clicked")
...

Related

How do I implement a queue system into my Discord Music Bot?

#client.command()
async def play(ctx, *, url = None):
if ctx.author.voice is None:
msg = await ctx.send("You are not in a voice channel.")
await msg.delete(delay = 3)
voice_channel = ctx.author.voice.channel
if ctx.voice_client is None:
await voice_channel.connect()
else:
await ctx.voice_client.move_to(voice_channel)
search_keyword = url
if not ("youtube.com/watch?" in search_keyword):
search_keyword = search_keyword.replace(" ", "+")
html = urllib.request.urlopen(f"https://www.youtube.com/results?search_query={search_keyword}")
video_ids = re.findall(r"watch\?v=(\S{11})", html.read().decode())
url = str(f"https://www.youtube.com/watch?v={video_ids[0]}")
ctx.voice_client.stop()
FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
YDL_OPTIONS = {'format': 'bestaudio', 'noplaylist':'True'}
vc = ctx.voice_client
with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl:
info = ydl.extract_info(url, download=False)
title = info.get('title', None)
length = info['duration']
url2 = info["formats"][0]["url"]
source = await discord. FFmpegOpusAudio.from_probe(url2, **FFMPEG_OPTIONS)
vc.play(source)
embed = discord.Embed(title = "Currently Playing", colour = discord.Colour.blue())
embed.add_field(name = "Song", value = title, inline = False)
embed.add_field(name = "Length", value = str(datetime.timedelta(seconds = length)), inline = False)
embed.add_field(name = "Link", value = url, inline = False)
msg = await ctx.send(embed=embed)
await msg.add_reaction("\u23F8")
await msg.add_reaction("\u25B6")
await msg.add_reaction("\u23F9")
while True:
try:
reaction, user = await client.wait_for("reaction_add", check=lambda reaction, user: user.id == ctx.author.id and reaction.message.id == msg.id and reaction.emoji in ["\u23F8", "\u25B6", "\u23F9"], timeout = length)
except asyncio.TimeoutError:
return await msg.clear_reactions()
async def process():
if reaction.emoji == "\u23F8":
await msg.remove_reaction(reaction.emoji, ctx.author)
ctx.voice_client.pause()
elif reaction.emoji == "\u25B6":
await msg.remove_reaction(reaction.emoji, ctx.author)
ctx.voice_client.resume()
elif reaction.emoji == "\u23F9":
await msg.remove_reaction(reaction.emoji, ctx.author)
ctx.voice_client.stop()
asyncio.create_task(process())
Here's the code for my play command. Right now if the command is invoked while a song is playing, then that song stops and the newly requested one begins, this is because of the ctx.voice_client.stop() before the song is downloaded. However, I'm trying to implement a queue system where if the command is invoked while another song is playing it will be added to queue, and songs in the queue will be played right after the current song ends. Currently my idea of how to do this would be to replace the ctx.voice_client.stop() with an if statement that checks the status of the bot, if it is currently playing or not, and either appends it it to a global list variable containing the current queue or plays the song. But I am clueless on how to make it play the queue one after another and implement a skip command. Another complicated part would be to implement the skip command into a reaction similar to how I've implemented the pause and play commands. I don't now if my idea will work, so any input is appreciated.
first you need to creat a empty queue outside your command
queues = {}
and a funtion to check if there's a song in queues it will play that song
#check queue
queues = {}
def check_queue(ctx, id):
if queues[id] !={}:
voice = ctx.guild.voice_client
source = queues[id].pop(0)
voice.play(source, after=lambda x=0: check_queue(ctx, ctx.message.guild.id))
and inside play command create a funtion to add the next song to queue if a song is already being played and add the check queue funtion
if voice.is_playing():
guild_id = ctx.message.guild.id
if guild_id in queues:
queues[guild_id].append(source)
else:
queues[guild_id] = [source]
else:
vc.play(source, after=lambda x=0: check_queue(ctx, ctx.message.guild.id))
You can check out my code here if u need more help Need help Discord bot queue

trying to send a an embed message based on event event

i'm trying to make a logger for deleted messages based on an event whenever the message is deleted
snipe_message_author = None
snipe_message_id = None
#client.event
async def on_message_delete(message):
global snipe_message_content
global snipe_message_author
global snipe_message_id
snipe_message_content = message.content
snipe_message_author = message.author.id
snipe_message_id = message.id
await asyncio.sleep(60)
if message.id == snipe_message_id:
snipe_message_author = None
snipe_message_content = None
snipe_message_id = None
#client.event
async def logs(ctx, message):
if snipe_message_content==None:
m == 1
else:
embed = discord.Embed(description=f"{snipe_message_content}")
embed.set_footer(text=f"Sniped by {message.author.name}#{message.author.discriminator}")
embed.set_author(name= f"<#{snipe_message_author}>")
await message.channel.send(client.get_channel('channel id'), embed=embed)
return
I'm encountering problems with this part....
#client.event
async def logs(ctx, message):
if snipe_message_content==None:
m == 1
else:
embed = discord.Embed(description=f"{snipe_message_content}")
embed.set_footer(text=f"Sniped by {message.author.name}#{message.author.discriminator}")
embed.set_author(name= f"<#{snipe_message_author}>")
await message.channel.send(client.get_channel('channnelid'), embed=embed)
return
I've tried using different methods but none have been working so far
You need a command?
#client.command()
async def logs(ctx):
global snipe_message_content
if snipe_message_content==None:
m = 1
else:
embed = discord.Embed(description=f"{snipe_message_content}")
embed.set_footer(text=f"Sniped by {ctx.author.name}#{ctx.author.discriminator}")
embed.set_author(name= f"<#{snipe_message_author}>")
await ctx.send(embed=embed)

Disconnect the music bot from voice channel

I have this as my music class to make my bot play music
class Music(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.bot.music = lavalink.Client(self.bot.user.id)
self.bot.music.add_node("localhost", 7000, 'server-utils', 'eu', 'music-node')
self.bot.add_listener(self.bot.music.voice_update_handler, 'on_socket_response')
self.bot.music.add_event_hook(self.track_hook)
#commands.command(name="music")
async def music(self, ctx, opt, *, arg=None):
if opt == "join":
print(f"music join command worked")
member = discord.utils.find(lambda m: m.id == ctx.author.id, ctx.guild.members)
if member is not None and member.voice is not None:
vc = member.voice.channel
player = self.bot.music.player_manager.create(ctx.guild.id, endpoint=str(ctx.guild.region))
if not player.is_connected:
player.store('channel', ctx.guild.id)
await self.connect_to(ctx.guild.id, str(vc.id))
if opt == "play" and arg is not None:
try:
player = self.bot.music.player_manager.get(ctx.guild.id)
query = f'ytsearch:{arg}'
results = await player.node.get_tracks(query)
tracks = results['tracks'][0:10]
i = 0
query_result = ''
for track in tracks:
i = i + 1
query_result = query_result + f'{i}) {track["info"]["title"]}\n'
embed = discord.Embed()
embed.description = query_result
await ctx.channel.send(embed=embed)
def check(m):
return m.author.id == ctx.author.id
reponse = await self.bot.wait_for('message', check=check)
track = tracks[int(reponse.content)-1]
player.add(requester=ctx.author.id, track=track)
if not player.is_playing:
await player.play()
except Exception as error:
print(error)
if opt == "stop":
try:
player = self.bot.music.player_manager.get(ctx.guild.id)
if player.is_playing:
await player.stop()
except Exception as error:
print(error)
if opt == "leave":
player = self.bot.music.player_manager.get(ctx.guild.id)
if player.is_playing:
await player.stop()
await self.disconnect_from(ctx.guild.id)
async def track_hook(self, event):
if isinstance(event, lavalink.events.QueueEndEvent):
guild_id = int(event.player.guild_id)
await self.connect_to(guild_id, None)
async def connect_to(self, guild_id: int, channel_id: int):
ws = self.bot._connection._get_websocket(guild_id)
await ws.voice_state(str(guild_id), channel_id)
async def disconnect_from(self, guild_id: int):
ws = self.bot._connection.voice_clients
print(ws)
def setup(bot):
bot.add_cog(Music(bot))
Everythink works fine except the part to disconnect from the channel he is connected to... I've tried lots of things and can't figure out how to make it disconnect..
Ps: Here the command doesn't do anything but to print a list where I hoped there would be the bot connect, but it had nothing there
I believe it's because you're passing the guild id as opposed to the voice channels id, for example.
You're in the guild; Hello World with an ID of 12345
You're in the guilds voice channel of; Hello World voice channel which has an id of 6789.
so you're trying to use the guild.id as opposed to the voice channel id. Does this make sense?
Can't you do await ctx.voice_client.disconnect()
if opt == "leave":
player = self.bot.music.player_manager.get(ctx.guild.id)
if player.is_playing:
await player.stop()
await ctx.voice_client.disconnect()
I did a disconnect command on my Discord bot using VoiceClient.disconnect(). I got some trouble with it in my first approach because the connect command generated the VoiceClient object, but disconnect command could not use it since it was a local variable on the other command, so i just made it global and it works
#commands.command()
async def enter(self, ctx):
try:
canal = ctx.author.voice.channel
global voice_client
voice_client = await canal.connect()
except AttributeError:
await ctx.send("Você precisa estar conectado a um canal de voz")
except discord.errors.ClientException:
await ctx.send("Eu já estou conectado ao seu canal de voz")
#commands.command()
async def leave(self, ctx):
try:
await voice_client.disconnect()
except NameError:
await ctx.send("Eu não estou conectado a nenhum canal de voz :worried:")
The full music cog that I coded:
https://github.com/Voz-bonita/Discord-Bot/blob/master/Music%20extension.py

How do I make wait_for() function work in cogs discord.py?

In the code below I want the bot to wait for a specific user's message after the command has run. To do that I typed in .esug ("." is the command prefix) and it responded with a message asking me to enter my Minecraft username, but when I entered my username it didn't ask me the second question which it should. Then I checked for errors but there were none and that lead me to here.
Code below:
import e_sugarcane
import discord
from discord.ext import commands
user = discord.Client()
class info_cmds(commands.Cog):
def __init__(self, bot):
self.bot = bot
#commands.command()
async def esug(self, ctx, name=None, profile=None):
authorId = ctx.author.id
if name == None:
embed2 = discord.Embed(
color = discord.Color.blue()
)
embed2.add_field(name="Missing Information", value="```Please Enter your Minecraft Username```")
await ctx.send(embed=embed2)
name = await user.wait_for('message', check=lambda message: message.author == ctx.author)
print(name)
profilesList, uuid, boolean = e_sugarcane.listProfiles(name)
if boolean:
embed3 = discord.Embed(
color = discord.Color.blue()
)
embed2.add_field(name="Missing Information", value="```Please Enter your SkyBlock Profile Name```")
await ctx.send(embed=embed3)
profile = await user.wait_for('message', check=lambda message: message.author == ctx.author)
profileID = profilesList[profile.lower()]
totalESugarcane = e_sugarcane.eSugarcane(uuid, profileID)
else:
profilesList, uuid, boolean = e_sugarcane.listProfiles(name)
profileID = profilesList[profile.lower()]
totalESugarcane = e_sugarcane.eSugarcane(uuid, profileID)
embed1 = discord.Embed(
color = discord.Color.blue()
)
embed1.add_field(name="Amount of Sugar Cane", value=f"```{str(totalESugarcane)}```")
await ctx.send(embed=embed1)```
It should be self.bot.wait_for() instead of user.wait_for()

I want to delete only the voice channels in one category

Here is my code:
import discord, asyncio
app = discord.Client()
#app.event
async def on_voice_state_update(member, before, after):
username = str(member)
guild = app.get_guild(660213767820410893)
ch = guild.get_channel(660213767820410918)
category = guild.get_channel(660213767820410908)
if after.channel == ch:
channel = await guild.create_voice_channel(
name=username+"`s Room",
category=category,
user_limit=99
)
await member.move_to(channel)
await channel.set_permissions(member, manage_channels=True)
if not before.channel.members and before.channel != ch:
await before.channel.delete()
I want to delete only the voice channels in one category. For now, all channels are deleted.
Do you only want to delete the VoiceChannel if it's in the category ? If yes, you could just add the condition: before.channel.category == category in the last if block:
import discord, asyncio
app = discord.Client()
#app.event
async def on_voice_state_update(member, before, after):
username = str(member)
guild = app.get_guild(660213767820410893)
ch = guild.get_channel(660213767820410918)
category = guild.get_channel(660213767820410908)
if after.channel == ch:
channel = await guild.create_voice_channel(
name=username+"`s Room",
category=category,
user_limit=99
)
await member.move_to(channel)
await channel.set_permissions(member, manage_channels=True)
b_channel = before.channel
if b_channel: # If the user was connected to a voice channel before
if not b_channel.members and b_channel != ch and b_channel.category == category:
await b_channel.delete()

Categories