mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Bot isn't working anymore?
This commit is contained in:
parent
53753cc399
commit
659e0e1965
6 changed files with 65 additions and 26 deletions
|
@ -20,13 +20,11 @@ commands = [PingCommand, ShipCommand, SmecdsCommand, ColorCommand, CiaoruoziComm
|
||||||
KvrollCommand, VideoinfoCommand, SummonCommand, PlayCommand]
|
KvrollCommand, VideoinfoCommand, SummonCommand, PlayCommand]
|
||||||
|
|
||||||
master = RoyalnetServer("localhost", 1234, "sas")
|
master = RoyalnetServer("localhost", 1234, "sas")
|
||||||
tg_bot = TelegramBot(os.environ["TG_AK"], "ws://localhost:1234", "sas", commands, os.environ["DB_PATH"], Royal, Telegram, "tg_id", error_command=ErrorHandlerCommand)
|
# tg_bot = TelegramBot(os.environ["TG_AK"], "ws://localhost:1234", "sas", commands, os.environ["DB_PATH"], Royal, Telegram, "tg_id", error_command=ErrorHandlerCommand)
|
||||||
ds_bot = DiscordBot(os.environ["DS_AK"], "ws://localhost:1234", "sas", commands, os.environ["DB_PATH"], Royal, Discord, "discord_id", error_command=ErrorHandlerCommand)
|
ds_bot = DiscordBot(os.environ["DS_AK"], "ws://localhost:1234", "sas", commands, os.environ["DB_PATH"], Royal, Discord, "discord_id", error_command=ErrorHandlerCommand)
|
||||||
loop.run_until_complete(master.run())
|
loop.run_until_complete(master.run())
|
||||||
# Dirty hack, remove me asap
|
# Dirty hack, remove me asap
|
||||||
loop.create_task(tg_bot.run())
|
# loop.create_task(tg_bot.run())
|
||||||
loop.create_task(ds_bot.run())
|
loop.create_task(ds_bot.run())
|
||||||
print("Commands enabled:")
|
|
||||||
print(tg_bot.generate_botfather_command_string())
|
|
||||||
print("Starting loop...")
|
print("Starting loop...")
|
||||||
loop.run_forever()
|
loop.run_forever()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from .playmodes import PlayMode, Playlist, Pool
|
from .playmodes import PlayMode, Playlist, Pool
|
||||||
from .youtubedl import YtdlFile, YtdlInfo
|
from .youtubedl import YtdlFile, YtdlInfo
|
||||||
from .royalaudiofile import RoyalAudioFile
|
from .royalpcmfile import RoyalPCMFile
|
||||||
|
|
||||||
__all__ = ["PlayMode", "Playlist", "Pool", "YtdlFile", "YtdlInfo", "RoyalAudioFile"]
|
__all__ = ["PlayMode", "Playlist", "Pool", "YtdlFile", "YtdlInfo", "RoyalPCMFile"]
|
||||||
|
|
26
royalnet/audio/royalpcmaudio.py
Normal file
26
royalnet/audio/royalpcmaudio.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
from discord import AudioSource
|
||||||
|
from discord.opus import Encoder as OpusEncoder
|
||||||
|
import typing
|
||||||
|
if typing.TYPE_CHECKING:
|
||||||
|
from .royalpcmfile import RoyalPCMFile
|
||||||
|
|
||||||
|
|
||||||
|
class RoyalPCMAudio(AudioSource):
|
||||||
|
def __init__(self, rpf: "RoyalPCMFile"):
|
||||||
|
self.rpf: "RoyalPCMFile" = rpf
|
||||||
|
self._file = open(rpf.audio_filename, "rb")
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
self._file.close()
|
||||||
|
|
||||||
|
def is_opus(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
data: bytes = self._file.read(OpusEncoder.FRAME_SIZE)
|
||||||
|
if len(data) != OpusEncoder.FRAME_SIZE:
|
||||||
|
return b""
|
||||||
|
return data
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<RoyalPCMAudio {self.rpf.audio_filename}>"
|
|
@ -5,26 +5,28 @@ import os
|
||||||
import typing
|
import typing
|
||||||
import logging as _logging
|
import logging as _logging
|
||||||
from .youtubedl import YtdlFile, YtdlInfo
|
from .youtubedl import YtdlFile, YtdlInfo
|
||||||
|
from .royalpcmaudio import RoyalPCMAudio
|
||||||
|
|
||||||
log = _logging.getLogger(__name__)
|
log = _logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class RoyalAudioFile(YtdlFile):
|
class RoyalPCMFile(YtdlFile):
|
||||||
ytdl_args = {
|
ytdl_args = {
|
||||||
"logger": log, # Log messages to a logging.Logger instance.
|
"logger": log, # Log messages to a logging.Logger instance.
|
||||||
"format": "bestaudio" # Fetch the best audio format available
|
"format": "bestaudio" # Fetch the best audio format available
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, info: "YtdlInfo", **ytdl_args):
|
def __init__(self, info: "YtdlInfo", **ytdl_args):
|
||||||
|
# Preemptively initialize info to be able to generate the filename
|
||||||
|
self.info = info
|
||||||
# Overwrite the new ytdl_args
|
# Overwrite the new ytdl_args
|
||||||
self.ytdl_args = {**self.ytdl_args, **ytdl_args}
|
self.ytdl_args = {**self.ytdl_args, **ytdl_args}
|
||||||
log.info(f"Now downloading {info.webpage_url}")
|
log.info(f"Now downloading {info.webpage_url}")
|
||||||
super().__init__(info, outtmpl="./downloads/%(title)s-%(id)s.ytdl", **self.ytdl_args)
|
super().__init__(info, outtmpl=self._ytdl_filename, **self.ytdl_args)
|
||||||
# Find the audio_filename with a regex (should be video.opus)
|
# Find the audio_filename with a regex (should be video.opus)
|
||||||
log.info(f"Preparing {self.video_filename}...")
|
log.info(f"Preparing {self.video_filename}...")
|
||||||
# Convert the video to opus
|
# Convert the video to pcm
|
||||||
# Actually not needed, but we do this anyways for compression reasons
|
ffmpeg.input(f"./{self.video_filename}") \
|
||||||
ffmpeg.input(self.video_filename) \
|
|
||||||
.output(self.audio_filename, format="s16le", acodec="pcm_s16le", ac=2, ar="48000") \
|
.output(self.audio_filename, format="s16le", acodec="pcm_s16le", ac=2, ar="48000") \
|
||||||
.overwrite_output() \
|
.overwrite_output() \
|
||||||
.run(quiet=not __debug__)
|
.run(quiet=not __debug__)
|
||||||
|
@ -32,21 +34,24 @@ class RoyalAudioFile(YtdlFile):
|
||||||
log.info(f"Deleting {self.video_filename}")
|
log.info(f"Deleting {self.video_filename}")
|
||||||
self.delete_video_file()
|
self.delete_video_file()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<RoyalPCMFile {self.audio_filename}>"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_from_url(url, **ytdl_args) -> typing.List["RoyalAudioFile"]:
|
def create_from_url(url, **ytdl_args) -> typing.List["RoyalPCMFile"]:
|
||||||
info_list = YtdlInfo.create_from_url(url)
|
info_list = YtdlInfo.create_from_url(url)
|
||||||
return [RoyalAudioFile(info) for info in info_list]
|
return [RoyalPCMFile(info) for info in info_list]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _ytdl_filename(self):
|
||||||
|
return f"./downloads/{self.info.title}-{self.info.id}.ytdl"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def audio_filename(self):
|
def audio_filename(self):
|
||||||
return f"./downloads/{self.info.title}-{self.info.id}.pcm"
|
return f"./downloads/{self.info.title}-{self.info.id}.pcm"
|
||||||
|
|
||||||
def as_audio_source(self):
|
def create_audio_source(self):
|
||||||
# TODO: find a way to close this
|
return RoyalPCMAudio(self)
|
||||||
file = open(self.audio_filename, "rb")
|
|
||||||
return discord.PCMAudio(file)
|
|
||||||
|
|
||||||
def delete_audio_file(self):
|
def delete_audio_file(self):
|
||||||
# TODO: can't delete it yet, see as_audio_source()
|
os.remove(self.audio_filename)
|
||||||
# os.remove(self.audio_filename)
|
|
||||||
pass
|
|
|
@ -39,6 +39,9 @@ class YtdlFile:
|
||||||
# Final checks
|
# Final checks
|
||||||
assert os.path.exists(self.video_filename)
|
assert os.path.exists(self.video_filename)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<YtdlFile {self.video_filename}>"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_from_url(url, outtmpl="%(title)s-%(id)s.%(ext)s", **ytdl_args) -> typing.List["YtdlFile"]:
|
def create_from_url(url, outtmpl="%(title)s-%(id)s.%(ext)s", **ytdl_args) -> typing.List["YtdlFile"]:
|
||||||
info_list = YtdlInfo.create_from_url(url)
|
info_list = YtdlInfo.create_from_url(url)
|
||||||
|
|
|
@ -9,7 +9,7 @@ from ..utils import asyncify, Call, Command
|
||||||
from ..error import UnregisteredError, NoneFoundError, TooManyFoundError
|
from ..error import UnregisteredError, NoneFoundError, TooManyFoundError
|
||||||
from ..network import RoyalnetLink, Message, RequestSuccessful, RequestError
|
from ..network import RoyalnetLink, Message, RequestSuccessful, RequestError
|
||||||
from ..database import Alchemy, relationshiplinkchain
|
from ..database import Alchemy, relationshiplinkchain
|
||||||
from ..audio import RoyalAudioFile, PlayMode, Playlist, Pool
|
from ..audio import RoyalPCMFile, PlayMode, Playlist, Pool
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
log = _logging.getLogger(__name__)
|
log = _logging.getLogger(__name__)
|
||||||
|
@ -213,7 +213,7 @@ class DiscordBot:
|
||||||
|
|
||||||
async def network_handler(self, message: Message) -> Message:
|
async def network_handler(self, message: Message) -> Message:
|
||||||
"""Handle a Royalnet request."""
|
"""Handle a Royalnet request."""
|
||||||
log.debug(f"Received a {message.__class__.__name__}")
|
log.debug(f"Received {message} from Royalnet")
|
||||||
if isinstance(message, SummonMessage):
|
if isinstance(message, SummonMessage):
|
||||||
return await self.nh_summon(message)
|
return await self.nh_summon(message)
|
||||||
elif isinstance(message, PlayMessage):
|
elif isinstance(message, PlayMessage):
|
||||||
|
@ -229,27 +229,34 @@ class DiscordBot:
|
||||||
|
|
||||||
async def add_to_music_data(self, url: str, guild: discord.Guild):
|
async def add_to_music_data(self, url: str, guild: discord.Guild):
|
||||||
"""Add a file to the corresponding music_data object."""
|
"""Add a file to the corresponding music_data object."""
|
||||||
files: typing.List[RoyalAudioFile] = await asyncify(RoyalAudioFile.create_from_url, url)
|
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]
|
guild_music_data = self.music_data[guild]
|
||||||
for file in files:
|
for file in files:
|
||||||
|
log.debug(f"Adding {file} to music_data")
|
||||||
guild_music_data.add(file)
|
guild_music_data.add(file)
|
||||||
if guild_music_data.now_playing is None:
|
if guild_music_data.now_playing is None:
|
||||||
|
log.debug(f"Starting playback chain")
|
||||||
await self.advance_music_data(guild)
|
await self.advance_music_data(guild)
|
||||||
|
|
||||||
async def advance_music_data(self, guild: discord.Guild):
|
async def advance_music_data(self, guild: discord.Guild):
|
||||||
"""Try to play the next song, while it exists. Otherwise, just return."""
|
"""Try to play the next song, while it exists. Otherwise, just return."""
|
||||||
guild_music_data = self.music_data[guild]
|
guild_music_data = self.music_data[guild]
|
||||||
voice_client = self.find_voice_client(guild)
|
voice_client = self.find_voice_client(guild)
|
||||||
next_file: RoyalAudioFile = await guild_music_data.next()
|
next_file: RoyalPCMFile = await guild_music_data.next()
|
||||||
if next_file is None:
|
if next_file is None:
|
||||||
|
log.debug(f"Ending playback chain")
|
||||||
return
|
return
|
||||||
|
|
||||||
def advance(error=None):
|
def advance(error=None):
|
||||||
|
log.debug(f"Deleting {next_file}")
|
||||||
next_file.delete_audio_file()
|
next_file.delete_audio_file()
|
||||||
loop.create_task(self.advance_music_data(guild))
|
loop.create_task(self.advance_music_data(guild))
|
||||||
|
|
||||||
log.info(f"Starting playback of {next_file.info.title}")
|
log.debug(f"Creating AudioSource of {next_file}")
|
||||||
voice_client.play(next_file.as_audio_source(), after=advance)
|
next_source = next_file.create_audio_source()
|
||||||
|
log.debug(f"Starting playback of {next_source}")
|
||||||
|
voice_client.play(next_source, after=advance)
|
||||||
|
|
||||||
async def nh_play(self, message: PlayMessage):
|
async def nh_play(self, message: PlayMessage):
|
||||||
"""Handle a play Royalnet request. That is, add audio to a PlayMode."""
|
"""Handle a play Royalnet request. That is, add audio to a PlayMode."""
|
||||||
|
|
Loading…
Reference in a new issue