From 449da2c463a947b19415d9c2271565ed4f504183 Mon Sep 17 00:00:00 2001 From: Drapersniper <27962761+drapersniper@users.noreply.github.com> Date: Tue, 6 Oct 2020 10:11:48 +0100 Subject: [PATCH] Add #3995 in here --- redbot/cogs/audio/core/__init__.py | 1 + redbot/cogs/audio/core/commands/audioset.py | 2 + redbot/cogs/audio/core/commands/llset.py | 68 +++++++++++++++++++++ redbot/cogs/audio/core/tasks/lavalink.py | 15 ++--- redbot/cogs/audio/manager.py | 36 +++++++---- 5 files changed, 103 insertions(+), 19 deletions(-) diff --git a/redbot/cogs/audio/core/__init__.py b/redbot/cogs/audio/core/__init__.py index 5f28e8d84..fbc215e50 100644 --- a/redbot/cogs/audio/core/__init__.py +++ b/redbot/cogs/audio/core/__init__.py @@ -94,6 +94,7 @@ class Audio( localpath=str(cog_data_path(raw_name="Audio")), url_keyword_blacklist=[], url_keyword_whitelist=[], + java_exc_path="java", **self._default_lavalink_settings, ) diff --git a/redbot/cogs/audio/core/commands/audioset.py b/redbot/cogs/audio/core/commands/audioset.py index e8e9a4b06..56f74a6ea 100644 --- a/redbot/cogs/audio/core/commands/audioset.py +++ b/redbot/cogs/audio/core/commands/audioset.py @@ -1111,12 +1111,14 @@ class AudioSetCommands(MixinMeta, metaclass=CompositeMetaClass): "Release date: [{build_time}]\n" "Lavaplayer version: [{lavaplayer}]\n" "Java version: [{jvm}]\n" + "Java Executable: [{jv_exec}]\n" ).format( build_time=self.player_manager.build_time, llbuild=self.player_manager.ll_build, llbranch=self.player_manager.ll_branch, lavaplayer=self.player_manager.lavaplayer, jvm=self.player_manager.jvm, + jv_exec=self.player_manager.path, ) if is_owner: msg += _("Localtracks path: [{localpath}]\n").format(**global_data) diff --git a/redbot/cogs/audio/core/commands/llset.py b/redbot/cogs/audio/core/commands/llset.py index 0eccecde2..16f579a18 100644 --- a/redbot/cogs/audio/core/commands/llset.py +++ b/redbot/cogs/audio/core/commands/llset.py @@ -1,4 +1,5 @@ import logging +from pathlib import Path import discord @@ -18,6 +19,73 @@ class LavalinkSetupCommands(MixinMeta, metaclass=CompositeMetaClass): async def command_llsetup(self, ctx: commands.Context): """Lavalink server configuration options.""" + @command_llsetup.command(name="java") + async def command_llsetup_java(self, ctx: commands.Context, *, java_path: str = None): + """Change your Java executable path + + Enter nothing to reset to default. + """ + external = await self.config.use_external_lavalink() + if external: + return await self.send_embed_msg( + ctx, + title=_("Invalid Environment"), + description=_( + "You cannot changed the Java executable path of " + "external Lavalink instances from the Audio Cog." + ), + ) + if java_path is None: + await self.config.java_exc_path.clear() + await self.send_embed_msg( + ctx, + title=_("Java Executable Reset"), + description=_("Audio will now use `java` to run your Lavalink.jar"), + ) + else: + exc = Path(java_path) + exc_absolute = exc.absolute() + if not exc.exists() or not exc.is_file(): + return await self.send_embed_msg( + ctx, + title=_("Invalid Environment"), + description=_("`{java_path}` is not a valid executable").format( + java_path=exc_absolute + ), + ) + await self.config.java_exc_path.set(exc_absolute) + await self.send_embed_msg( + ctx, + title=_("Java Executable Changed"), + description=_("Audio will now use `{exc}` to run your Lavalink.jar").format( + exc=exc_absolute + ), + ) + try: + if self.player_manager is not None: + await self.player_manager.shutdown() + except ProcessLookupError: + await self.send_embed_msg( + ctx, + title=_("Failed To Shutdown Lavalink"), + description=_( + "For it to take effect please reload " "Audio (`{prefix}reload audio`)." + ).format( + prefix=ctx.prefix, + ), + ) + else: + try: + self.lavalink_restart_connect() + except ProcessLookupError: + await self.send_embed_msg( + ctx, + title=_("Failed To Shutdown Lavalink"), + description=_("Please reload Audio (`{prefix}reload audio`).").format( + prefix=ctx.prefix + ), + ) + @command_llsetup.command(name="external") async def command_llsetup_external(self, ctx: commands.Context): """Toggle using external Lavalink servers.""" diff --git a/redbot/cogs/audio/core/tasks/lavalink.py b/redbot/cogs/audio/core/tasks/lavalink.py index 1be63aa89..05f970554 100644 --- a/redbot/cogs/audio/core/tasks/lavalink.py +++ b/redbot/cogs/audio/core/tasks/lavalink.py @@ -23,7 +23,9 @@ class LavalinkTasks(MixinMeta, metaclass=CompositeMetaClass): max_retries = 5 retry_count = 0 while retry_count < max_retries: - external = await self.config.use_external_lavalink() + configs = await self.config.all() + external = configs["use_external_lavalink"] + java_exec = configs["java_exc_path"] if external is False: settings = self._default_lavalink_settings host = settings["host"] @@ -34,7 +36,7 @@ class LavalinkTasks(MixinMeta, metaclass=CompositeMetaClass): await self.player_manager.shutdown() self.player_manager = ServerManager() try: - await self.player_manager.start() + await self.player_manager.start(java_exec) except LavalinkDownloadFailed as exc: await asyncio.sleep(1) if exc.should_retry: @@ -66,11 +68,10 @@ class LavalinkTasks(MixinMeta, metaclass=CompositeMetaClass): else: break else: - config_data = await self.config.all() - host = config_data["host"] - password = config_data["password"] - rest_port = config_data["rest_port"] - ws_port = config_data["ws_port"] + host = configs["host"] + password = configs["password"] + rest_port = configs["rest_port"] + ws_port = configs["ws_port"] break else: log.critical( diff --git a/redbot/cogs/audio/manager.py b/redbot/cogs/audio/manager.py index 5b8723988..e0cab4a63 100644 --- a/redbot/cogs/audio/manager.py +++ b/redbot/cogs/audio/manager.py @@ -13,7 +13,6 @@ import time from typing import ClassVar, Final, List, Optional, Pattern, Tuple -# Cog Dependencies import aiohttp from redbot.core import data_manager @@ -61,6 +60,7 @@ class ServerManager: _jvm: ClassVar[Optional[str]] = None _lavalink_branch: ClassVar[Optional[str]] = None _buildtime: ClassVar[Optional[str]] = None + _java_exc: ClassVar[str] = "java" def __init__(self) -> None: self.ready: asyncio.Event = asyncio.Event() @@ -69,6 +69,10 @@ class ServerManager: self._monitor_task: Optional[asyncio.Task] = None self._shutdown: bool = False + @property + def path(self) -> Optional[str]: + return self._java_exc + @property def jvm(self) -> Optional[str]: return self._jvm @@ -89,8 +93,9 @@ class ServerManager: def build_time(self) -> Optional[str]: return self._buildtime - async def start(self) -> None: + async def start(self, java_path: str) -> None: arch_name = platform.machine() + self._java_exc = java_path if arch_name in self._blacklisted_archs: raise asyncio.CancelledError( "You are attempting to run Lavalink audio on an unsupported machine architecture." @@ -133,27 +138,37 @@ class ServerManager: if not java_available: raise RuntimeError("You must install Java 11 for Lavalink to run.") - return ["java", "-Djdk.tls.client.protocols=TLSv1.2", "-jar", str(LAVALINK_JAR_FILE)] + return [ + self._java_exc, + "-Djdk.tls.client.protocols=TLSv1.2", + "-jar", + str(LAVALINK_JAR_FILE), + ] async def _has_java(self) -> Tuple[bool, Optional[Tuple[int, int]]]: if self._java_available is not None: # Return cached value if we've checked this before return self._java_available, self._java_version - java_available = shutil.which("java") is not None + java_exec = shutil.which(self._java_exc) + java_available = java_exec is not None if not java_available: self.java_available = False self.java_version = None + self._java_exc = "java" else: self._java_version = version = await self._get_java_version() self._java_available = (11, 0) <= version < (12, 0) + self._java_exc = java_exec return self._java_available, self._java_version - @staticmethod - async def _get_java_version() -> Tuple[int, int]: + async def _get_java_version(self) -> Tuple[int, int]: """This assumes we've already checked that java exists.""" _proc: asyncio.subprocess.Process = ( await asyncio.create_subprocess_exec( # pylint:disable=no-member - "java", "-version", stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE + self._java_exc, + "-version", + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, ) ) # java -version outputs to stderr @@ -176,10 +191,7 @@ class ServerManager: elif short_match: return int(short_match["major"]), 0 - raise RuntimeError( - "The output of `java -version` was unexpected. Please report this issue on Red's " - "issue tracker." - ) + raise RuntimeError(f"The output of `{self._java_exc} -version` was unexpected.") async def _wait_for_launcher(self) -> None: log.debug("Waiting for Lavalink server to be ready") @@ -207,7 +219,7 @@ class ServerManager: log.info("Internal Lavalink jar shutdown unexpectedly") if not self._has_java_error(): log.info("Restarting internal Lavalink server") - await self.start() + await self.start(self._java_exc) else: log.critical( "Your Java is borked. Please find the hs_err_pid%d.log file"