mirror of
https://github.com/UiO-Gaming/ShiteMusicBot.git
synced 2026-11-06 14:24:30 +01:00
167 lines
5.9 KiB
Python
167 lines
5.9 KiB
Python
from .mixqueue import MixQueue
|
|
|
|
from abc import ABC, abstractmethod
|
|
from random import randrange
|
|
|
|
from lavalink import BasePlayer
|
|
from lavalink.AudioTrack import AudioTrack
|
|
from lavalink.Events import QueueEndEvent, TrackExceptionEvent, TrackEndEvent, TrackStartEvent, TrackStuckEvent
|
|
|
|
|
|
'''
|
|
|
|
Version of lavalink.py's DefaultPlayer with a custom queue(mixqueue).
|
|
|
|
'''
|
|
|
|
class MixPlayer(BasePlayer):
|
|
def __init__(self, lavalink, guild_id: int):
|
|
super().__init__(lavalink, guild_id)
|
|
|
|
self._user_data = {}
|
|
self.channel_id = None
|
|
|
|
self.paused = False
|
|
self.position = 0
|
|
self.position_timestamp = 0
|
|
self.volume = 100
|
|
|
|
self.queue = MixQueue()
|
|
self.current = None
|
|
|
|
@property
|
|
def is_playing(self):
|
|
""" Returns the player's track state. """
|
|
return self.connected_channel is not None and self.current is not None
|
|
|
|
@property
|
|
def is_connected(self):
|
|
""" Returns the player's connection state. """
|
|
return self.connected_channel is not None
|
|
|
|
@property
|
|
def connected_channel(self):
|
|
""" Returns the voice channel the player is connected to. """
|
|
if not self.channel_id:
|
|
return None
|
|
|
|
return self._lavalink.bot.get_channel(int(self.channel_id))
|
|
|
|
async def connect(self, channel_id: int):
|
|
""" Connects to a voice channel. """
|
|
ws = self._lavalink.bot._connection._get_websocket(int(self.guild_id))
|
|
await ws.voice_state(self.guild_id, str(channel_id))
|
|
|
|
async def disconnect(self):
|
|
""" Disconnects from the voice channel, if any. """
|
|
if not self.is_connected:
|
|
return
|
|
|
|
await self.stop()
|
|
|
|
ws = self._lavalink.bot._connection._get_websocket(int(self.guild_id))
|
|
await ws.voice_state(self.guild_id, None)
|
|
|
|
def store(self, key: object, value: object):
|
|
""" Stores custom user data. """
|
|
self._user_data.update({key: value})
|
|
|
|
def fetch(self, key: object, default=None):
|
|
""" Retrieves the related value from the stored user data. """
|
|
return self._user_data.get(key, default)
|
|
|
|
def delete(self, key: object):
|
|
""" Removes an item from the the stored user data. """
|
|
try:
|
|
del self._user_data[key]
|
|
except KeyError:
|
|
pass
|
|
|
|
def add(self, requester: int, track: dict):
|
|
""" Adds a track to the queue. """
|
|
self.queue.add_track(requester, AudioTrack().build(track, requester))
|
|
|
|
def add_next(self, requester: int, track: dict):
|
|
""" Adds a track to beginning of the queue """
|
|
self.queue.add_next_track(AudioTrack().build(track, requester))
|
|
|
|
def add_at(self, index: int, requester: int, track: dict):
|
|
""" Adds a track at a specific index in the queue. """
|
|
self.queue.add_track(requester, AudioTrack().build(track, requester), index)
|
|
|
|
def move_user_track(self, requester: int, initial: int, final: int):
|
|
""" Moves a track in a users queue"""
|
|
self.queue.move_user_track(requester, initial, final)
|
|
|
|
def remove_user_track(self, requester: int, pos: int):
|
|
""" Removes the song at <pos> from the queue of requester """
|
|
self.queue.remove_user_track(requester, pos)
|
|
|
|
def remove_global_track(self, pos: int):
|
|
""" Removes the song at <pos> in the global queue """
|
|
self.queue.remove_global_track(pos)
|
|
|
|
def shuffle_user_queue(self, requester: int):
|
|
""" Randomly reorders the queue of requester """
|
|
self.queue.shuffle_user_queue(requester)
|
|
|
|
async def play(self, track_index: int = 0):
|
|
""" Plays the first track in the queue, if any or plays a track from the specified index in the queue. """
|
|
|
|
self.current = None
|
|
self.position = 0
|
|
self.paused = False
|
|
|
|
if self.queue.is_empty():
|
|
await self.stop()
|
|
await self._lavalink.dispatch_event(QueueEndEvent(self))
|
|
else:
|
|
track = self.queue.pop_first()
|
|
|
|
self.current = track
|
|
await self._lavalink.ws.send(op='play', guildId=self.guild_id, track=track.track)
|
|
await self._lavalink.dispatch_event(TrackStartEvent(self, track))
|
|
|
|
async def play_now(self, requester: int, track: dict):
|
|
""" Add track and play it. """
|
|
self.add_next(requester, track)
|
|
await self.play()
|
|
|
|
async def skip_to(self, index: int):
|
|
""" Play the queue from a specific point. Disregards tracks before the index. """
|
|
for i in range(index):
|
|
_ = self.queue.pop_first()
|
|
await self.play()
|
|
|
|
async def stop(self):
|
|
""" Stops the player, if playing. """
|
|
await self._lavalink.ws.send(op='stop', guildId=self.guild_id)
|
|
self.current = None
|
|
|
|
async def skip(self):
|
|
""" Plays the next track in the queue, if any. """
|
|
await self.play()
|
|
|
|
async def set_pause(self, pause: bool):
|
|
""" Sets the player's paused state. """
|
|
await self._lavalink.ws.send(op='pause', guildId=self.guild_id, pause=pause)
|
|
self.paused = pause
|
|
|
|
async def set_volume(self, vol: int):
|
|
""" Sets the player's volume (150% or 1000% limit imposed by lavalink depending on the version). """
|
|
if self._lavalink._server_version <= 2:
|
|
self.volume = max(min(vol, 150), 0)
|
|
else:
|
|
self.volume = max(min(vol, 1000), 0)
|
|
await self._lavalink.ws.send(op='volume', guildId=self.guild_id, volume=self.volume)
|
|
|
|
async def seek(self, pos: int):
|
|
""" Seeks to a given position in the track. """
|
|
await self._lavalink.ws.send(op='seek', guildId=self.guild_id, position=pos)
|
|
|
|
async def handle_event(self, event):
|
|
""" Makes the player play the next song from the queue if a song has finished or an issue occurred. """
|
|
if isinstance(event, (TrackStuckEvent, TrackExceptionEvent)) or \
|
|
isinstance(event, TrackEndEvent) and event.reason == 'FINISHED':
|
|
await self.play()
|