diff --git a/royalnet/audio/__init__.py b/royalnet/audio/__init__.py index bd1458bf..711f3e44 100644 --- a/royalnet/audio/__init__.py +++ b/royalnet/audio/__init__.py @@ -1,5 +1,6 @@ from .playmodes import PlayMode, Playlist, Pool from .youtubedl import YtdlFile, YtdlInfo from .royalpcmfile import RoyalPCMFile +from .royalpcmaudio import RoyalPCMAudio -__all__ = ["PlayMode", "Playlist", "Pool", "YtdlFile", "YtdlInfo", "RoyalPCMFile"] +__all__ = ["PlayMode", "Playlist", "Pool", "YtdlFile", "YtdlInfo", "RoyalPCMFile", "RoyalPCMAudio"] diff --git a/royalnet/audio/royalpcmaudio.py b/royalnet/audio/royalpcmaudio.py index 90144913..5ba95064 100644 --- a/royalnet/audio/royalpcmaudio.py +++ b/royalnet/audio/royalpcmaudio.py @@ -1,8 +1,7 @@ from discord import AudioSource from discord.opus import Encoder as OpusEncoder import typing -if typing.TYPE_CHECKING: - from .royalpcmfile import RoyalPCMFile +from .royalpcmfile import RoyalPCMFile class RoyalPCMAudio(AudioSource): @@ -10,6 +9,11 @@ class RoyalPCMAudio(AudioSource): self.rpf: "RoyalPCMFile" = rpf self._file = open(rpf.audio_filename, "rb") + @staticmethod + def create_from_url(url) -> typing.List["RoyalPCMAudio"]: + rpf_list = RoyalPCMFile.create_from_url(url) + return [RoyalPCMAudio(rpf) for rpf in rpf_list] + def cleanup(self): self._file.close() diff --git a/royalnet/audio/royalpcmfile.py b/royalnet/audio/royalpcmfile.py index 51efe180..c112d5d2 100644 --- a/royalnet/audio/royalpcmfile.py +++ b/royalnet/audio/royalpcmfile.py @@ -1,11 +1,8 @@ -import discord import ffmpeg -import re import os import typing import logging as _logging from .youtubedl import YtdlFile, YtdlInfo -from .royalpcmaudio import RoyalPCMAudio log = _logging.getLogger(__name__) @@ -50,8 +47,6 @@ class RoyalPCMFile(YtdlFile): def audio_filename(self): return f"./downloads/{self.info.title}-{self.info.id}.pcm" - def create_audio_source(self): - return RoyalPCMAudio(self) - - def delete_audio_file(self): + def __del__(self): + log.info(f"Deleting {self.audio_filename}") os.remove(self.audio_filename) diff --git a/royalnet/bots/discord.py b/royalnet/bots/discord.py index 8f02262a..3356598c 100644 --- a/royalnet/bots/discord.py +++ b/royalnet/bots/discord.py @@ -8,7 +8,7 @@ from ..utils import asyncify, Call, Command from ..error import UnregisteredError, NoneFoundError, TooManyFoundError, InvalidConfigError from ..network import Message, RoyalnetConfig from ..database import DatabaseConfig -from ..audio import PlayMode, Playlist +from ..audio import PlayMode, Playlist, RoyalPCMAudio loop = asyncio.get_event_loop() log = _logging.getLogger(__name__) @@ -108,6 +108,10 @@ class DiscordBot(GenericBot): # Skip non-text messages if not text: return + # Skip bot messages + author: typing.Union[discord.User] = message.author + if author.bot: + return # Find and clean parameters command_text, *parameters = text.split(" ") # Call the command @@ -193,35 +197,29 @@ class DiscordBot(GenericBot): await self.client.connect() # TODO: how to stop? -# class DiscordBot: -# async def add_to_music_data(self, url: str, guild: discord.Guild): -# """Add a file to the corresponding music_data object.""" -# log.debug(f"Downloading {url} to add to music_data") -# files: typing.List[RoyalPCMFile] = await asyncify(RoyalPCMFile.create_from_url, url) -# guild_music_data = self.music_data[guild] -# for file in files: -# log.debug(f"Adding {file} to music_data") -# guild_music_data.add(file) -# if guild_music_data.now_playing is None: -# log.debug(f"Starting playback chain") -# await self.advance_music_data(guild) -# -# async def advance_music_data(self, guild: discord.Guild): -# """Try to play the next song, while it exists. Otherwise, just return.""" -# guild_music_data = self.music_data[guild] -# voice_client = self.find_voice_client(guild) -# next_file: RoyalPCMFile = await guild_music_data.next() -# if next_file is None: -# log.debug(f"Ending playback chain") -# return -# -# def advance(error=None): -# log.debug(f"Deleting {next_file}") -# next_file.delete_audio_file() -# loop.create_task(self.advance_music_data(guild)) -# -# log.debug(f"Creating AudioSource of {next_file}") -# next_source = next_file.create_audio_source() -# log.debug(f"Starting playback of {next_source}") -# voice_client.play(next_source, after=advance) -# + async def add_to_music_data(self, url: str, guild: discord.Guild): + """Add a file to the corresponding music_data object.""" + log.debug(f"Adding {url} to music_data of {guild}") + guild_music_data = self.music_data[guild] + audio_sources = RoyalPCMAudio.create_from_url(url) + for audio_source in audio_sources: + log.debug(f"Adding {audio_source} to music_data") + guild_music_data.add(audio_source) + if guild_music_data.now_playing is None: + log.debug(f"Starting playback chain") + await self.advance_music_data(guild) + + async def advance_music_data(self, guild: discord.Guild): + """Try to play the next song, while it exists. Otherwise, just return.""" + guild_music_data = self.music_data[guild] + voice_client = self.client.find_voice_client_by_guild(guild) + next_source: RoyalPCMAudio = await guild_music_data.next() + if next_source is None: + log.debug(f"Ending playback chain") + return + + def advance(error=None): + loop.create_task(self.advance_music_data(guild)) + + log.debug(f"Starting playback of {next_source}") + voice_client.play(next_source, after=advance) diff --git a/royalnet/commands/play.py b/royalnet/commands/play.py index 977bb64a..8bad9313 100644 --- a/royalnet/commands/play.py +++ b/royalnet/commands/play.py @@ -21,7 +21,7 @@ class PlayNH(NetworkHandler): message_type = PlayMessage @classmethod - async def nh_play(cls, bot: "DiscordBot", message: PlayMessage): + async def discord(cls, bot: "DiscordBot", message: PlayMessage): """Handle a play Royalnet request. That is, add audio to a PlayMode.""" # Find the matching guild if message.guild_identifier: diff --git a/royalnet/commands/summon.py b/royalnet/commands/summon.py index 27fc4240..d34049b7 100644 --- a/royalnet/commands/summon.py +++ b/royalnet/commands/summon.py @@ -48,7 +48,7 @@ class SummonCommand(Command): @classmethod async def discord(cls, call: Call): - bot = call.interface_obj.bot + bot = call.interface_obj.client message: discord.Message = call.kwargs["message"] channel_name: str = call.args.optional(0) if channel_name: