repeat the song when the command is used again - discord.py

I want it to say the same file again when using the command again but it doesn't work please help
#client.command()
async def join(ctx):
voicechannel = discord.utils.get(ctx.guild.channels, name='text')
vc = await voicechannel.connect()
vc.play(discord.FFmpegPCMAudio('deneme/audio.mp3'), after=lambda e: print('done', e))

Related

Discord.py - Music bot queue command

I’m trying to code a simple music bot for discord in python. I tried coding a queue command so that I can queue a certain song (searching for songs and playing them etc. all work). This is my code for the queue command:
#commands.command()
async def checkqueue(self, ctx):
if len(self.song_queue[ctx.guild.id]) == 0:
return await ctx.send("Queue is empty")
else:
embed = discord.Embed(title="Song Queue", description="", colour=discord.colour.dark_gold())
i = 1
for url in self.song_queue[ctx.guild.id]:
embed.description += f"{i}) {url}\n"
i += 1
await ctx.send(embed=embed)
When the queue is empty, the bot sends a message in discord saying "Queue is empty”. When I use the play command, it adds a song to the queue. However, when I try to use the checkqueue command when there’s at least one song in the queue, the bot doesn’t send the embed. Not sure if this is a problem with the code in the queue command or outside the queue command, so here’s the cut-down version of the rest of my code in my commands Cog.
import discord
from discord.ext import commands
import youtube_dl
import pafy
import asyncio
class Commands(commands.Cog):
def __init__(self, client):
self.client = client
self.song_queue = {}
#commands.Cog.listener()
async def on_ready(self):
for guild in self.client.guilds:
self.song_queue[guild.id] = []
async def check_queue(self, ctx):
if len(self.song_queue[ctx.guild.id]) > 0:
ctx.voice_client.stop()
await self.play_song(ctx, self.song_queue[ctx.guild.id][0])
self.song_queue[ctx.guild.id].pop(0)
async def search_song(self, amount, song, get_url=False):
info = await self.client.loop.run_in_executor(None, lambda: youtube_dl.YoutubeDL({"format": "bestaudio", "quiet" : True}).extract_info(f"ytsearch{amount}:{song}", download=False, ie_key="YoutubeSearch"))
if len(info["entries"]) == 0:
return None
return [entry["webpage_url"] for entry in info["entries"]] if get_url else info
async def play_song(self, ctx, song):
url = pafy.new(song).getbestaudio().url
ctx.voice_client.play(discord.PCMVolumeTransformer(discord.FFmpegPCMAudio(url)), after=lambda error: self.client.loop.create_task(self.check_queue(ctx)))
ctx.voice_client.source.volume = 0.5
#commands.command()
async def stop(self, ctx):
if ctx.voice_client is not None:
return await ctx.voice_client.disconnect()
return await ctx.send("Disconnected")
else:
return await ctx.send("I am not connected to a voice channel")
#commands.command()
async def join(self, ctx):
if ctx.author.voice is None:
return await ctx.send("You are not connected to a voice channel")
else:
channel = ctx.author.voice.channel
await channel.connect()
await ctx.send(f"Connected to voice channel: '{channel}'")
#commands.command()
async def play(self, ctx, *, song=None):
if song is None:
return await ctx.send("You must include a song to play.")
if ctx.voice_client is None:
return await ctx.send("I must be in a voice channel to play a song.")
if not ("youtube.com/watch?" in song or "https://youtu.be/" in song):
await ctx.send("Searching for a song, this may take a few seconds...")
result = await self.search_song(1, song, get_url=True)
if result is None:
return await ctx.send("Sorry, I couldn't find the song you asked for. Try using my search command to find the song you want.")
song = result[0]
if ctx.voice_client.source is not None:
queue_len = len(self.song_queue[ctx.guild.id])
if queue_len < 10:
self.song_queue[ctx.guild.id].append(song)
return await ctx.send(f"Song added to the queue at position {queue_len+1}")
else:
return await ctx.send("Maximum queue limit has been reached, please wait for the current song to end to add more songs to the queue")
await self.play_song(ctx, song)
await ctx.send(f"Now playing: {song}")
#commands.command()
async def search(self, ctx, *, song=None):
if song is None:
return await ctx.send("Please include a song to search for")
await ctx.send("Searching for song, this may take a few seconds...")
info = await self.search_song(5, song)
embed = discord.Embed(title=f"Results for '{song}':", description="You can use these URL's to play the song\n", colour=discord.Colour.blue())
amount = 0
for entry in info["entries"]:
embed.description += f"[{entry['title']}]({entry['webpage_url']})\n"
amount += 1
embed.set_footer(text=f"Displaying the first {amount} results.")
await ctx.send(embed=embed)
#commands.command()
async def checkqueue(self, ctx):
if len(self.song_queue[ctx.guild.id]) == 0:
return await ctx.send("Queue is empty")
else:
embed = discord.Embed(title="Song Queue", description="", colour=discord.colour.blue())
i = 1
for url in self.song_queue[ctx.guild.id]:
embed.description += f"{i}) {url}\n"
i += 1
await ctx.send(embed=embed)
#commands.command()
async def queue(self, ctx, *, song=None):
if song is None:
return await ctx.send("You must include a song to queue.")
if not ("youtube.com/watch?" in song or "https://youtu.be/" in song):
await ctx.send("Searching for a song, this may take a few seconds...")
result = await self.search_song(1, song, get_url=True)
if result is None:
return await ctx.send("Sorry, I couldn't find the song you asked for. Try using my search command to find the song you want.")
song = result[0]
if ctx.voice_client.source is not None:
queue_len = len(self.song_queue[ctx.guild.id])
if queue_len < 10:
self.song_queue[ctx.guild.id].append(song)
return await ctx.send(f"Song added to the queue at position {queue_len+1}")
else:
return await ctx.send("Maximum queue limit has been reached, please wait for the current song to end to add more songs to the queue")
The issue that I was having with your code was the color of the Embed. Everything else went smoothly when I ran your code. When you referenced the Colour, you didn't properly access the function.
What you did:
embed = discord.Embed(title="Song Queue",
description="",
colour=discord.colour.dark_gold())
What you should do:
embed = discord.Embed(title="Song Queue",
description="",
colour=discord.Colour.dark_gold())

Snipe command in cogs discord,py

I am reworking my discord bot with cogs and I'm stuck on the snipe function:
import discord
from discord.ext import commands
class Snipe(commands.Cog):
def __init__(self, client):
self.Client = client
#commands.Cog.listener()
async def on_ready(self):
print ("Snipe is now enabled")
async def on_message_delete(self, message):
messageauthor = {}
messagecontent = {}
messageauthor[message.channel.id] = message.author
messagecontent[message.channel.id] = message.content
#commands.command()
async def snipe(self, ctx):
channel = ctx.channel
try:
em = discord.Embed(description = f"said:\n{ctx.messagecontent[channel.id]}", color = 0x00c230)
em.set_author(name = f"Last deleted message in #{ctx.channel.name}")
em.set_thumbnail(url="https://cdn.discordapp.com/avatars/352793093105254402/8a2018de21ad29973696bfbf92fc31cd.png?size=4096")
em.set_footer(text = f"Snipe requested by {ctx.message.author}")
await ctx.channel.send(embed = em)
except:
embed = discord.Embed(colour = 0x00c230)
embed.set_author(name=f"There are no deleted messages in #{ctx.channel.name}!")
embed.set_thumbnail(url="https://cdn.discordapp.com/avatars/352793093105254402/8a2018de21ad29973696bfbf92fc31cd.png?size=4096")
embed.set_footer(text=f"Snipe requested by {ctx.message.author}")
await ctx.channel.send(embed=embed)
def setup(client):
client.add_cog(Snipe(client))
This is my code so far, this is the part that doesn't seem to work:
#commands.command()
async def snipe(self, ctx):
channel = ctx.channel
try:
em = discord.Embed(description = f"said:\n{ctx.messagecontent[channel.id]}", color = 0x00c230)
em.set_author(name = f"Last deleted message in #{ctx.channel.name}")
em.set_thumbnail(url="https://cdn.discordapp.com/avatars/352793093105254402/8a2018de21ad29973696bfbf92fc31cd.png?size=4096")
em.set_footer(text = f"Snipe requested by {ctx.message.author}")
await ctx.channel.send(embed = em)
When I try to snipe a deleted message it just shows the text for the "no messages to snipe" option.
If anyone can help with this/has their own code, edit it as much as you want ill work around that,
Thanks!
Well, in python, if you assign a variable in a function, it will be considered as a local variable. To make it global, you will need to use the global keyword. but since you are coding in a class, you can assign the variable to the class, like:
# to assign
self.messageauthor = {}
# to use
print(self.messageauthor)
So your new code will be:
#commands.command()
async def snipe(self, ctx):
channel = ctx.channel
try:
em = discord.Embed(title="Put something here", description = f"said:\n{ctx.messagecontent[channel.id]}", color = '0x00c230') #color code should be a str
em.set_author(name = f"Last deleted message in #{ctx.channel.name}")
em.set_thumbnail(url="https://cdn.discordapp.com/avatars/352793093105254402/8a2018de21ad29973696bfbf92fc31cd.png?size=4096")
em.set_footer(text = f"Snipe requested by {ctx.message.author}")
await ctx.channel.send(embed = em)
except:
embed = discord.Embed(title="", description="", colour = '0x00c230') # should be str
embed.set_author(name=f"There are no deleted messages in #{ctx.channel.name}!")
embed.set_thumbnail(url="https://cdn.discordapp.com/avatars/352793093105254402/8a2018de21ad29973696bfbf92fc31cd.png?size=4096")
embed.set_footer(text=f"Snipe requested by {ctx.message.author}")
await ctx.channel.send(embed=embed)
Also, title and description are required arguments to make an embed. and, the html color code should be a str. (Use ''). I hope this much helps you.

