Add files via upload

This commit is contained in:
streloss
2026-03-11 22:51:17 +09:00
committed by GitHub
parent 5eb1c53ceb
commit 2dcaaf2290
3 changed files with 324 additions and 0 deletions

167
cogs/music.py Normal file
View File

@@ -0,0 +1,167 @@
import discord
from discord.ext import commands
from discord import app_commands
import asyncio
from cogs.player import (
YTDLSource, get_player,
now_playing_embed, fmt_duration
)
class Music(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
# ── Внутренний метод: следующий трек ──────
async def play_next(self, guild: discord.Guild, channel: discord.TextChannel):
player = get_player(guild.id)
vc: discord.VoiceClient = guild.voice_client
if not vc:
return
# Повтор текущего трека
if player.loop and player.current:
try:
source = await YTDLSource.from_url(player.current.url, loop=self.bot.loop)
source.volume = player.volume
player.current = source
vc.play(source, after=lambda e: asyncio.run_coroutine_threadsafe(
self.play_next(guild, channel), self.bot.loop))
await channel.send(embed=now_playing_embed(source))
except Exception as e:
await channel.send(f"❌ Ошибка повтора: {e}")
return
if player.queue:
url = player.queue.popleft()
try:
source = await YTDLSource.from_url(url, loop=self.bot.loop)
except Exception as e:
await channel.send(f"❌ Ошибка воспроизведения: {e}")
return
source.volume = player.volume
player.current = source
vc.play(source, after=lambda e: asyncio.run_coroutine_threadsafe(
self.play_next(guild, channel), self.bot.loop))
await channel.send(embed=now_playing_embed(source))
else:
player.current = None
await channel.send("✅ Очередь закончилась.")
# ── /play ─────────────────────────────────
@app_commands.command(name="play", description="Воспроизвести трек по названию или ссылке")
@app_commands.describe(query="Название песни или YouTube ссылка")
async def play(self, interaction: discord.Interaction, query: str):
await interaction.response.defer()
if not interaction.user.voice:
return await interaction.followup.send("❌ Сначала зайди в голосовой канал!")
vc: discord.VoiceClient = interaction.guild.voice_client
if not vc:
vc = await interaction.user.voice.channel.connect()
elif interaction.user.voice.channel != vc.channel:
await vc.move_to(interaction.user.voice.channel)
player = get_player(interaction.guild.id)
try:
source = await YTDLSource.from_url(query, loop=self.bot.loop)
except Exception as e:
return await interaction.followup.send(f"Не удалось найти трек: {e}")
source.volume = player.volume
if vc.is_playing() or vc.is_paused():
player.queue.append(source.url)
embed = discord.Embed(
title="📥 Добавлено в очередь",
description=f"**{source.title}**",
color=0x5865F2
)
embed.add_field(name="Позиция", value=str(len(player.queue)))
return await interaction.followup.send(embed=embed)
player.current = source
vc.play(source, after=lambda e: asyncio.run_coroutine_threadsafe(
self.play_next(interaction.guild, interaction.channel), self.bot.loop))
await interaction.followup.send(embed=now_playing_embed(source))
# ── /skip ─────────────────────────────────
@app_commands.command(name="skip", description="Пропустить текущий трек")
async def skip(self, interaction: discord.Interaction):
vc = interaction.guild.voice_client
if vc and vc.is_playing():
vc.stop()
await interaction.response.send_message("⏭️ Трек пропущен.")
else:
await interaction.response.send_message("❌ Ничего не играет.")
# ── /pause ────────────────────────────────
@app_commands.command(name="pause", description="Пауза / продолжить")
async def pause(self, interaction: discord.Interaction):
vc = interaction.guild.voice_client
if vc and vc.is_playing():
vc.pause()
await interaction.response.send_message("⏸️ Пауза.")
elif vc and vc.is_paused():
vc.resume()
await interaction.response.send_message("▶️ Продолжаю.")
else:
await interaction.response.send_message("❌ Ничего не играет.")
# ── /stop ─────────────────────────────────
@app_commands.command(name="stop", description="Остановить музыку и очистить очередь")
async def stop(self, interaction: discord.Interaction):
player = get_player(interaction.guild.id)
player.queue.clear()
player.current = None
vc = interaction.guild.voice_client
if vc:
vc.stop()
await vc.disconnect()
await interaction.response.send_message("⏹️ Остановлено, очередь очищена.")
# ── /loop ─────────────────────────────────
@app_commands.command(name="loop", description="Включить/выключить повтор трека")
async def loop(self, interaction: discord.Interaction):
player = get_player(interaction.guild.id)
player.loop = not player.loop
status = "включён 🔁" if player.loop else "выключен ➡️"
await interaction.response.send_message(f"Повтор {status}")
# ── /nowplaying ───────────────────────────
@app_commands.command(name="nowplaying", description="Текущий трек")
async def nowplaying(self, interaction: discord.Interaction):
player = get_player(interaction.guild.id)
if player.current:
await interaction.response.send_message(embed=now_playing_embed(player.current))
else:
await interaction.response.send_message("❌ Ничего не играет.")
# ── /volume ───────────────────────────────
@app_commands.command(name="volume", description="Громкость от 1 до 100")
@app_commands.describe(level="Уровень громкости (1100)")
async def volume(self, interaction: discord.Interaction, level: int):
if not 1 <= level <= 100:
return await interaction.response.send_message("❌ Укажи значение от 1 до 100.")
player = get_player(interaction.guild.id)
player.volume = level / 100
vc = interaction.guild.voice_client
if vc and vc.source:
vc.source.volume = player.volume
await interaction.response.send_message(f"🔊 Громкость: **{level}%**")
# ── /leave ────────────────────────────────
@app_commands.command(name="leave", description="Выгнать бота из канала")
async def leave(self, interaction: discord.Interaction):
vc = interaction.guild.voice_client
if vc:
await vc.disconnect()
await interaction.response.send_message("👋 Отключился.")
else:
await interaction.response.send_message("❌ Я не в канале.")
async def setup(bot: commands.Bot):
await bot.add_cog(Music(bot))