music play + now playing

This commit is contained in:
2023-05-17 01:04:16 +02:00
parent 0749f742c3
commit d09c2b7a89
21 changed files with 410 additions and 143 deletions

View File

@ -1,2 +1,3 @@
from .fileManager import FileManager
from .playbackManager import PlaybackManager
from .queueManager import QueueManager

View File

@ -1,10 +1,11 @@
import re
from os import path
from collections.abc import AsyncIterator
from os import path, stat
from time import time
from discord import Interaction
from entity import Entry
from entity import Entry, File
from framework import Downloader, Youtube
@ -18,7 +19,7 @@ class FileManager:
self.youtubeVideoRegex = re.compile(
r"(https:\/\/)?(www|music)\.youtube\.com\/(watch\?v=|shorts\/)\w*"
)
self.progressLastUpdate = 0
self.progressLastUpdate = 0.0
def getFileName(self, entryId: str) -> str:
return path.join(self.downloadDirectory, entryId)
@ -27,24 +28,29 @@ class FileManager:
self,
interaction: Interaction,
entry: Entry,
current_size: int,
total_size: int,
current_size: float,
total_size: float,
):
if time() - self.progressLastUpdate > 1:
current_size = current_size / 1024 / 1024
total_size = total_size / 1024 / 1024
if time() - self.progressLastUpdate > 1 and total_size > 10:
self.progressLastUpdate = time()
await interaction.edit_original_response(
content=f"Downloading {entry.title.name} [%.2f/%.2f Mo]"
% (current_size / 1024 / 1024, total_size / 1024 / 1024)
% (current_size, total_size)
)
async def download(self, interaction: Interaction, entries: list[Entry]):
async def download(
self, interaction: Interaction, entries: list[Entry]
) -> AsyncIterator[File]:
for entry in entries:
entryId = self.youtube.getId(entry.title.url)
print("DOWNLOAD", entry.source)
entryId = self.youtube.getId(entry.source)
fileName = self.getFileName(entryId)
if not path.isfile(fileName) and isinstance(entry.source, str):
if self.youtubeVideoRegex.match(entry.source) is not None:
entry.source = await self.youtube.download(
yield await self.youtube.download(
entry.source,
fileName,
lambda current_size, total_size: self.downloadProgress(
@ -52,10 +58,12 @@ class FileManager:
),
)
else:
entry.source = await self.downloader.download(
yield await self.downloader.download(
entry.source,
fileName,
lambda current_size, total_size: self.downloadProgress(
interaction, entry, current_size, total_size
),
)
yield File(fileName, stat(fileName).st_size)

View File

@ -0,0 +1,59 @@
from discord import TextChannel, VoiceChannel
from entity import Queue
from framework import DiscordPlayer
class ActiveQueue:
def __init__(
self, queue: Queue, textChannel: TextChannel, voiceChannel: VoiceChannel
) -> None:
self.queue = queue
self.textChannel = textChannel
self.voiceChannel = voiceChannel
class PlaybackManager:
def __init__(self, player: DiscordPlayer) -> None:
self.player = player
self.queues: dict[int, ActiveQueue] = {}
async def nextTrack(self, error: Exception, guildId: int):
queue = self.queues[guildId].queue
textChannel = self.queues[guildId].textChannel
queue.incrementCursor()
if queue.cursor < len(queue):
self.startPlayback(guildId)
await textChannel.send(f"Playing {queue[queue.cursor].title.name}")
else:
self.stopPlayback(guildId)
def startPlayback(self, guildId: int, seekTime=0):
queue = self.queues[guildId].queue
if len(queue) > queue.cursor and not queue.playing:
queue.startPlaying()
self.player.play(
guildId,
queue[queue.cursor].source,
seekTime,
lambda error: self.nextTrack(error, guildId),
)
def stopPlayback(self, guildId: int):
queue = self.queues[guildId].queue
if queue.playing:
queue.stopPlaying()
self.player.stop(guildId)
async def registerQueue(
self,
guildId: int,
queue: Queue,
textChannel: TextChannel,
voiceChannel: VoiceChannel,
):
if guildId not in self.queues:
self.queues[guildId] = ActiveQueue(queue, textChannel, voiceChannel)
await self.player.connect(guildId, voiceChannel)
self.startPlayback(guildId)

View File

@ -1,3 +1,4 @@
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from entity import Queue
@ -10,21 +11,13 @@ class QueueManager:
self.queues: dict[int, Queue] = {}
@asynccontextmanager
async def __call__(self, guildId: int) -> Queue:
# await self.acquire(guildId)
async def __call__(self, guildId: int) -> AsyncIterator[Queue]:
queue = await self.get(guildId)
yield queue
await self.save(guildId)
# await self.release(guildId)
async def acquire(self, guildId: int) -> None:
await self.redis.acquire(guildId)
async def release(self, guildId: int) -> None:
await self.redis.release(guildId)
async def get(self, guildId: int) -> Queue:
queue: Queue | None = await self.redis.get(guildId)
queue: Queue | None = await self.redis.get("queue", str(guildId))
if queue is None:
queue = Queue()
self.queues[guildId] = queue
@ -32,4 +25,4 @@ class QueueManager:
return self.queues[guildId]
async def save(self, guildId: int) -> None:
await self.redis.set(guildId, self.queues[guildId])
await self.redis.set("queue", str(guildId), self.queues[guildId])