Counting command (discord.py)

Im trying make the bot count to whatever the user says but it is not sending anything
#commands.cooldown(1, 5, commands.BucketType.user)
#client.command()
async def count(ctx, num):
for i in range(1, num+1):
await ctx.channel.send(i)
There is no error.
Can anyone help
The problem is that num has to be an integer. Here's how you should do it :-
#client.command()
async def count(ctx, num: int):
for i in range(1, num+1):
await ctx.send(i)

How To Make Discord.py dev only Commands

How To Make Discord.py dev only Commands
def restart_bot():
os.execv(sys.executable, ['python'] + sys.argv)
#Bot.command(name= 'restart')
async def restart(ctx):
await ctx.send("Restarting bot...")
restart_bot()
You can do with #commands.is_owner()
basically like this:
#Bot.command(name = 'restart')
#commands.is_owner()
async def restart(ctx):
await ctx.send("Restarting bot...")
restart_bot()
thank me later :D

Command not found in cogs

I was trying to make my code a little cleaner by using cogs but it doesn't seem to work. When I do +balance this error comes up: Ignoring exception in command None: discord.ext.commands.errors.CommandNotFound: Command "balance" is not found: Here's the code part in main.py:
for file in os.listdir("./cogs"): # lists all the cog files inside the cog folder.
if file.endswith(".py"): # It gets all the cogs that ends with a ".py".
name = file[:-3] # It gets the name of the file removing the ".py"
bot.load_extension(f"cogs.{name}") # This loads the cog.
And from the balance file:
bot = commands.Bot(command_prefix='+')
class Balance(commands.Cog):
def __init__(self, client):
self.bot = bot
#commands.command(aliases = ["bal"])
async def balance(self, ctx):
await open_account(ctx.author)
user = ctx.author
users = await get_bank_data()
wallet_amt = users[str(user.id)]["wallet"]
#bank_amt = users[str(user.id)]["bank"]
em = discord.Embed(title = f"{ctx.author.name}'s balance",color = (0x95a5a6), description = f"{wallet_amt} dogecoins")
#em.add_field(name = "Bank balance",value = bank_amt)
await ctx.send(embed = em)
async def open_account(user):
users = await get_bank_data()
if str(user.id) in users:
return False
else:
users[str(user.id)] = {}
users[str(user.id)]["wallet"] = 250
users[str(user.id)]["bank"] = 0
with open("mainbank.json","w") as f:
json.dump(users,f)
return True
async def get_bank_data():
with open("mainbank.json","r") as f:
users = json.load(f)
return users
async def update_bank(user,change = 0,mode = "wallet"):
users = await get_bank_data()
users[str(user.id)][mode] += change
with open("mainbank.json","w") as f:
json.dump(users,f)
return True
def setup(bot):
bot.add_cog(Balance(bot))
I'm new to coding and cogs especially so if anyone knows how to fix this, please help me.
I can't tell if the commands and functions you're showing are inside the class or not. Also, why are you creating a new Bot instance, and why does your init function take an argument called client and then set self.bot to bot?
Try replacing client in your init function with bot, or vice versa.
Do you get any errors when you try to run your main file?

Resources