Play mp3 music from a local Folder? discord.py - discord.py

I want my bot to play multiple songs after each other. All I have is my bot playing one song and then stopping to do it. My Code so far:
#bot.command()
async def startq(ctx):
channel = bot.get_channel(705831663497904211)
vc = await channel.connect()
vc.play(discord.FFmpegPCMAudio("E:\Programmieren\Programmieren\Disc-Bot\music2.mp3"))

You should add the songs you want in the songs list, after that it should play all the songs.
You can also scan all the files in the folder and add them to the list using glob.
Note: I have not tried it, but it should work theoretically.
import glob
#bot.command()
async def startq(ctx):
channel = bot.get_channel(705831663497904211)
vc = await channel.connect()
songs = ["music2.mp3","music1.mp3"]
# or check all files in folder
songs = glob.glob("E:\Programmieren\Programmieren\Disc-Bot\*.mp3")
for song in songs:
vc.play(discord.FFmpegPCMAudio(f"E:\Programmieren\Programmieren\Disc-Bot\{song}"))
while vc.is_playing():
await asyncio.sleep(1)

Related

Youtube DL prepare filename discord bot

I'm creating a discord bot which also has a music part. I have it working but i wanted to give the info to the user of which song it's playing. Right now I've this for the play command:
#commands.command()
async def play(self,ctx,url):
await ctx.channel.purge(limit = 1)
ctx.voice_client.stop()
FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
YDL_OPTIONS = {'format':"bestaudio"}
vc = ctx.voice_client
await ctx.send("Searching for the requested song")
with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl:
info = ydl.extract_info(url, download=False)
videotitle = ydl.prepare_filename(info)
url2 = info['formats'][0]['url']
source = await discord.FFmpegOpusAudio.from_probe(url2, **FFMPEG_OPTIONS)
vc.play(source)
await ctx.send(f"Playing {videotitle}")
This works but i want the output to be changed. Right now i get this:
MIX TECH HOUSE 2020 #8 (Camelphat, Torren Foot, Cardi B, Pax, Muus, Kevin McKay...)-RN7mbUBzUJw.m4a
I want the part "RN7mbUBzUJw.m4a" not to be there. does any one know what goes wrong in the ydl.prepare_filename?
The function YoutubeDL.prepare_filename generates a string that's a valid file name, mangling the video title if necessary and including the video ID and extension. It seems you want just the video title, so you can just do the same thing that function does manually.
The way they get the video title is:
video_title = info_dict.get('title', info_dict.get('id', 'video'))
where info_dict is the dictionary returned by YoutubeDL.extract_info. So in your case
videotitle = info.get('title', 'Video with ID: '+info.get('id', 'unknown'))
should work.

How to auto update channel name using Discord.py

I am trying to understand how to automatically update a specific voice channels name in Discord. Looking through the API and around the site, I have found this:
#client.command()
async def emoivb(ctx, channel: discord.VoiceChannel, new_name):
await channel.edit(name=new_name)
However, I need it not as a command.
Example: Each time a person sends a specific message, the channel will increment its integer name by +1
Create a json file to store the number of messages with name message and use the following code
#client.listen()
async def on_message(message):
channel_id="channel which is to be edited"
channel=await client.fetch_channel(channel_id)
with open('message.json',"r") as f:
messages=json.load(f)
try:
x=messages[str(message.guild.id)]
x=x+1
messages[str(message.guild.id)]=x
with open('message.json',"w") as f:
json.dump(messages,f,indent=4)
await channel.edit(name=str(x))
except:
messages[str(message.guild.id)]=1
with open('message.json',"w") as f:
json.dump(messages,f,indent=4)
await channel.edit(name=str(1))

Command to spam something discord-bot

