add logging and fix other things
This commit is contained in:
parent
c2b952438a
commit
52a45afd70
|
|
@ -174,7 +174,7 @@ class RouteIPType(Enum):
|
||||||
|
|
||||||
class URLRegex:
|
class URLRegex:
|
||||||
"""
|
"""
|
||||||
The enums for all the URL Regexes in use by Pomice.
|
The enum for all the URL Regexes in use by Pomice.
|
||||||
|
|
||||||
URLRegex.SPOTIFY_URL returns the Spotify URL Regex.
|
URLRegex.SPOTIFY_URL returns the Spotify URL Regex.
|
||||||
|
|
||||||
|
|
@ -245,3 +245,33 @@ class URLRegex:
|
||||||
LAVALINK_SEARCH = re.compile(r"(?P<type>ytm?|sc)search:")
|
LAVALINK_SEARCH = re.compile(r"(?P<type>ytm?|sc)search:")
|
||||||
|
|
||||||
BASE_URL = re.compile(r"https?://(?:www\.)?.+")
|
BASE_URL = re.compile(r"https?://(?:www\.)?.+")
|
||||||
|
|
||||||
|
|
||||||
|
class LogLevel(Enum):
|
||||||
|
"""
|
||||||
|
The enum for specifying the logging level within Pomice.
|
||||||
|
This class serves as shorthand for logging.<level>
|
||||||
|
This enum is exclusively for the logging feature in Pomice.
|
||||||
|
If you are not using this feature, this class is not necessary.
|
||||||
|
|
||||||
|
|
||||||
|
LogLevel.DEBUG sets the logging level to "debug".
|
||||||
|
|
||||||
|
LogLevel.INFO sets the logging level to "info".
|
||||||
|
|
||||||
|
LogLevel.WARN sets the logging level to "warn".
|
||||||
|
|
||||||
|
LogLevel.ERROR sets the logging level to "error".
|
||||||
|
|
||||||
|
LogLevel.CRITICAL sets the logging level to "CRITICAL".
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
DEBUG = 10
|
||||||
|
INFO = 20
|
||||||
|
WARN = 30
|
||||||
|
ERROR = 40
|
||||||
|
CRITICAL = 50
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.value
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ from .objects import Playlist
|
||||||
from .objects import Track
|
from .objects import Track
|
||||||
from .pool import Node
|
from .pool import Node
|
||||||
from .pool import NodePool
|
from .pool import NodePool
|
||||||
|
from pomice.utils import LavalinkVersion
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from discord.types.voice import VoiceServerUpdate
|
from discord.types.voice import VoiceServerUpdate
|
||||||
|
|
@ -158,6 +159,7 @@ class Player(VoiceProtocol):
|
||||||
self._last_position: int = 0
|
self._last_position: int = 0
|
||||||
self._last_update: float = 0
|
self._last_update: float = 0
|
||||||
self._ending_track: Optional[Track] = None
|
self._ending_track: Optional[Track] = None
|
||||||
|
self._log = self._node._log
|
||||||
|
|
||||||
self._voice_state: dict = {}
|
self._voice_state: dict = {}
|
||||||
|
|
||||||
|
|
@ -260,13 +262,9 @@ class Player(VoiceProtocol):
|
||||||
return self.guild.id not in self._node._players
|
return self.guild.id not in self._node._players
|
||||||
|
|
||||||
def _adjust_end_time(self):
|
def _adjust_end_time(self):
|
||||||
version = self._node._version
|
if self._node._version >= LavalinkVersion(3, 7, 5):
|
||||||
if version.major == 4:
|
|
||||||
return None
|
return None
|
||||||
if version.major == 3:
|
|
||||||
if version.minor == 7 and version.fix == 5:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
return "0"
|
return "0"
|
||||||
|
|
||||||
async def _update_state(self, data: dict) -> None:
|
async def _update_state(self, data: dict) -> None:
|
||||||
|
|
@ -274,6 +272,7 @@ class Player(VoiceProtocol):
|
||||||
self._last_update = int(state.get("time", 0))
|
self._last_update = int(state.get("time", 0))
|
||||||
self._is_connected = bool(state.get("connected"))
|
self._is_connected = bool(state.get("connected"))
|
||||||
self._last_position = int(state.get("position", 0))
|
self._last_position = int(state.get("position", 0))
|
||||||
|
self._log.debug(f"Got player update state with data {state}")
|
||||||
|
|
||||||
async def _dispatch_voice_update(self, voice_data: Optional[Dict[str, Any]] = None) -> None:
|
async def _dispatch_voice_update(self, voice_data: Optional[Dict[str, Any]] = None) -> None:
|
||||||
if {"sessionId", "event"} != self._voice_state.keys():
|
if {"sessionId", "event"} != self._voice_state.keys():
|
||||||
|
|
@ -294,6 +293,8 @@ class Player(VoiceProtocol):
|
||||||
data={"voice": data},
|
data={"voice": data},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._log.debug(f"Dispatched voice update to {state['event']['endpoint']} with data {data}")
|
||||||
|
|
||||||
async def on_voice_server_update(self, data: VoiceServerUpdate) -> None:
|
async def on_voice_server_update(self, data: VoiceServerUpdate) -> None:
|
||||||
self._voice_state.update({"event": data})
|
self._voice_state.update({"event": data})
|
||||||
await self._dispatch_voice_update(self._voice_state)
|
await self._dispatch_voice_update(self._voice_state)
|
||||||
|
|
@ -330,6 +331,8 @@ class Player(VoiceProtocol):
|
||||||
if isinstance(event, TrackStartEvent):
|
if isinstance(event, TrackStartEvent):
|
||||||
self._ending_track = self._current
|
self._ending_track = self._current
|
||||||
|
|
||||||
|
self._log.debug(f"Dispatched event {data['type']} to player.")
|
||||||
|
|
||||||
async def _swap_node(self, *, new_node: Node) -> None:
|
async def _swap_node(self, *, new_node: Node) -> None:
|
||||||
if self.current:
|
if self.current:
|
||||||
data: dict = {"position": self.position, "encodedTrack": self.current.track_id}
|
data: dict = {"position": self.position, "encodedTrack": self.current.track_id}
|
||||||
|
|
@ -348,6 +351,8 @@ class Player(VoiceProtocol):
|
||||||
data=data,
|
data=data,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._log.debug(f"Swapped all players to new node {new_node._identifier}.")
|
||||||
|
|
||||||
async def get_tracks(
|
async def get_tracks(
|
||||||
self,
|
self,
|
||||||
query: str,
|
query: str,
|
||||||
|
|
@ -401,6 +406,8 @@ class Player(VoiceProtocol):
|
||||||
data={"encodedTrack": None},
|
data={"encodedTrack": None},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._log.debug(f"Player has been stopped.")
|
||||||
|
|
||||||
async def disconnect(self, *, force: bool = False) -> None:
|
async def disconnect(self, *, force: bool = False) -> None:
|
||||||
"""Disconnects the player from voice."""
|
"""Disconnects the player from voice."""
|
||||||
try:
|
try:
|
||||||
|
|
@ -426,14 +433,13 @@ class Player(VoiceProtocol):
|
||||||
guild_id=self._guild.id,
|
guild_id=self._guild.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._log.debug("Player has been destroyed.")
|
||||||
|
|
||||||
async def play(
|
async def play(
|
||||||
self, track: Track, *, start: int = 0, end: int = 0, ignore_if_playing: bool = False
|
self, track: Track, *, start: int = 0, end: int = 0, ignore_if_playing: bool = False
|
||||||
) -> Track:
|
) -> Track:
|
||||||
"""Plays a track. If a Spotify track is passed in, it will be handled accordingly."""
|
"""Plays a track. If a Spotify track is passed in, it will be handled accordingly."""
|
||||||
|
|
||||||
end_time = self._adjust_end_time()
|
|
||||||
print(f"got end time of {end_time}")
|
|
||||||
|
|
||||||
# Make sure we've never searched the track before
|
# Make sure we've never searched the track before
|
||||||
if track.original is None:
|
if track.original is None:
|
||||||
# First lets try using the tracks ISRC, every track has one (hopefully)
|
# First lets try using the tracks ISRC, every track has one (hopefully)
|
||||||
|
|
@ -465,7 +471,7 @@ class Player(VoiceProtocol):
|
||||||
data = {
|
data = {
|
||||||
"encodedTrack": search.track_id,
|
"encodedTrack": search.track_id,
|
||||||
"position": str(start),
|
"position": str(start),
|
||||||
"endTime": end_time,
|
"endTime": self._adjust_end_time(),
|
||||||
}
|
}
|
||||||
track.original = search
|
track.original = search
|
||||||
track.track_id = search.track_id
|
track.track_id = search.track_id
|
||||||
|
|
@ -474,7 +480,7 @@ class Player(VoiceProtocol):
|
||||||
data = {
|
data = {
|
||||||
"encodedTrack": track.track_id,
|
"encodedTrack": track.track_id,
|
||||||
"position": str(start),
|
"position": str(start),
|
||||||
"endTime": end_time,
|
"endTime": self._adjust_end_time(),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Lets set the current track before we play it so any
|
# Lets set the current track before we play it so any
|
||||||
|
|
@ -515,6 +521,10 @@ class Player(VoiceProtocol):
|
||||||
query=f"noReplace={ignore_if_playing}",
|
query=f"noReplace={ignore_if_playing}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._log.debug(
|
||||||
|
f"Playing {track.title} from uri {track.uri} with a length of {track.length}",
|
||||||
|
)
|
||||||
|
|
||||||
return self._current
|
return self._current
|
||||||
|
|
||||||
async def seek(self, position: float) -> float:
|
async def seek(self, position: float) -> float:
|
||||||
|
|
@ -533,6 +543,8 @@ class Player(VoiceProtocol):
|
||||||
guild_id=self._guild.id,
|
guild_id=self._guild.id,
|
||||||
data={"position": position},
|
data={"position": position},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._log.debug(f"Seeking to {position}.")
|
||||||
return self.position
|
return self.position
|
||||||
|
|
||||||
async def set_pause(self, pause: bool) -> bool:
|
async def set_pause(self, pause: bool) -> bool:
|
||||||
|
|
@ -544,6 +556,8 @@ class Player(VoiceProtocol):
|
||||||
data={"paused": pause},
|
data={"paused": pause},
|
||||||
)
|
)
|
||||||
self._paused = pause
|
self._paused = pause
|
||||||
|
|
||||||
|
self._log.debug(f"Player has been {'paused' if pause else 'resumed'}.")
|
||||||
return self._paused
|
return self._paused
|
||||||
|
|
||||||
async def set_volume(self, volume: int) -> int:
|
async def set_volume(self, volume: int) -> int:
|
||||||
|
|
@ -555,6 +569,8 @@ class Player(VoiceProtocol):
|
||||||
data={"volume": volume},
|
data={"volume": volume},
|
||||||
)
|
)
|
||||||
self._volume = volume
|
self._volume = volume
|
||||||
|
|
||||||
|
self._log.debug(f"Player volume has been adjusted to {volume}")
|
||||||
return self._volume
|
return self._volume
|
||||||
|
|
||||||
async def add_filter(self, _filter: Filter, fast_apply: bool = False) -> Filters:
|
async def add_filter(self, _filter: Filter, fast_apply: bool = False) -> Filters:
|
||||||
|
|
@ -573,7 +589,10 @@ class Player(VoiceProtocol):
|
||||||
guild_id=self._guild.id,
|
guild_id=self._guild.id,
|
||||||
data={"filters": payload},
|
data={"filters": payload},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._log.debug(f"Filter has been applied to player with tag {_filter.tag}")
|
||||||
if fast_apply:
|
if fast_apply:
|
||||||
|
self._log.debug(f"Fast apply passed, now applying filter instantly.")
|
||||||
await self.seek(self.position)
|
await self.seek(self.position)
|
||||||
|
|
||||||
return self._filters
|
return self._filters
|
||||||
|
|
@ -594,7 +613,9 @@ class Player(VoiceProtocol):
|
||||||
guild_id=self._guild.id,
|
guild_id=self._guild.id,
|
||||||
data={"filters": payload},
|
data={"filters": payload},
|
||||||
)
|
)
|
||||||
|
self._log.debug(f"Filter has been removed from player with tag {filter_tag}")
|
||||||
if fast_apply:
|
if fast_apply:
|
||||||
|
self._log.debug(f"Fast apply passed, now removing filter instantly.")
|
||||||
await self.seek(self.position)
|
await self.seek(self.position)
|
||||||
|
|
||||||
return self._filters
|
return self._filters
|
||||||
|
|
@ -618,6 +639,8 @@ class Player(VoiceProtocol):
|
||||||
guild_id=self._guild.id,
|
guild_id=self._guild.id,
|
||||||
data={"filters": {}},
|
data={"filters": {}},
|
||||||
)
|
)
|
||||||
|
self._log.debug(f"All filters have been removed from player.")
|
||||||
|
|
||||||
if fast_apply:
|
if fast_apply:
|
||||||
|
self._log.debug(f"Fast apply passed, now removing all filters instantly.")
|
||||||
await self.seek(self.position)
|
await self.seek(self.position)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import logging
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
|
import time
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
@ -20,6 +22,7 @@ from . import __version__
|
||||||
from . import applemusic
|
from . import applemusic
|
||||||
from . import spotify
|
from . import spotify
|
||||||
from .enums import *
|
from .enums import *
|
||||||
|
from .enums import LogLevel
|
||||||
from .exceptions import AppleMusicNotEnabled
|
from .exceptions import AppleMusicNotEnabled
|
||||||
from .exceptions import InvalidSpotifyClientAuthorization
|
from .exceptions import InvalidSpotifyClientAuthorization
|
||||||
from .exceptions import LavalinkVersionIncompatible
|
from .exceptions import LavalinkVersionIncompatible
|
||||||
|
|
@ -102,6 +105,7 @@ class Node:
|
||||||
spotify_client_secret: Optional[str] = None,
|
spotify_client_secret: Optional[str] = None,
|
||||||
apple_music: bool = False,
|
apple_music: bool = False,
|
||||||
fallback: bool = False,
|
fallback: bool = False,
|
||||||
|
log_level: LogLevel = LogLevel.INFO,
|
||||||
):
|
):
|
||||||
self._bot: commands.Bot = bot
|
self._bot: commands.Bot = bot
|
||||||
self._host: str = host
|
self._host: str = host
|
||||||
|
|
@ -112,6 +116,7 @@ class Node:
|
||||||
self._heartbeat: int = heartbeat
|
self._heartbeat: int = heartbeat
|
||||||
self._secure: bool = secure
|
self._secure: bool = secure
|
||||||
self._fallback: bool = fallback
|
self._fallback: bool = fallback
|
||||||
|
self._log_level: LogLevel = log_level
|
||||||
|
|
||||||
self._websocket_uri: str = f"{'wss' if self._secure else 'ws'}://{self._host}:{self._port}"
|
self._websocket_uri: str = f"{'wss' if self._secure else 'ws'}://{self._host}:{self._port}"
|
||||||
self._rest_uri: str = f"{'https' if self._secure else 'http'}://{self._host}:{self._port}"
|
self._rest_uri: str = f"{'https' if self._secure else 'http'}://{self._host}:{self._port}"
|
||||||
|
|
@ -126,6 +131,7 @@ class Node:
|
||||||
self._version: LavalinkVersion = None
|
self._version: LavalinkVersion = None
|
||||||
|
|
||||||
self._route_planner = RoutePlanner(self)
|
self._route_planner = RoutePlanner(self)
|
||||||
|
self._log = self._setup_logging(self._log_level)
|
||||||
|
|
||||||
if not self._bot.user:
|
if not self._bot.user:
|
||||||
raise NodeCreationError("Bot user is not ready yet.")
|
raise NodeCreationError("Bot user is not ready yet.")
|
||||||
|
|
@ -202,6 +208,20 @@ class Node:
|
||||||
"""Alias for `Node.latency`, returns the latency of the node"""
|
"""Alias for `Node.latency`, returns the latency of the node"""
|
||||||
return self.latency
|
return self.latency
|
||||||
|
|
||||||
|
def _setup_logging(self, level: LogLevel) -> logging.Logger:
|
||||||
|
logger = logging.getLogger()
|
||||||
|
handler = logging.StreamHandler()
|
||||||
|
dt_fmt = "%Y-%m-%d %H:%M:%S"
|
||||||
|
formatter = logging.Formatter(
|
||||||
|
"[{asctime}] [{levelname:<8}] {name}: {message}",
|
||||||
|
dt_fmt,
|
||||||
|
style="{",
|
||||||
|
)
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
logger.setLevel(level)
|
||||||
|
logger.addHandler(handler)
|
||||||
|
return logger
|
||||||
|
|
||||||
async def _handle_version_check(self, version: str):
|
async def _handle_version_check(self, version: str):
|
||||||
if version.endswith("-SNAPSHOT"):
|
if version.endswith("-SNAPSHOT"):
|
||||||
# we're just gonna assume all snapshot versions correlate with v4
|
# we're just gonna assume all snapshot versions correlate with v4
|
||||||
|
|
@ -328,6 +348,7 @@ class Node:
|
||||||
headers=self._headers,
|
headers=self._headers,
|
||||||
json=data or {},
|
json=data or {},
|
||||||
) as resp:
|
) as resp:
|
||||||
|
self._log.debug(f"Making REST request with method {method} to {uri}")
|
||||||
if resp.status >= 300:
|
if resp.status >= 300:
|
||||||
resp_data: dict = await resp.json()
|
resp_data: dict = await resp.json()
|
||||||
raise NodeRestException(
|
raise NodeRestException(
|
||||||
|
|
@ -335,11 +356,20 @@ class Node:
|
||||||
)
|
)
|
||||||
|
|
||||||
if method == "DELETE" or resp.status == 204:
|
if method == "DELETE" or resp.status == 204:
|
||||||
|
self._log.debug(
|
||||||
|
f"REST request with method {method} to {uri} completed sucessfully and returned no data.",
|
||||||
|
)
|
||||||
return await resp.json(content_type=None)
|
return await resp.json(content_type=None)
|
||||||
|
|
||||||
if resp.content_type == "text/plain":
|
if resp.content_type == "text/plain":
|
||||||
|
self._log.debug(
|
||||||
|
f"REST request with method {method} to {uri} completed sucessfully and returned text with body {await resp.text()}",
|
||||||
|
)
|
||||||
return await resp.text()
|
return await resp.text()
|
||||||
|
|
||||||
|
self._log.debug(
|
||||||
|
f"REST request with method {method} to {uri} completed sucessfully and returned JSON with body {await resp.json()}",
|
||||||
|
)
|
||||||
return await resp.json()
|
return await resp.json()
|
||||||
|
|
||||||
def get_player(self, guild_id: int) -> Optional[Player]:
|
def get_player(self, guild_id: int) -> Optional[Player]:
|
||||||
|
|
@ -350,6 +380,8 @@ class Node:
|
||||||
"""Initiates a connection with a Lavalink node and adds it to the node pool."""
|
"""Initiates a connection with a Lavalink node and adds it to the node pool."""
|
||||||
await self._bot.wait_until_ready()
|
await self._bot.wait_until_ready()
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
if not self._session:
|
if not self._session:
|
||||||
self._session = aiohttp.ClientSession()
|
self._session = aiohttp.ClientSession()
|
||||||
|
|
||||||
|
|
@ -363,16 +395,26 @@ class Node:
|
||||||
|
|
||||||
await self._handle_version_check(version=version)
|
await self._handle_version_check(version=version)
|
||||||
|
|
||||||
|
self._log.debug(f"Version check from node successful. Returned version {version}")
|
||||||
|
|
||||||
self._websocket = await self._session.ws_connect(
|
self._websocket = await self._session.ws_connect(
|
||||||
f"{self._websocket_uri}/v{self._version.major}/websocket",
|
f"{self._websocket_uri}/v{self._version.major}/websocket",
|
||||||
headers=self._headers,
|
headers=self._headers,
|
||||||
heartbeat=self._heartbeat,
|
heartbeat=self._heartbeat,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._log.debug(
|
||||||
|
f"Connected to node websocket using {self._websocket_uri}/v{self._version.major}/websocket",
|
||||||
|
)
|
||||||
|
|
||||||
if not self._task:
|
if not self._task:
|
||||||
self._task = self._loop.create_task(self._listen())
|
self._task = self._loop.create_task(self._listen())
|
||||||
|
|
||||||
self._available = True
|
self._available = True
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
|
||||||
|
self._log.info(f"Connected to node {self._identifier}. Took {end - start:.3f}s")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
except (aiohttp.ClientConnectorError, ConnectionRefusedError):
|
except (aiohttp.ClientConnectorError, ConnectionRefusedError):
|
||||||
|
|
@ -392,21 +434,34 @@ class Node:
|
||||||
"""Disconnects a connected Lavalink node and removes it from the node pool.
|
"""Disconnects a connected Lavalink node and removes it from the node pool.
|
||||||
This also destroys any players connected to the node.
|
This also destroys any players connected to the node.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
|
||||||
for player in self.players.copy().values():
|
for player in self.players.copy().values():
|
||||||
await player.destroy()
|
await player.destroy()
|
||||||
|
self._log.debug("All players disconnected from node.")
|
||||||
|
|
||||||
await self._websocket.close()
|
await self._websocket.close()
|
||||||
await self._session.close()
|
await self._session.close()
|
||||||
|
self._log.debug("Websocket and http session closed.")
|
||||||
|
|
||||||
if self._spotify_client:
|
if self._spotify_client:
|
||||||
await self._spotify_client.close()
|
await self._spotify_client.close()
|
||||||
|
self._log.debug("Spotify client session closed.")
|
||||||
|
|
||||||
if self._apple_music_client:
|
if self._apple_music_client:
|
||||||
await self._apple_music_client.close()
|
await self._apple_music_client.close()
|
||||||
|
self._log.debug("Apple Music client session closed.")
|
||||||
|
|
||||||
del self._pool._nodes[self._identifier]
|
del self._pool._nodes[self._identifier]
|
||||||
self.available = False
|
self.available = False
|
||||||
self._task.cancel()
|
self._task.cancel()
|
||||||
|
|
||||||
|
end = time.perf_counter()
|
||||||
|
self._log.info(
|
||||||
|
f"Successfully disconnected from node {self._identifier} and closed all sessions. Took {end - start:.3f}s",
|
||||||
|
)
|
||||||
|
|
||||||
async def build_track(self, identifier: str, ctx: Optional[commands.Context] = None) -> Track:
|
async def build_track(self, identifier: str, ctx: Optional[commands.Context] = None) -> Track:
|
||||||
"""
|
"""
|
||||||
Builds a track using a valid track identifier
|
Builds a track using a valid track identifier
|
||||||
|
|
|
||||||
|
|
@ -231,3 +231,47 @@ class LavalinkVersion(NamedTuple):
|
||||||
major: int
|
major: int
|
||||||
minor: int
|
minor: int
|
||||||
fix: int
|
fix: int
|
||||||
|
|
||||||
|
def __eq__(self, other: object) -> bool:
|
||||||
|
if not isinstance(other, LavalinkVersion):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return (
|
||||||
|
(self.major == other.major) and (self.minor == other.minor) and (self.fix == other.fix)
|
||||||
|
)
|
||||||
|
|
||||||
|
def __ne__(self, other: object) -> bool:
|
||||||
|
if not isinstance(other, LavalinkVersion):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return not (self == other)
|
||||||
|
|
||||||
|
def __lt__(self, other: object) -> bool:
|
||||||
|
if not isinstance(other, LavalinkVersion):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if self.major > other.major:
|
||||||
|
return False
|
||||||
|
if self.minor > other.minor:
|
||||||
|
return False
|
||||||
|
if self.fix > other.fix:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __gt__(self, other: object) -> bool:
|
||||||
|
if not isinstance(other, LavalinkVersion):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return not (self < other)
|
||||||
|
|
||||||
|
def __le__(self, other: object) -> bool:
|
||||||
|
if not isinstance(other, LavalinkVersion):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return (self < other) or (self == other)
|
||||||
|
|
||||||
|
def __ge__(self, other: object) -> bool:
|
||||||
|
if not isinstance(other, LavalinkVersion):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return (self > other) or (self == other)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue