music play + now playing
This commit is contained in:
@ -1,2 +1,3 @@
|
||||
from .fileManager import FileManager
|
||||
from .playbackManager import PlaybackManager
|
||||
from .queueManager import QueueManager
|
||||
|
@ -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)
|
||||
|
59
service/playbackManager.py
Normal file
59
service/playbackManager.py
Normal 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)
|
@ -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])
|
||||
|
Reference in New Issue
Block a user