so basically I am trying to make a spam command for my discord bot, which takes in a custom message to spam. Here's the code:
#client.command(name='spam')
async def spam(ctx):
global stop
stop = 0
content = ctx.message.content[11:]
if ctx.author.guild_permissions.administrator or ctx.author.id in admins:
if lock == 1:
await ctx.send('Jesus bot is currently locked.')
elif lock == 0:
await ctx.send('Beginning spam..')
while not stop:
await ctx.send(content)
else:
await ctx.send('Sorry, but you do not have admin permissions in this server, or you are not a verified admin.')
For some reason, whenever I try to use this command, the bot doesn't respond. I'm not sure why this happens, and could use some help please.
Picture of bot not responding:
I have a spam command, but I only use it to mess around with my friends. I would not recommend using this as a public command, as you may get rate limited or banned for abuse or something like that. Anyway here is the code I have used for it.
#commands.command()
#commands.is_owner()
# If you want to use admin only, use this below
# #commands.has_permissions(administrator=True)
async def spam(self, ctx, amount, *, word):
int(amount)
await asyncio.sleep(2)
print(f"Starting to spam {word} in {ctx.guild.name}")
await ctx.message.delete()
await ctx.send(f"{ctx.author.mention}\nPlease note that this will clog up the bot's reaction time")
await asyncio.sleep(3)
count = 0
counting=True
while counting:
await ctx.send(word)
count = count + 1
if count == amount:
await asyncio.sleep(2)
await ctx.send("Spam complete")
print(Fore.GREEN + "Spam complete")
counting = False
At the top of your code, make sure you import asyncio as time.sleep will cause the whole bot to pause. Also the Fore.GREEN stuff is just colorama (import colorama).
Try using tasks instead of asyncio. It is made for such repetetive operations and it is easier and nicer because it is made by discord and is included in discord.ext. Something like this:
from discord.ext import tasks
#client.command(name='spam')
async def spam(ctx):
#get message and do all the ifs that you have there
spamLoop.start()
#client.command(name='stopSpam')
async def spamStop(ctx):
# stop the loop
spamLoop.cancel()
#tasks.loop(seconds=1)
async def spamLoop():
print("The message")
Actually quite a simple way of adding spam
import asyncio
#bot.command(name='spam', help= "Spam to your heart's delight")
async def spam(ctx, thing, amount):
count = 0
while count < int(amount):
await ctx.send(thing)
count += 1
if count < amount:
await asyncio.sleep(1)

Discord Bot sending more than one message

So I am creating a simple bot that detects when somebody joins a server and when somebody leaves the server.
I added a command to show people's avatars, but any time I do it, or when somebody joins or leaves, it sends the message more than once.
I've searched and I can't find the problem.
Can you guys help me?
Here's my code
import discord
from discord.ext import commands
client = commands.Bot(command_prefix="?")
#client.event
async def on_ready():
print("Ready")
#client.event
async def on_member_join(member):
channel = discord.utils.get(member.guild.text_channels, name="entradas")
await channel.send(f"{member} is new on the server, everyone say hi")
show_avatar = discord.Embed(color = discord.Color.blue())
show_avatar.set_image(url="{}".format(member.avatar_url))
await channel.send(embed=show_avatar)
#client.event
async def on_member_remove(member):
channel = discord.utils.get(member.guild.text_channels, name="saidas")
await channel.send(f"{member} left the server, press F to pay respects")
#client.command()
async def avatar(ctx, member: discord.Member):
show_avatar = discord.Embed(color = discord.Color.blue())
show_avatar.set_image(url="{}".format(member.avatar_url))
await ctx.send(embed=show_avatar)
You should check if you are running 2 bots.
If you are running your bot on Linux with screen, simply check with
screen -ls
on windows, just check the task-manager and look under something like Python.
It's btw possible to have the same bot running twice.

how to test event in discord.py

lets say on_member_join event
#commands.Cog.listener()
async def on_member_join(self, member):
# On member joins we find a channel called general and if it exists,
# send an embed welcoming them to our guild
channel = discord.utils.get(member.guild.text_channels, name="welcome")
if channel:
embed = discord.Embed(
description="Welcome to our guild!",
color=random.choice(self.bot.color_list),
)
embed.set_thumbnail(url=member.avatar_url)
embed.set_author(name=member.name, icon_url=member.avatar_url)
embed.set_footer(text=member.guild, icon_url=member.guild.icon_url)
embed.timestamp = datetime.datetime.utcnow()
await channel.send(embed=embed)
This is my event (I know it works) how can I test it in any way to execute command to emit the event (not manually by adding and removing someone)?
[something like .emit on_member_join #user where arg1 is event and if needed arg2 is mention or id of channel ]
Any command for that ?
something like Discord.js: Manually triggering events but in discord.py not in JavaScript
Currently there isn't official support in the discord.py api to do something like that but you can always make a command in the cog like follows:
#commands.command()
async def test_join(self, ctx, member: discord.Member):
await self.on_member_join(member)
Technically there is a way to probably do it that isn't documented...
Line 131 in here. I will not offer addition support for that because it isn't documented.

Resources