2023-05-03 19:53:01 +03:00
|
|
|
|
import discord
|
|
|
|
|
import yt_dlp as youtube_dl
|
|
|
|
|
import functools
|
|
|
|
|
import asyncio
|
|
|
|
|
|
|
|
|
|
from loguru import logger
|
|
|
|
|
from json import dumps
|
2023-05-06 23:53:55 +03:00
|
|
|
|
from discord import app_commands
|
2023-05-03 19:53:01 +03:00
|
|
|
|
from discord.ext import commands
|
|
|
|
|
|
|
|
|
|
from bot import db
|
|
|
|
|
|
2023-05-09 23:24:00 +03:00
|
|
|
|
FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
|
|
|
|
|
YDL_OPTIONS = {'format': 'bestaudio', 'noplaylist':'True'}
|
|
|
|
|
|
2023-05-06 23:53:55 +03:00
|
|
|
|
# TODO: locale
|
|
|
|
|
|
2023-05-03 19:53:01 +03:00
|
|
|
|
class Music(commands.Cog, name="Музыка"):
|
|
|
|
|
def __init__(self, bot):
|
|
|
|
|
self.bot = bot
|
2023-05-09 23:24:00 +03:00
|
|
|
|
self.queue = {}
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-09 23:24:00 +03:00
|
|
|
|
def play_(self, inter, info):
|
2023-05-03 19:53:01 +03:00
|
|
|
|
try:
|
|
|
|
|
URL = info['url']
|
|
|
|
|
except:
|
|
|
|
|
URL = url
|
|
|
|
|
logger.debug(URL)
|
2023-05-09 23:24:00 +03:00
|
|
|
|
|
2023-05-03 19:53:01 +03:00
|
|
|
|
audio_source = discord.FFmpegPCMAudio(URL, **FFMPEG_OPTIONS)
|
2023-05-06 23:53:55 +03:00
|
|
|
|
inter.guild.voice_client.play(audio_source, after=lambda error: self.next_(inter, error))
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-09 23:24:00 +03:00
|
|
|
|
asyncio.run_coroutine_threadsafe(self.send_embed_(inter, info), self.bot.loop)
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-09 23:24:00 +03:00
|
|
|
|
async def send_embed_(self, inter, info):
|
2023-05-03 19:53:01 +03:00
|
|
|
|
embed = discord.Embed (
|
|
|
|
|
title=info["title"],
|
2023-05-09 23:24:00 +03:00
|
|
|
|
url=info['url'],
|
2023-05-03 19:53:01 +03:00
|
|
|
|
description=info["description"]
|
|
|
|
|
)
|
|
|
|
|
embed.set_author (
|
|
|
|
|
name=info["uploader"],
|
|
|
|
|
url=info["uploader_url"]
|
|
|
|
|
)
|
|
|
|
|
embed.set_thumbnail( url=info["thumbnail"] )
|
2023-05-07 01:15:06 +03:00
|
|
|
|
try:
|
|
|
|
|
await inter.response.send_message(embed=embed)
|
|
|
|
|
except:
|
|
|
|
|
await inter.channel.send(embed=embed)
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-09 23:24:00 +03:00
|
|
|
|
async def end_of_queue_(self, inter):
|
|
|
|
|
await inter.channel.send("В очереди больше не осталось песен")
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-06 23:53:55 +03:00
|
|
|
|
@app_commands.command(description="Plays music from popular platforms")
|
2023-05-07 01:15:06 +03:00
|
|
|
|
@app_commands.describe(url="URL from Youtube/RuTube and other platforms")
|
|
|
|
|
async def play(self, inter, url: str):
|
|
|
|
|
logger.debug(asyncio.get_running_loop())
|
2023-05-06 23:53:55 +03:00
|
|
|
|
channel = inter.user.voice.channel
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-06 23:53:55 +03:00
|
|
|
|
if inter.user.voice is None:
|
|
|
|
|
await inter.response.send_message("Ты не в ГК")
|
2023-05-03 19:53:01 +03:00
|
|
|
|
return
|
2023-05-06 23:53:55 +03:00
|
|
|
|
if inter.guild.voice_client is None:
|
2023-05-03 19:53:01 +03:00
|
|
|
|
await channel.connect()
|
2023-05-09 23:24:00 +03:00
|
|
|
|
self.queue[channel.id] = {
|
|
|
|
|
"adder": inter.user.id,
|
|
|
|
|
"cur_pos": 0,
|
|
|
|
|
"queue": [],
|
|
|
|
|
"context": inter,
|
|
|
|
|
"skip_policy": "everyone"
|
|
|
|
|
}
|
2023-05-06 23:53:55 +03:00
|
|
|
|
elif inter.user.voice.channel != inter.guild.voice_client.channel:
|
|
|
|
|
await inter.response.send_message(f"Занято каналом {inter.guild.voice_client.channel.mention}")
|
2023-05-03 19:53:01 +03:00
|
|
|
|
return
|
|
|
|
|
|
2023-05-06 23:53:55 +03:00
|
|
|
|
client = inter.guild.voice_client
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-09 23:24:00 +03:00
|
|
|
|
with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl:
|
|
|
|
|
info = ydl.extract_info(url, download=False)
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-09 23:24:00 +03:00
|
|
|
|
self.queue[channel.id]["queue"].append({'requester': inter.user.id, 'url': url, 'info': info})
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-06 23:53:55 +03:00
|
|
|
|
if client.is_playing() or client.is_paused():
|
2023-05-07 01:15:06 +03:00
|
|
|
|
await inter.response.send_message("Добавлена новая песня в очередь")
|
|
|
|
|
return
|
|
|
|
|
else:
|
|
|
|
|
inter.guild.voice_client.stop()
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-09 23:24:00 +03:00
|
|
|
|
self.play_(inter, info)
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
2023-05-06 23:53:55 +03:00
|
|
|
|
@app_commands.command()
|
|
|
|
|
async def stop(self, inter):
|
2023-05-09 23:24:00 +03:00
|
|
|
|
queue = self.queue[inter.user.voice.channel.id]
|
|
|
|
|
queue['cur_pos'] = len(queue['queue'])-1
|
2023-05-06 23:53:55 +03:00
|
|
|
|
inter.guild.voice_client.stop()
|
|
|
|
|
await inter.response.send_message("Остановлено")
|
|
|
|
|
|
|
|
|
|
@app_commands.command()
|
|
|
|
|
async def pause(self, inter):
|
|
|
|
|
inter.guild.voice_client.pause()
|
|
|
|
|
await inter.response.send_message("Поставлено на паузу")
|
|
|
|
|
|
|
|
|
|
@app_commands.command()
|
|
|
|
|
async def resume(self, inter):
|
|
|
|
|
inter.guild.voice_client.resume()
|
|
|
|
|
await inter.response.send_message("Снято с паузы")
|
|
|
|
|
|
|
|
|
|
@app_commands.command()
|
|
|
|
|
async def disconnect(self, inter):
|
|
|
|
|
await inter.guild.voice_client.disconnect()
|
|
|
|
|
await inter.response.send_message("Отключено")
|
|
|
|
|
|
|
|
|
|
@app_commands.command()
|
|
|
|
|
async def next(self, inter):
|
2023-05-09 23:24:00 +03:00
|
|
|
|
inter.guild.voice_client.stop()
|
|
|
|
|
|
|
|
|
|
@app_commands.command(name='queue')
|
|
|
|
|
async def _queue(self, inter):
|
|
|
|
|
queue = self.queue[inter.user.voice.channel.id]
|
|
|
|
|
text = ''
|
|
|
|
|
for pos, item in enumerate(queue['queue']):
|
|
|
|
|
if queue['cur_pos'] == pos: text += '>>> '
|
|
|
|
|
else: text += ' '
|
|
|
|
|
|
|
|
|
|
text += f"{pos+1}. "
|
|
|
|
|
text += item['info']['title']
|
|
|
|
|
text += '\n - Запросил: ' + self.bot.get_user(item['requester']).name
|
|
|
|
|
|
|
|
|
|
text += '\n'
|
|
|
|
|
await inter.response.send_message(f"```\n{text}\n```")
|
|
|
|
|
|
2023-05-06 23:53:55 +03:00
|
|
|
|
|
|
|
|
|
def next_(self, inter, error=None):
|
2023-05-09 23:24:00 +03:00
|
|
|
|
if error:
|
|
|
|
|
logger.error(error)
|
|
|
|
|
return
|
2023-05-07 01:15:06 +03:00
|
|
|
|
|
2023-05-06 23:53:55 +03:00
|
|
|
|
inter.guild.voice_client.stop()
|
2023-05-09 23:24:00 +03:00
|
|
|
|
|
|
|
|
|
queue = self.queue[inter.user.voice.channel.id]
|
|
|
|
|
queue["cur_pos"] += 1
|
|
|
|
|
logger.debug((len(queue["queue"]), queue["cur_pos"]))
|
|
|
|
|
if len(queue["queue"]) == queue["cur_pos"]:
|
|
|
|
|
asyncio.run_coroutine_threadsafe(self.end_of_queue_(inter), self.bot.loop)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
#logger.debug([query["music_pos"]])
|
|
|
|
|
info = queue["queue"][queue["cur_pos"]]['info']
|
|
|
|
|
self.play_(inter, info)
|
2023-05-03 19:53:01 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def setup(bot):
|
|
|
|
|
await bot.add_cog(Music(bot))
|