diff --git a/redbot/cogs/audio/core/commands/audioset.py b/redbot/cogs/audio/core/commands/audioset.py index 691a1b2b5..fc45e2f31 100644 --- a/redbot/cogs/audio/core/commands/audioset.py +++ b/redbot/cogs/audio/core/commands/audioset.py @@ -1065,9 +1065,9 @@ class AudioSetCommands(MixinMeta, metaclass=CompositeMetaClass): "\n---" + _("Lavalink Settings") + "--- \n" - + _("Cog version: [{version}]\n") - + _("Red-Lavalink: [{lavalink_version}]\n") - + _("External server: [{use_external_lavalink}]\n") + + _("Cog version: [{version}]\n") + + _("Red-Lavalink: [{lavalink_version}]\n") + + _("External server: [{use_external_lavalink}]\n") ).format( version=__version__, lavalink_version=lavalink.__version__, @@ -1075,8 +1075,22 @@ class AudioSetCommands(MixinMeta, metaclass=CompositeMetaClass): if global_data["use_external_lavalink"] else _("Disabled"), ) + if not global_data["use_external_lavalink"] and self.player_manager.ll_build: + msg += _( + "Lavalink build: [{llbuild}]\n" + "Lavalink branch: [{llbranch}]\n" + "Release date: [{build_time}]\n" + "Lavaplayer version: [{lavaplayer}]\n" + "Java version: [{jvm}]\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, + ) if is_owner: - msg += _("Localtracks path: [{localpath}]\n").format(**global_data) + msg += _("Localtracks path: [{localpath}]\n").format(**global_data) await self.send_embed_msg(ctx, description=box(msg, lang="ini")) diff --git a/redbot/cogs/audio/manager.py b/redbot/cogs/audio/manager.py index 9c0cc09ab..ba02a4723 100644 --- a/redbot/cogs/audio/manager.py +++ b/redbot/cogs/audio/manager.py @@ -39,6 +39,11 @@ _RE_JAVA_VERSION_LINE: Final[Pattern] = re.compile( ) _RE_JAVA_SHORT_VERSION: Final[Pattern] = re.compile(r'version "(?P\d+)"') +LAVALINK_BRANCH_LINE: Final[Pattern] = re.compile(rb"Branch\s+(?P[\w\-\d_.]+)") +LAVALINK_JAVA_LINE: Final[Pattern] = re.compile(rb"JVM:\s+(?P\d+[.\d+]*)") +LAVALINK_LAVAPLAYER_LINE: Final[Pattern] = re.compile(rb"Lavaplayer\s+(?P\d+[.\d+]*)") +LAVALINK_BUILD_TIME_LINE: Final[Pattern] = re.compile(rb"Build time:\s+(?P\d+[.\d+]*)") + class ServerManager: @@ -47,6 +52,12 @@ class ServerManager: _up_to_date: ClassVar[Optional[bool]] = None _blacklisted_archs: List[str] = [] + _lavaplayer: ClassVar[Optional[str]] = None + _lavalink_build: ClassVar[Optional[int]] = None + _jvm: ClassVar[Optional[str]] = None + _lavalink_branch: ClassVar[Optional[str]] = None + _buildtime: ClassVar[Optional[str]] = None + def __init__(self) -> None: self.ready: asyncio.Event = asyncio.Event() @@ -54,6 +65,26 @@ class ServerManager: self._monitor_task: Optional[asyncio.Task] = None self._shutdown: bool = False + @property + def jvm(self) -> Optional[str]: + return self._jvm + + @property + def lavaplayer(self) -> Optional[str]: + return self._lavaplayer + + @property + def ll_build(self) -> Optional[int]: + return self._lavalink_build + + @property + def ll_branch(self) -> Optional[str]: + return self._lavalink_branch + + @property + def build_time(self) -> Optional[str]: + return self._buildtime + async def start(self) -> None: arch_name = platform.machine() if arch_name in self._blacklisted_archs: @@ -91,28 +122,26 @@ class ServerManager: self._monitor_task = asyncio.create_task(self._monitor()) - @classmethod - async def _get_jar_args(cls) -> List[str]: - (java_available, java_version) = await cls._has_java() + async def _get_jar_args(self) -> List[str]: + (java_available, java_version) = await self._has_java() 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)] - @classmethod - async def _has_java(cls) -> Tuple[bool, Optional[Tuple[int, int]]]: - if cls._java_available is not None: + 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 cls._java_available, cls._java_version + return self._java_available, self._java_version java_available = shutil.which("java") is not None if not java_available: - cls.java_available = False - cls.java_version = None + self.java_available = False + self.java_version = None else: - cls._java_version = version = await cls._get_java_version() - cls._java_available = (11, 0) <= version < (12, 0) - return cls._java_available, cls._java_version + self._java_version = version = await self._get_java_version() + self._java_available = (11, 0) <= version < (12, 0) + return self._java_available, self._java_version @staticmethod async def _get_java_version() -> Tuple[int, int]: @@ -195,8 +224,7 @@ class ServerManager: await self._proc.wait() self._shutdown = True - @staticmethod - async def _download_jar() -> None: + async def _download_jar(self) -> None: log.info("Downloading Lavalink.jar...") async with aiohttp.ClientSession() as session: async with session.get(LAVALINK_DOWNLOAD_URL) as response: @@ -239,13 +267,13 @@ class ServerManager: shutil.move(path, str(LAVALINK_JAR_FILE), copy_function=shutil.copyfile) log.info("Successfully downloaded Lavalink.jar (%s bytes written)", format(nbytes, ",")) + await self._is_up_to_date() - @classmethod - async def _is_up_to_date(cls): - if cls._up_to_date is True: + async def _is_up_to_date(self): + if self._up_to_date is True: # Return cached value if we've checked this before return True - args = await cls._get_jar_args() + args = await self._get_jar_args() args.append("--version") _proc = await asyncio.subprocess.create_subprocess_exec( # pylint:disable=no-member *args, @@ -254,15 +282,33 @@ class ServerManager: stderr=asyncio.subprocess.STDOUT, ) stdout = (await _proc.communicate())[0] - match = _RE_BUILD_LINE.search(stdout) - if not match: + if (build := _RE_BUILD_LINE.search(stdout)) is None: + # Output is unexpected, suspect corrupted jarfile + return False + if (branch := LAVALINK_BRANCH_LINE.search(stdout)) is None: + # Output is unexpected, suspect corrupted jarfile + return False + if (java := LAVALINK_JAVA_LINE.search(stdout)) is None: + # Output is unexpected, suspect corrupted jarfile + return False + if (lavaplayer := LAVALINK_LAVAPLAYER_LINE.search(stdout)) is None: + # Output is unexpected, suspect corrupted jarfile + return False + if (buildtime := LAVALINK_BUILD_TIME_LINE.search(stdout)) is None: # Output is unexpected, suspect corrupted jarfile return False - build = int(match["build"]) - cls._up_to_date = build >= JAR_BUILD - return cls._up_to_date - @classmethod - async def maybe_download_jar(cls): - if not (LAVALINK_JAR_FILE.exists() and await cls._is_up_to_date()): - await cls._download_jar() + build = int(build["build"]) + date = buildtime["build_time"].decode() + date = date.replace(".", "/") + self._lavalink_build = build + self._lavalink_branch = branch["branch"].decode() + self._jvm = java["jvm"].decode() + self._lavaplayer = lavaplayer["lavaplayer"].decode() + self._buildtime = date + self._up_to_date = build >= JAR_BUILD + return self._up_to_date + + async def maybe_download_jar(self): + if not (LAVALINK_JAR_FILE.exists() and await self._is_up_to_date()): + await self._download_jar()