Skip to content

Commit fab50da

Browse files
committed
ajout play_music command
1 parent 1a3ab06 commit fab50da

File tree

5 files changed

+103
-19
lines changed

5 files changed

+103
-19
lines changed

app/_app.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from discord import app_commands
22
import asyncio
3-
from config import os, bot, tree, logger, discord, TOKEN
4-
from tools import help, clear_slash, start_Session, Wait, presentation_bot
3+
from config import os, bot, tree, logger, discord, TOKEN, ROLE_ID_F1PADDOCKCLUB
4+
import tools as tool
55
import error_embed as embed
66
import classement as ldb
77
from admin_command import ban
@@ -26,13 +26,13 @@ async def on_ready():
2626
@tree.command(name="clear", description="Supprime des messages (admin uniquement)")
2727
@app_commands.describe(nombre="Nombre de messages à supprimer")
2828
async def clearing_tool(interaction: discord.Interaction, nombre: int):
29-
await clear_slash(interaction, nombre)
29+
await tool.clear_slash(interaction, nombre)
3030
# _______________________________________________________________________________________________________________________________
3131

3232

3333
@tree.command(name="help", description="Gives you all the commands you can use with this bot")
3434
async def helping_tools(interaction: discord.Interaction):
35-
await help(interaction)
35+
await tool.help(interaction)
3636

3737
# _______________________________________________________________________________________________________________________________
3838

@@ -134,7 +134,7 @@ async def create(interaction: discord.Interaction, duration: float):
134134
global command_enabled
135135
command_enabled = True
136136
task = asyncio.create_task(
137-
start_Session(interaction, duration))
137+
tool.start_Session(interaction, duration))
138138
await task
139139
command_enabled = False
140140
else:
@@ -272,7 +272,7 @@ async def auto_mod(interaction: discord.Interaction):
272272
while (True):
273273
f1api.getNextEvent()
274274
await interaction.followup.send("Le mode auto à bien été lancé", ephemeral=True)
275-
time = Wait()
275+
time = tool.Wait()
276276
logger.info(str(time))
277277
if (time > 0):
278278
await asyncio.sleep(time)
@@ -341,7 +341,7 @@ async def on_message(message: discord.Message):
341341
async def presentation(interaction: discord.Interaction):
342342
await interaction.response.defer(ephemeral=True)
343343
await interaction.followup.send(f"{interaction.user.mention}, va voir tes MP !", ephemeral=False)
344-
await presentation_bot(interaction)
344+
await tool.presentation_bot(interaction)
345345
logger.info(f"{interaction.user} a demandé la présentation du BOT")
346346

347347
# _______________________________________________________________________________________________________________________________
@@ -352,5 +352,17 @@ async def reglement(interaction: discord.Interaction):
352352
await interaction.response.defer(ephemeral=True)
353353
await embed.rules(interaction)
354354
logger.info(f"{interaction.user} a demandé les règles du BOT.")
355+
356+
# _______________________________________________________________________________________________________________________________
357+
358+
359+
@tree.command(name="play_song", description="Joue une musique demander")
360+
@app_commands.describe(title="Nom de la musique")
361+
async def music(interaction: discord.Interaction, title: str):
362+
if any(role.id == ROLE_ID_F1PADDOCKCLUB for role in interaction.user.roles) or interaction.user.guild_permissions.administrator:
363+
await interaction.response.defer(ephemeral=True)
364+
await tool.music_play(interaction, title)
365+
logger.info(f"{interaction.user} a demandé de la musique au BOT.")
366+
355367

356368
bot.run(TOKEN)

app/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,4 @@
6262

6363
PRONOS_ID = 1395093933176131755
6464
GUILD_ID = 1394054995523010761
65+
ROLE_ID_F1PADDOCKCLUB = 992784555150946446

app/pronos.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import fastf1 as f1
77
from datetime import datetime, timezone
88
import pandas as pd
9-
from config import logger
9+
from config import logger, EMBED_COLOR_RED, EMBED_FOOTER_ICON, EMBED_IMAGE, EMBED_THUMBNAIL, EMBED_FOOTER_TEXT
1010
import tools as tool
1111

