Source code for harmonize.queue
from __future__ import annotations
from random import shuffle
from typing import TYPE_CHECKING, Optional, overload, Iterator
from harmonize.enums import LoopStatus
from harmonize.objects import MISSING
if TYPE_CHECKING:
from harmonize.objects import Track
from harmonize import Player
__all__ = (
"Queue",
)
[docs]
class Queue:
"""
Represents a queue of tracks for a Discord voice player.
Operations
----------
.. describe:: len(x)
Returns the number of tracks in the queue.
.. describe:: x == y
Checks if two queues are the same.
.. describe:: x != y
Checks if two filters are not the same.
.. desribe:: x >= y
Checks if the first queue is greater or equal to the second queue.
.. describe:: x <= y
Checks if the first queue is less than or equal to the second queue.
.. describe:: x > y
Checks if the first queue is greater than the second queue.
.. describe:: x < y
Checks if the first queue is less than the second queue.
.. describe:: for y in x
Returns an iterator over the tracks in the queue.
.. describe:: x[key]
Returns the track at the specified index.
.. describe:: x in y
Checks if a track is in the queue.
.. describe:: bool(x)
Checks if the queue is empty.
.. describe:: hash(x)
Return the filter's hash.
.. describe:: str(x)
Returns a string representation of the queue.
Tip
---
The ``history`` and ``tracks`` attributes give the ORIGINAL OBJECT, you can change them at will
Attributes
----------
current : Optional[:class:`harmonize.objects.Track`]
The currently playing track in the queue.
tracks : list[:class:`harmonize.objects.Track`]
The list of tracks currently in the queue.
history : list[:class:`harmonize.objects.Track`]
The list of tracks that have been played in the queue.
loop : :class:`harmonize.enums.LoopStatus`
The loop status of the queue.
listened_count : int
The number of times a track has been played in the queue.
"""
def __init__(self, player: Player) -> None:
self._loop: LoopStatus = LoopStatus(0)
self._history: list[Track] = []
self._listened_count = 0
self._now: list[Track] = []
self._current: Optional[Track] = None
self._player: Player = player
@property
def current(self) -> Optional[Track]:
return self._current
@property
def history(self) -> list[Track]:
return self._history
@property
def tracks(self) -> list[Track]:
return self._now
@property
def listened_count(self) -> int:
return self._listened_count
@property
def loop(self) -> LoopStatus:
return self._loop
[docs]
def set_loop(self, value: LoopStatus, /) -> None:
"""
Sets the loop status of the queue.
Parameters
----------
value : :class:`harmonize.enums.LoopStatus`
The new loop status to set.
Raises
------
ValueError
If the provided value is not an instance of LoopStatus.
Returns
-------
None
"""
if not isinstance(value, LoopStatus):
raise ValueError("Invalid loop value. Please provide LoopStatus enum.")
self._loop = value
@overload
def add(self, track: Track) -> None:
...
@overload
def add(self, tracks: list[Track]) -> None:
...
[docs]
def add(self, **kwargs: Track | list[Track]) -> None:
"""
Adds a track or multiple tracks to the queue.
Parameters
----------
**kwargs : :class:`harmonize.objects.Track` | list[:class:`harmonize.objects.Track`]
'track' (:class:`harmonize.objects.Track`): A single track to add to the queue.
'tracks' (list[:class:`harmonize.objects.Track`]): A list of tracks to add to the queue.
Raises
------
ValueError: If neither 'track' nor 'tracks' is provided in kwargs.
Returns
-------
None
"""
if 'track' in kwargs:
self._now.append(kwargs.pop("track"))
elif 'tracks' in kwargs:
self._now.extend(kwargs.pop("tracks"))
else:
raise ValueError("Invalid arguments. Please provide track or tracks.")
[docs]
def clear(self) -> None:
"""
Clears the queue by removing all tracks from the current and history lists.
Returns
-------
None
"""
self._now.clear()
self._history.clear()
[docs]
def shuffle(self) -> None:
"""
Shuffles the current queue in-place.
Returns
-------
None
"""
shuffle(self._now)
[docs]
def reverse(self) -> None:
"""
Reverses the current queue in-place.
Returns
-------
None
"""
self._now.reverse()
async def _go_to_next(self, track: Optional[Track] = MISSING) -> Optional[Track]:
self._listened_count += 1
old = self._current
if self.loop.value > 0 and self._current:
match self.loop:
case LoopStatus.TRACK:
if track is MISSING:
track = self._current
case LoopStatus.QUEUE:
self._now.append(self._current)
if track is MISSING:
if not self._now:
await self._player.stop()
return self._player.dispatch('queue_end', self._player)
track = self._now.pop(0)
if old:
self._history.insert(0, old)
self._current = track
return track
def __repr__(self) -> str:
return (
f'<harmonize.Queue '
f'tracks={len(self._now)}, '
f'history={len(self._history)}, '
f'current={self._current.title}, '
f'loop={self._loop.value}>'
)
def __len__(self) -> int:
return len(self._now)
def __getitem__(self, index: int) -> Track:
return self._now[index]
def __iter__(self) -> Iterator[Track]:
return iter(self._now)
def __contains__(self, track: Track) -> bool:
return track in self._now
def __eq__(self, other: object) -> bool:
if isinstance(other, Queue):
return self._now == other._now
return False
def __bool__(self) -> bool:
return bool(self._now)
def __ne__(self, other: object) -> bool:
return not self.__eq__(other)
def __hash__(self) -> int:
return hash(self._now)
def __str__(self) -> str:
return str(self._now)
def __le__(self, other: int | Queue) -> bool:
if isinstance(other, Queue):
return len(self) <= len(other)
return self.__lt__(other) or len(self) == other
def __lt__(self, other: int | Queue) -> bool:
if isinstance(other, Queue):
return len(self) < len(other)
return len(self) < other
def __ge__(self, other: int | Queue) -> bool:
if isinstance(other, Queue):
return len(self) >= len(other)
return self.__gt__(other) or len(self) == other
def __gt__(self, other: int | Queue) -> bool:
if isinstance(other, Queue):
return len(self) > len(other)
return len(self) > other