edit filters, log level matches handler, other fixes
This commit is contained in:
parent
cbb676e004
commit
02d22f20b5
|
|
@ -20,7 +20,7 @@ if not discord.version_info.major >= 2:
|
|||
"using 'pip install discord.py'",
|
||||
)
|
||||
|
||||
__version__ = "2.6.1a"
|
||||
__version__ = "2.7.0a"
|
||||
__title__ = "pomice"
|
||||
__author__ = "cloudwithax"
|
||||
__license__ = "GPL-3.0"
|
||||
|
|
|
|||
|
|
@ -77,6 +77,12 @@ class Equalizer(Filter):
|
|||
def __repr__(self) -> str:
|
||||
return f"<Pomice.EqualizerFilter tag={self.tag} eq={self.eq} raw={self.raw}>"
|
||||
|
||||
def __eq__(self, __value: object) -> bool:
|
||||
if not isinstance(__value, Equalizer):
|
||||
return False
|
||||
|
||||
return self.raw == __value.raw
|
||||
|
||||
@classmethod
|
||||
def flat(cls) -> "Equalizer":
|
||||
"""Equalizer preset which represents a flat EQ board,
|
||||
|
|
@ -231,6 +237,16 @@ class Timescale(Filter):
|
|||
def __repr__(self) -> str:
|
||||
return f"<Pomice.TimescaleFilter tag={self.tag} speed={self.speed} pitch={self.pitch} rate={self.rate}>"
|
||||
|
||||
def __eq__(self, __value: object) -> bool:
|
||||
if not isinstance(__value, Timescale):
|
||||
return False
|
||||
|
||||
return (
|
||||
self.speed == __value.speed
|
||||
and self.pitch == __value.pitch
|
||||
and self.rate == __value.rate
|
||||
)
|
||||
|
||||
|
||||
class Karaoke(Filter):
|
||||
"""Filter which filters the vocal track from any song and leaves the instrumental.
|
||||
|
|
@ -270,6 +286,17 @@ class Karaoke(Filter):
|
|||
f"filter_band={self.filter_band} filter_width={self.filter_width}>"
|
||||
)
|
||||
|
||||
def __eq__(self, __value: object) -> bool:
|
||||
if not isinstance(__value, Karaoke):
|
||||
return False
|
||||
|
||||
return (
|
||||
self.level == __value.level
|
||||
and self.mono_level == __value.mono_level
|
||||
and self.filter_band == __value.filter_band
|
||||
and self.filter_width == __value.filter_width
|
||||
)
|
||||
|
||||
|
||||
class Tremolo(Filter):
|
||||
"""Filter which produces a wavering tone in the music,
|
||||
|
|
@ -305,6 +332,12 @@ class Tremolo(Filter):
|
|||
f"<Pomice.TremoloFilter tag={self.tag} frequency={self.frequency} depth={self.depth}>"
|
||||
)
|
||||
|
||||
def __eq__(self, __value: object) -> bool:
|
||||
if not isinstance(__value, Tremolo):
|
||||
return False
|
||||
|
||||
return self.frequency == __value.frequency and self.depth == __value.depth
|
||||
|
||||
|
||||
class Vibrato(Filter):
|
||||
"""Filter which produces a wavering tone in the music, similar to the Tremolo filter,
|
||||
|
|
@ -340,6 +373,12 @@ class Vibrato(Filter):
|
|||
f"<Pomice.VibratoFilter tag={self.tag} frequency={self.frequency} depth={self.depth}>"
|
||||
)
|
||||
|
||||
def __eq__(self, __value: object) -> bool:
|
||||
if not isinstance(__value, Vibrato):
|
||||
return False
|
||||
|
||||
return self.frequency == __value.frequency and self.depth == __value.depth
|
||||
|
||||
|
||||
class Rotation(Filter):
|
||||
"""Filter which produces a stereo-like panning effect, which sounds like
|
||||
|
|
@ -357,6 +396,12 @@ class Rotation(Filter):
|
|||
def __repr__(self) -> str:
|
||||
return f"<Pomice.RotationFilter tag={self.tag} rotation_hertz={self.rotation_hertz}>"
|
||||
|
||||
def __eq__(self, __value: object) -> bool:
|
||||
if not isinstance(__value, Rotation):
|
||||
return False
|
||||
|
||||
return self.rotation_hertz == __value.rotation_hertz
|
||||
|
||||
|
||||
class ChannelMix(Filter):
|
||||
"""Filter which manually adjusts the panning of the audio, which can make
|
||||
|
|
@ -418,6 +463,17 @@ class ChannelMix(Filter):
|
|||
f"right_to_left={self.right_to_left} right_to_right={self.right_to_right}>"
|
||||
)
|
||||
|
||||
def __eq__(self, __value: object) -> bool:
|
||||
if not isinstance(__value, ChannelMix):
|
||||
return False
|
||||
|
||||
return (
|
||||
self.left_to_left == __value.left_to_left
|
||||
and self.left_to_right == __value.left_to_right
|
||||
and self.right_to_left == __value.right_to_left
|
||||
and self.right_to_right == __value.right_to_right
|
||||
)
|
||||
|
||||
|
||||
class Distortion(Filter):
|
||||
"""Filter which generates a distortion effect. Useful for certain filter implementations where
|
||||
|
|
@ -479,6 +535,21 @@ class Distortion(Filter):
|
|||
f"tan_scale={self.tan_scale} offset={self.offset} scale={self.scale}"
|
||||
)
|
||||
|
||||
def __eq__(self, __value: object) -> bool:
|
||||
if not isinstance(__value, Distortion):
|
||||
return False
|
||||
|
||||
return (
|
||||
self.sin_offset == __value.sin_offset
|
||||
and self.sin_scale == __value.sin_scale
|
||||
and self.cos_offset == __value.cos_offset
|
||||
and self.cos_scale == __value.cos_scale
|
||||
and self.tan_offset == __value.tan_offset
|
||||
and self.tan_scale == __value.tan_scale
|
||||
and self.offset == __value.offset
|
||||
and self.scale == __value.scale
|
||||
)
|
||||
|
||||
|
||||
class LowPass(Filter):
|
||||
"""Filter which supresses higher frequencies and allows lower frequencies to pass.
|
||||
|
|
@ -495,3 +566,9 @@ class LowPass(Filter):
|
|||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Pomice.LowPass tag={self.tag} smoothing={self.smoothing}>"
|
||||
|
||||
def __eq__(self, __value: object) -> bool:
|
||||
if not isinstance(__value, LowPass):
|
||||
return False
|
||||
|
||||
return self.smoothing == __value.smoothing
|
||||
|
|
|
|||
|
|
@ -79,6 +79,27 @@ class Filters:
|
|||
if filter.tag == filter_tag:
|
||||
del self._filters[index]
|
||||
|
||||
def edit_filter(self, *, filter_tag: str, to_apply: Filter) -> None:
|
||||
"""Edits a filter in the list of filters applied using its filter tag and replaces it with the new filter."""
|
||||
if not any(f for f in self._filters if f.tag == filter_tag):
|
||||
raise FilterTagInvalid("A filter with that tag was not found.")
|
||||
|
||||
for index, filter in enumerate(self._filters):
|
||||
if filter.tag == filter_tag:
|
||||
if not type(filter) == type(to_apply):
|
||||
raise FilterInvalidArgument(
|
||||
"Edited filter is not the same type as the current filter.",
|
||||
)
|
||||
if self._filters[index] == to_apply:
|
||||
raise FilterInvalidArgument("Edited filter is the same as the current filter.")
|
||||
|
||||
if to_apply.tag != filter_tag:
|
||||
raise FilterInvalidArgument(
|
||||
"Edited filter tag is not the same as the current filter tag.",
|
||||
)
|
||||
|
||||
self._filters[index] = to_apply
|
||||
|
||||
def has_filter(self, *, filter_tag: str) -> bool:
|
||||
"""Checks if a filter exists in the list of filters using its filter tag"""
|
||||
return any(f for f in self._filters if f.tag == filter_tag)
|
||||
|
|
@ -382,6 +403,16 @@ class Player(VoiceProtocol):
|
|||
"""
|
||||
return await self._node.get_tracks(query, ctx=ctx, search_type=search_type, filters=filters)
|
||||
|
||||
async def build_track(self, identifier: str, ctx: Optional[commands.Context] = None) -> Track:
|
||||
"""
|
||||
Builds a track using a valid track identifier
|
||||
|
||||
You can also pass in a discord.py Context object to get a
|
||||
Context object on the track it builds.
|
||||
"""
|
||||
|
||||
return await self._node.build_track(identifier, ctx=ctx)
|
||||
|
||||
async def get_recommendations(
|
||||
self, *, track: Track, ctx: Optional[commands.Context] = None
|
||||
) -> Optional[Union[List[Track], Playlist]]:
|
||||
|
|
@ -431,7 +462,7 @@ class Player(VoiceProtocol):
|
|||
except AttributeError:
|
||||
# 'NoneType' has no attribute '_get_voice_client_key' raised by self.cleanup() ->
|
||||
# assume we're already disconnected and cleaned up
|
||||
assert not self.is_connected and not self.channel
|
||||
assert self.channel is None and not self.is_connected
|
||||
|
||||
self._node._players.pop(self.guild.id)
|
||||
if self.node.is_connected:
|
||||
|
|
@ -637,6 +668,33 @@ class Player(VoiceProtocol):
|
|||
|
||||
return self._filters
|
||||
|
||||
async def edit_filter(
|
||||
self, *, filter_tag: str, edited_filter: Filter, fast_apply: bool = False
|
||||
) -> Filters:
|
||||
"""Edits a filter from the player using its filter tag and a new filter of the same type.
|
||||
The filter to be replaced must have the same tag as the one you are replacing it with.
|
||||
This will only work if you are using a version of Lavalink that supports filters.
|
||||
|
||||
If you would like for the filter to apply instantly, set the `fast_apply` arg to `True`.
|
||||
|
||||
(You must have a song playing in order for `fast_apply` to work.)
|
||||
"""
|
||||
|
||||
self._filters.edit_filter(filter_tag=filter_tag, to_apply=edited_filter)
|
||||
payload = self._filters.get_all_payloads()
|
||||
await self._node.send(
|
||||
method="PATCH",
|
||||
path=self._player_endpoint_uri,
|
||||
guild_id=self._guild.id,
|
||||
data={"filters": payload},
|
||||
)
|
||||
self._log.debug(f"Filter with tag {filter_tag} has been edited to {edited_filter!r}")
|
||||
if fast_apply:
|
||||
self._log.debug(f"Fast apply passed, now editing filter instantly.")
|
||||
await self.seek(self.position)
|
||||
|
||||
return self._filters
|
||||
|
||||
async def reset_filters(self, *, fast_apply: bool = False) -> None:
|
||||
"""Resets all currently applied filters to their default parameters.
|
||||
You must have filters applied in order for this to work.
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class Node:
|
|||
password: str,
|
||||
identifier: str,
|
||||
secure: bool = False,
|
||||
heartbeat: int = 60,
|
||||
heartbeat: int = 120,
|
||||
resume_key: Optional[str] = None,
|
||||
resume_timeout: int = 60,
|
||||
loop: Optional[asyncio.AbstractEventLoop] = None,
|
||||
|
|
@ -234,13 +234,15 @@ class Node:
|
|||
|
||||
def _setup_logging(self, level: LogLevel) -> logging.Logger:
|
||||
logger = logging.getLogger("pomice")
|
||||
logger.setLevel(level)
|
||||
|
||||
handler = None
|
||||
|
||||
if self._log_handler:
|
||||
handler = self._log_handler
|
||||
logger.setLevel(handler.level)
|
||||
else:
|
||||
handler = logging.StreamHandler()
|
||||
logger.setLevel(level)
|
||||
dt_fmt = "%Y-%m-%d %H:%M:%S"
|
||||
formatter = logging.Formatter(
|
||||
"[{asctime}] [{levelname:<8}] {name}: {message}",
|
||||
|
|
@ -960,7 +962,7 @@ class NodePool:
|
|||
password: str,
|
||||
identifier: str,
|
||||
secure: bool = False,
|
||||
heartbeat: int = 30,
|
||||
heartbeat: int = 120,
|
||||
resume_key: Optional[str] = None,
|
||||
resume_timeout: int = 60,
|
||||
loop: Optional[asyncio.AbstractEventLoop] = None,
|
||||
|
|
|
|||
Loading…
Reference in New Issue