1212

@@ -110,7 +110,7 @@ async def visualisation(interaction: discord.Interaction):
110110
prono = pronos_database[user_id]
111111
embed = discord.Embed(
112112
title=f"🐐 Merci pour vos pronos {interaction.user} !",
113-
color=discord.Color.red()
113+
color=EMBED_COLOR_RED
114114
)
115115
embed.description = "Voici tes pronostics de course :"
116116
embed.add_field(name="Ton Premier 🥇 :", value=prono.get(
@@ -126,13 +126,17 @@ async def visualisation(interaction: discord.Interaction):
126126
"Modif", True) else "✅ Tu peux modifier ton pronostic en relançant /pronos_course"
127127
embed.add_field(name="Droit de modification :",
128128
value=modif_text, inline=False)
129+
130+
embed.set_footer(text=EMBED_FOOTER_TEXT, icon_url=EMBED_THUMBNAIL)
131+
embed.set_thumbnail(url=interaction.user.display_avatar.url)
132+
embed.set_image(url=EMBED_IMAGE)
129133

130134
# Cas : seulement prono qualif
131135
elif user_id in pronos_database_qualif and user_id not in pronos_database:
132136
prono = pronos_database_qualif[user_id]
133137
embed = discord.Embed(
134138
title=f"🐐 Merci pour vos pronos {interaction.user} !",
135-
color=discord.Color.red()
139+
color=EMBED_COLOR_RED
136140
)
137141
embed.description = "Voici tes pronostics de qualif :"
138142
embed.add_field(name="Ton Premier 🥇 :", value=prono.get(
@@ -146,14 +150,18 @@ async def visualisation(interaction: discord.Interaction):
146150
"Modif", True) else "✅ Tu peux modifier ton pronostic en relançant /pronos_qualif"
147151
embed.add_field(name="Droit de modification :",
148152
value=modif_text, inline=False)
153+
154+
embed.set_footer(text=EMBED_FOOTER_TEXT, icon_url=EMBED_THUMBNAIL)
155+
embed.set_thumbnail(url=interaction.user.display_avatar.url)
156+
embed.set_image(url=EMBED_IMAGE)
149157

150158
# Cas : les deux pronos existent
151159
elif user_id in pronos_database and user_id in pronos_database_qualif:
152160
pr_course = pronos_database[user_id]
153161
pr_qualif = pronos_database_qualif[user_id]
154162
embed = discord.Embed(
155163
title=f"🐐 Merci pour vos pronos {interaction.user} !",
156-
color=discord.Color.red()
164+
color=EMBED_COLOR_RED
157165
)
158166

159167
embed.description = "Voici tes pronostics complets :"
@@ -180,13 +188,17 @@ async def visualisation(interaction: discord.Interaction):
180188
"Modif", True) else "✅ Tu peux modifier ton prono Course (/pronos_course)"
181189
embed.add_field(name="Droits de modification :",
182190
value=f"{modif_q}\n{modif_c}", inline=False)
191+
192+
embed.set_footer(text=EMBED_FOOTER_TEXT, icon_url=EMBED_THUMBNAIL)
193+
embed.set_thumbnail(url=interaction.user.display_avatar.url)
194+
embed.set_image(url=EMBED_IMAGE)
183195

184196
# Cas : aucun prono
185197
else:
186198
embed = discord.Embed(
187199
title=f"Désolé {interaction.user} !",
188200
description="On dirait que tu n'as pas encore fait de pronostic.",
189-
color=discord.Color.red()
201+
color=EMBED_COLOR_RED
190202
)
191203

192204
# Envoi final

app/tools.py

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
import asyncio
44
from datetime import timedelta, datetime
55
from config import os
6-
import fastf1 as f1api
7-
import classement as ldb
6+
import yt_dlp
87
import json
9-
from error_embed import info_embed, no_prono
8+
from error_embed import info_embed
109

1110

1211
def ensure_file_exists(path):
@@ -23,8 +22,8 @@ async def help(interaction: discord.Interaction):
2322
)
2423

2524
# Commandes utilisateurs
26-
embed.add_field(
27-
name="/help", value="📖 Affiche cette liste d’aide", inline=False)
25+
embed.add_field(name="/help",
26+
value="📖 Affiche cette liste d’aide", inline=False)
2827
embed.add_field(name="/pronos_course",
2928
value="🏁 Enregistre ou modifie ton pronostic pour la **course**", inline=False)
3029
embed.add_field(name="/pronos_qualif",
@@ -35,8 +34,10 @@ async def help(interaction: discord.Interaction):
3534
value="🏆 Affiche le classement général", inline=False)
3635
embed.add_field(name="/presentation",
3736
value="🤖 Laisse le bot se présenter et choisis-lui un nom", inline=False)
38-
embed.add_field(
39-
name="/rules", value="📏 Affiche le règlement d’utilisation du bot", inline=False)
37+
embed.add_field(name="/rules",
38+
value="📏 Affiche le règlement d’utilisation du bot", inline=False)
39+
embed.add_field(name="/play_music",
40+
value="🎶 Joue une chanson demander (Reservé au Booster)", inline=False)
4041

4142
# Commandes admin
4243
embed.add_field(
@@ -164,3 +165,59 @@ async def presentation_bot(interaction: discord.Interaction):
164165
else:
165166
logger.info(
166167
f"Présentation par {interaction.user.name} dans {interaction.channel.name} sur {interaction.guild.name}")
168+
169+
170+
async def music_play(interaction: discord.Interaction, song_name: str):
171+
intents = discord.Intents.default()
172+
intents.message_content = True
173+
intents.voice_states = True
174+
175+
if not interaction.guild.voice_client:
176+
if interaction.user.voice:
177+
channel = interaction.user.voice.channel
178+
await channel.connect()
179+
await interaction.response.send_message("✅ Rejoint le salon vocal", ephemeral=True)
180+
else:
181+
await interaction.response.send_message("❌ Tu dois être dans un salon vocal", ephemeral=True)
182+
return
183+
184+
voice = interaction.guild.voice_client
185+
186+
if not voice:
187+
if interaction.user.voice:
188+
channel = interaction.user.voice.channel
189+
voice = await channel.connect()
190+
else:
191+
await interaction.response.send_message("❌ Tu dois être dans un salon vocal", ephemeral=True)
192+
return
193+
194+
await interaction.response.send_message(f"🔍 Recherche : **{song_name}**", ephemeral=True)
195+
196+
ydl_opts = {'format': 'bestaudio', 'noplaylist': 'True'}
197+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
198+
try:
199+
info = ydl.extract_info(f"ytsearch:{song_name}", download=False)['entries'][0]
200+
stream_url = info['url']
201+
found_title = info.get('title', song_name)
202+
except Exception as e:
203+
await interaction.followup.send(f"❌ Impossible de lire la musique. Erreur : {e}")
204+
return
205+
206+
# Définir la fonction avant de l'utiliser
207+
async def auto_leave_if_idle(voice_client, delay=300):
208+
await asyncio.sleep(delay)
209+
if not voice_client.is_playing() and not voice_client.is_paused():
210+
await voice_client.disconnect()
211+
logger.info("⏹️ Déconnexion automatique après 5 minutes d'inactivité.")
212+
await interaction.followup.send("⏹️ Déconnexion automatique après 5 minutes d'inactivité.**")
213+
# Ici, interaction n'est plus garanti safe. Tu peux notifier ailleurs si besoin.
214+
215+
def after_playing(err):
216+
if err:
217+
print(f"Erreur de lecture : {err}")
218+
asyncio.create_task(auto_leave_if_idle(voice))
219+
220+
audio_source = discord.FFmpegPCMAudio(stream_url)
221+
voice.play(audio_source, after=after_playing)
222+
223+
await interaction.followup.send(f"🎶 Lecture : **{found_title}**")

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ sphinx
77
sphinx_rtd_theme
88
myst-parser
99
furo
10+
yt-dlp>=2024.4.9
11+
youtube-search-python>=1.6.6
1012

0 commit comments

Comments
 (0)