Skip to content

Commit 596937c

Browse files
committed
📝 Add soundboard.py example 🎉
1 parent f4e32ee commit 596937c

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

examples/soundboard.py

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import asyncio
2+
import logging
3+
import os
4+
5+
from dotenv import load_dotenv
6+
7+
import discord
8+
9+
logging.basicConfig(level=logging.INFO)
10+
11+
load_dotenv()
12+
TOKEN = os.getenv("TOKEN")
13+
14+
bot = discord.Bot(intents=discord.Intents.all())
15+
16+
17+
class SoundboardCog(discord.Cog):
18+
"""A cog demonstrating Discord's soundboard features."""
19+
20+
def __init__(self, bot: discord.Bot):
21+
self.bot = bot
22+
23+
@discord.Cog.listener()
24+
async def on_voice_channel_effect_send(
25+
self, event: discord.VoiceChannelEffectSendEvent
26+
):
27+
"""Called when someone uses a soundboard effect in a voice channel."""
28+
if event.sound:
29+
print(f"{event.user} played sound '{event.sound.name}' in {event.channel}")
30+
elif event.emoji:
31+
print(f"{event.user} sent emoji effect {event.emoji} in {event.channel}")
32+
33+
@discord.slash_command()
34+
async def list_sounds(self, ctx: discord.ApplicationContext):
35+
"""Lists all available sounds in the guild."""
36+
await ctx.defer()
37+
38+
# Fetch both default and guild-specific sounds
39+
default_sounds = await self.bot.fetch_default_sounds()
40+
guild_sounds = await ctx.guild.fetch_sounds()
41+
42+
embed = discord.Embed(title="Available Sounds")
43+
44+
# List default sounds
45+
if default_sounds:
46+
default_list = "\n".join(
47+
f"{s.emoji} {s.name} (Volume: {s.volume})" for s in default_sounds
48+
)
49+
embed.add_field(
50+
name="Default Sounds", value=default_list or "None", inline=False
51+
)
52+
53+
# List guild sounds
54+
if guild_sounds:
55+
guild_list = "\n".join(
56+
f"{s.emoji} {s.name} (Volume: {s.volume})" for s in guild_sounds
57+
)
58+
embed.add_field(
59+
name="Guild Sounds", value=guild_list or "None", inline=False
60+
)
61+
62+
await ctx.respond(embed=embed)
63+
64+
@discord.slash_command()
65+
@discord.default_permissions(manage_guild=True)
66+
async def add_sound(
67+
self,
68+
ctx: discord.ApplicationContext,
69+
name: str,
70+
emoji: str,
71+
attachment: discord.Attachment,
72+
):
73+
"""Adds a new sound to the guild's soundboard. Currently only supports mp3 files."""
74+
await ctx.defer()
75+
76+
if not attachment.content_type.startswith("audio/"):
77+
return await ctx.respond("Please upload an audio file!")
78+
79+
try:
80+
sound_bytes = await attachment.read()
81+
emoji = discord.PartialEmoji.from_str(emoji)
82+
83+
new_sound = await ctx.guild.create_sound(
84+
name=name, sound=sound_bytes, volume=1.0, emoji=emoji
85+
)
86+
87+
await ctx.respons(f"Added new sound: {new_sound.emoji} {new_sound.name}")
88+
except Exception as e:
89+
await ctx.respond(f"Failed to add sound: {str(e)}")
90+
91+
@discord.slash_command()
92+
@discord.default_permissions(manage_guild=True)
93+
async def edit_sound(
94+
self,
95+
ctx: discord.ApplicationContext,
96+
sound_name: str,
97+
new_name: str | None = None,
98+
new_emoji: str | None = None,
99+
new_volume: float | None = None,
100+
):
101+
"""Edit an existing sound in the guild's soundboard."""
102+
await ctx.defer()
103+
104+
# Find the sound by name
105+
sounds = await ctx.guild.fetch_sounds()
106+
sound = discord.utils.get(sounds, name=sound_name)
107+
108+
if not sound:
109+
return await ctx.respond(f"Sound '{sound_name}' not found!")
110+
111+
try:
112+
await sound.edit(
113+
name=new_name or sound.name,
114+
emoji=(
115+
discord.PartialEmoji.from_str(new_emoji)
116+
if new_emoji
117+
else sound.emoji
118+
),
119+
volume=new_volume or sound.volume,
120+
)
121+
await ctx.respond(f"Updated sound: {sound.emoji} {sound.name}")
122+
except Exception as e:
123+
await ctx.respond(f"Failed to edit sound: {str(e)}")
124+
125+
@discord.slash_command()
126+
async def play_sound(
127+
self,
128+
ctx: discord.ApplicationContext,
129+
sound_name: str,
130+
channel: discord.VoiceChannel | None = None,
131+
):
132+
"""Plays a sound in a voice channel."""
133+
await ctx.defer()
134+
135+
# Use author's voice channel if none specified
136+
if not channel and ctx.author.voice:
137+
channel = ctx.author.voice.channel
138+
if not channel:
139+
return await ctx.respond("Please specify a voice channel or join one!")
140+
141+
try:
142+
# Find the sound
143+
sounds = await ctx.guild.fetch_sounds()
144+
sound = discord.utils.get(sounds, name=sound_name)
145+
if not sound:
146+
# Check default sounds if not found in guild sounds
147+
defaults = await self.bot.fetch_default_sounds()
148+
sound = discord.utils.get(defaults, name=sound_name)
149+
150+
if not sound:
151+
return await ctx.respond(f"Sound '{sound_name}' not found!")
152+
153+
# Connect to voice channel if not already connected
154+
voice_client = await channel.connect()
155+
156+
# Play the sound
157+
await channel.send_soundboard_sound(sound)
158+
await ctx.respond(f"Playing sound: {sound.emoji} {sound.name}")
159+
160+
await asyncio.sleep(6)
161+
if voice_client.is_connected():
162+
await voice_client.disconnect()
163+
164+
except Exception as e:
165+
await ctx.respond(f"Failed to play sound: {str(e)}")
166+
167+
168+
bot.add_cog(SoundboardCog(bot))
169+
170+
bot.run(TOKEN)

0 commit comments

Comments
 (0)