[V3 Audio] Update audio to use Red-Lavalink (#1440)

* [V3 Audio] Update audio for Red-Lavalink

* Update requirements for new library

* Fix logic for connect time storage for audiostats

Only store time when connecting to the voice channel.
This commit is contained in:
aikaterna 2018-03-20 15:28:31 -07:00 committed by Kowlin
parent f83e3cc3e7
commit 2e9a0de4a1
3 changed files with 306 additions and 285 deletions

View File

@ -1,5 +1,3 @@
# Lavalink.py cog for Red v3 beta 7+
# Cog base thanks to Kromatic's example cog.
import asyncio import asyncio
import datetime import datetime
import discord import discord
@ -11,7 +9,7 @@ from redbot.core import Config, checks
from .manager import shutdown_lavalink_server from .manager import shutdown_lavalink_server
__version__ = "2.0.2.9.b" __version__ = "0.0.3a"
__author__ = ["aikaterna", "billy/bollo/ati"] __author__ = ["aikaterna", "billy/bollo/ati"]
@ -22,8 +20,9 @@ class Audio:
default_global = { default_global = {
"host": 'localhost', "host": 'localhost',
"port": '2332', "rest_port": '2333',
"passw": 'youshallnotpass', "ws_port": '2332',
"password": 'youshallnotpass',
"status": False, "status": False,
"current_build": 0 "current_build": 0
} }
@ -38,80 +37,75 @@ class Audio:
self.config.register_guild(**default_guild) self.config.register_guild(**default_guild)
self.config.register_global(**default_global) self.config.register_global(**default_global)
self._lavalink = None
async def init_config(self): async def init_config(self):
host = await self.config.host() host = await self.config.host()
passw = await self.config.passw() password = await self.config.password()
port = await self.config.port() rest_port = await self.config.rest_port()
ws_port = await self.config.ws_port()
try: await lavalink.initialize(
self._lavalink = lavalink.Client( bot=self.bot, host=host, password=password, rest_port=rest_port, ws_port=ws_port
bot=self.bot, password=passw, host=host, port=port, loop=self.bot.loop
) )
except RuntimeError: lavalink.register_event_listener(self.event_handler)
pass
self.bot.lavalink.client.register_hook(self.track_hook) async def event_handler(self, player, event_type, extra):
notify = await self.config.guild(player.channel.guild).notify()
@property
def lavalink(self):
return self._lavalink
async def track_hook(self, player, event):
notify = await self.config.guild(self.bot.get_guild(player.fetch('guild'))).notify()
status = await self.config.status() status = await self.config.status()
playing_servers = await self._get_playing()
get_players = [p for p in self.bot.lavalink.players._players.values() if p.is_playing]
try: try:
get_players = [p for p in lavalink.players if p.current is not None]
get_single_title = get_players[0].current.title get_single_title = get_players[0].current.title
playing_servers = len(get_players)
except IndexError: except IndexError:
pass playing_servers = 0
if event == 'TrackStartEvent': if event_type == lavalink.LavalinkEvents.TRACK_START:
playing_song = player.fetch('playing_song') playing_song = player.fetch('playing_song')
requester = player.fetch('requester') requester = player.fetch('requester')
player.store('prev_song', playing_song) player.store('prev_song', playing_song)
player.store('prev_requester', requester) player.store('prev_requester', requester)
player.store('playing_song', self.bot.lavalink.players.get(player.fetch('guild')).current.uri) player.store('playing_song', player.current.uri)
player.store('requester', self.bot.get_user(self.bot.lavalink.players.get(player.fetch('guild')).current.requester)) player.store('requester', player.current.requester)
if event == 'TrackStartEvent' and notify: if event_type == lavalink.LavalinkEvents.TRACK_START and notify:
c = player.fetch('channel') notify_channel = player.fetch('channel')
if c: if notify_channel:
c = self.bot.get_channel(c) notify_channel = self.bot.get_channel(notify_channel)
if player.fetch('notify_message') is not None: if player.fetch('notify_message') is not None:
try: try:
await player.fetch('notify_message').delete() await player.fetch('notify_message').delete()
except discord.errors.NotFound: except discord.errors.NotFound:
pass pass
embed = discord.Embed(colour=c.guild.me.top_role.colour, title='Now Playing', embed = discord.Embed(colour=notify_channel.guild.me.top_role.colour, title='Now Playing',
description='**[{}]({})**'.format(player.current.title, player.current.uri)) description='**[{}]({})**'.format(player.current.title, player.current.uri))
notify_message = await c.send(embed=embed) notify_message = await notify_channel.send(embed=embed)
player.store('notify_message', notify_message) player.store('notify_message', notify_message)
if event == 'TrackStartEvent' and status: if event_type == lavalink.LavalinkEvents.TRACK_START and status:
if playing_servers > 1:
await self.bot.change_presence(activity=discord.Activity(name='music in {} servers'.format(playing_servers), type=discord.ActivityType.playing))
else:
await self.bot.change_presence(activity=discord.Activity(name=get_single_title, type=discord.ActivityType.listening))
if event == 'QueueEndEvent' and notify:
c = player.fetch('channel')
if c:
c = self.bot.get_channel(c)
if c:
embed = discord.Embed(colour=c.guild.me.top_role.colour, title='Queue ended.')
await c.send(embed=embed)
if event == 'QueueEndEvent' and status:
await asyncio.sleep(1)
if playing_servers == 0: if playing_servers == 0:
await self.bot.change_presence(activity=None) await self.bot.change_presence(activity=None)
if playing_servers == 1: if playing_servers == 1:
await self.bot.change_presence(activity=discord.Activity(name=get_single_title, type=discord.ActivityType.listening)) await self.bot.change_presence(activity=discord.Activity(name=get_single_title,
type=discord.ActivityType.listening))
if playing_servers > 1: if playing_servers > 1:
await self.bot.change_presence(activity=discord.Activity(name='music in {} servers'.format(playing_servers), type=discord.ActivityType.playing)) await self.bot.change_presence(activity=discord.Activity(name='music in {} servers'.format(playing_servers),
type=discord.ActivityType.playing))
if event_type == lavalink.LavalinkEvents.QUEUE_END and notify:
notify_channel = player.fetch('channel')
if notify_channel:
notify_channel = self.bot.get_channel(notify_channel)
embed = discord.Embed(colour=notify_channel.guild.me.top_role.colour, title='Queue ended.')
await notify_channel.send(embed=embed)
if event_type == lavalink.LavalinkEvents.QUEUE_END and status:
if playing_servers == 0:
await self.bot.change_presence(activity=None)
if playing_servers == 1:
await self.bot.change_presence(activity=discord.Activity(name=get_single_title,
type=discord.ActivityType.listening))
if playing_servers > 1:
await self.bot.change_presence(activity=discord.Activity(name='music in {} servers'.format(playing_servers),
type=discord.ActivityType.playing))
@commands.group() @commands.group()
@checks.is_owner() @checks.is_owner()
@ -143,8 +137,7 @@ class Audio:
msg += 'Repeat: [{}]\n'.format(repeat) msg += 'Repeat: [{}]\n'.format(repeat)
msg += 'Shuffle: [{}]\n'.format(shuffle) msg += 'Shuffle: [{}]\n'.format(shuffle)
msg += '---Lavalink Settings---\n' msg += '---Lavalink Settings---\n'
msg += 'Cog version: {}\n'.format(__version__) msg += 'Cog version: {}\n```'.format(__version__)
msg += 'Pip version: {}\n```'.format(lavalink.__version__)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, description=msg) embed = discord.Embed(colour=ctx.guild.me.top_role.colour, description=msg)
return await ctx.send(embed=embed) return await ctx.send(embed=embed)
@ -156,48 +149,43 @@ class Audio:
status = await self.config.status() status = await self.config.status()
await self.config.status.set(not status) await self.config.status.set(not status)
get_status = await self.config.status() get_status = await self.config.status()
await self._embed_msg(ctx, 'Song titles as status: {}'.format(get_status)) await self._embed_msg(ctx, 'Song titles as status: {}.'.format(get_status))
@commands.command() @commands.command()
async def audiostats(self, ctx): async def audiostats(self, ctx):
"""Audio stats.""" """Audio stats."""
server_num = await self._get_playing() server_num = len([p for p in lavalink.players if p.current is not None])
server_ids = self.bot.lavalink.players._players
server_list = [] server_list = []
for k, v in server_ids.items(): for p in lavalink.players:
guild_id = k connect_start = p.fetch('connect')
player = v
connect_start = v.fetch('connect')
try:
connect_dur = self._dynamic_time(int((datetime.datetime.utcnow() - connect_start).total_seconds())) connect_dur = self._dynamic_time(int((datetime.datetime.utcnow() - connect_start).total_seconds()))
except TypeError:
connect_dur = 0
try: try:
server_list.append('{} [`{}`]: **[{}]({})**'.format(self.bot.get_guild(guild_id).name, connect_dur, server_list.append('{} [`{}`]: **[{}]({})**'.format(p.channel.guild.name, connect_dur,
v.current.title, v.current.uri)) p.current.title, p.current.uri))
except AttributeError: except AttributeError:
pass server_list.append('{} [`{}`]: **{}**'.format(p.channel.guild.name, connect_dur,
servers = '\n'.join(server_list) 'Nothing playing.'))
if server_list == []: if server_num == 0:
servers = 'Not connected anywhere.' servers = 'Not connected anywhere.'
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Playing in {} servers:'.format(server_num), else:
servers = '\n'.join(server_list)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Connected in {} servers:'.format(server_num),
description=servers) description=servers)
await ctx.send(embed=embed) await ctx.send(embed=embed)
@commands.command() @commands.command()
async def bump(self, ctx, index: int): async def bump(self, ctx, index: int):
"""Bump a song number to the top of the queue.""" """Bump a song number to the top of the queue."""
player = self.bot.lavalink.players.get(ctx.guild.id) if not self._player_check(ctx):
return await self._embed_msg(ctx, 'Nothing playing.')
if not player.queue:
return await self._embed_msg(ctx, 'Nothing queued.')
player = lavalink.get_player(ctx.guild.id)
if index > len(player.queue) or index < 1: if index > len(player.queue) or index < 1:
return await self._embed_msg(ctx, 'Song number must be greater than 1 and within the queue limit.') return await self._embed_msg(ctx, 'Song number must be greater than 1 and within the queue limit.')
bump_index = index - 1 bump_index = index - 1
bump_song = self.bot.lavalink.players.get(ctx.guild.id).queue[bump_index] bump_song = player.queue[bump_index]
player.queue.insert(0, bump_song) player.queue.insert(0, bump_song)
removed = player.queue.pop(index) removed = player.queue.pop(index)
await self._embed_msg(ctx, 'Moved **' + removed.title + '** to the top of the queue.') await self._embed_msg(ctx, 'Moved **' + removed.title + '** to the top of the queue.')
@ -205,40 +193,38 @@ class Audio:
@commands.command(aliases=['dc']) @commands.command(aliases=['dc'])
async def disconnect(self, ctx): async def disconnect(self, ctx):
"""Disconnect from the voice channel.""" """Disconnect from the voice channel."""
player = self.bot.lavalink.players.get(ctx.guild.id) if self._player_check(ctx):
await player.disconnect() await lavalink.get_player(ctx.guild.id).stop()
player.queue.clear() await lavalink.get_player(ctx.guild.id).disconnect()
player.store('connect', None)
player.store('prev_requester', None)
player.store('prev_song', None)
player.store('playing_song', None)
player.store('requester', None)
await self.bot.lavalink.client._trigger_event("QueueEndEvent", ctx.guild.id)
@commands.command(aliases=['np', 'n', 'song']) @commands.command(aliases=['np', 'n', 'song'])
async def now(self, ctx): async def now(self, ctx):
"""Now playing.""" """Now playing."""
expected = ['', '', ''] if not self._player_check(ctx):
return await self._embed_msg(ctx, 'Nothing playing.')
expected = ['', '', '', '']
emoji = { emoji = {
'prev': '',
'stop': '', 'stop': '',
'pause': '', 'pause': '',
'next': '' 'next': ''
} }
player = self.bot.lavalink.players.get(ctx.guild.id) player = lavalink.get_player(ctx.guild.id)
song = 'Nothing' song = 'Nothing'
if player.current: if player.current:
arrow = await self._draw_time(ctx) arrow = await self._draw_time(ctx)
pos = lavalink.Utils.format_time(player.position) pos = lavalink.utils.format_time(player.position)
if player.current.stream: if player.current.is_stream:
dur = 'LIVE' dur = 'LIVE'
else: else:
dur = lavalink.Utils.format_time(player.current.duration) dur = lavalink.utils.format_time(player.current.length)
if not player.current: song = '**[{}]({})**\nRequested by: **{}**\n\n{}`{}`/`{}`'.format(
song = 'Nothing.' player.current.title, player.current.uri,
player.current.requester, arrow, pos, dur
)
else: else:
req_user = self.bot.get_user(player.current.requester) song = 'Nothing.'
song = '**[{}]({})**\nRequested by: **{}**\n\n{}`{}`/`{}`'.format(player.current.title, player.current.uri,
req_user, arrow, pos, dur)
if player.fetch('np_message') is not None: if player.fetch('np_message') is not None:
try: try:
await player.fetch('np_message').delete() await player.fetch('np_message').delete()
@ -253,7 +239,7 @@ class Audio:
return r.message.id == message.id and u == ctx.message.author return r.message.id == message.id and u == ctx.message.author
if player.current: if player.current:
for i in range(3): for i in range(4):
await message.add_reaction(expected[i]) await message.add_reaction(expected[i])
try: try:
(r, u) = await self.bot.wait_for('reaction_add', check=check, timeout=10.0) (r, u) = await self.bot.wait_for('reaction_add', check=check, timeout=10.0)
@ -263,7 +249,10 @@ class Audio:
reacts = {v: k for k, v in emoji.items()} reacts = {v: k for k, v in emoji.items()}
react = reacts[r.emoji] react = reacts[r.emoji]
if react == 'stop': if react == 'prev':
await self._clear_react(message)
await ctx.invoke(self.prev)
elif react == 'stop':
await self._clear_react(message) await self._clear_react(message)
await ctx.invoke(self.stop) await ctx.invoke(self.stop)
elif react == 'pause': elif react == 'pause':
@ -276,28 +265,44 @@ class Audio:
@commands.command(aliases=['resume']) @commands.command(aliases=['resume'])
async def pause(self, ctx): async def pause(self, ctx):
"""Pause and resume.""" """Pause and resume."""
player = self.bot.lavalink.players.get(ctx.guild.id) if not self._player_check(ctx):
if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)): return await self._embed_msg(ctx, 'Nothing playing.')
player = lavalink.get_player(ctx.guild.id)
if not ctx.author.voice or ctx.author.voice.channel != player.channel:
return await self._embed_msg(ctx, 'You must be in the voice channel to pause the music.') return await self._embed_msg(ctx, 'You must be in the voice channel to pause the music.')
if not player.is_playing: if player.current and not player.paused:
return await player.pause()
embed = discord.Embed(
colour=ctx.guild.me.top_role.colour, title='Track Paused',
description='**[{}]({})**'.format(
player.current.title,
player.current.uri
)
)
return await ctx.send(embed=embed)
if player.paused: if player.paused:
await player.set_pause(False) await player.pause(False)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Track Resumed', embed = discord.Embed(
description='**[{}]({})**'.format(player.current.title, player.current.uri)) colour=ctx.guild.me.top_role.colour,
message = await ctx.send(embed=embed) title='Track Resumed',
else: description='**[{}]({})**'.format(
await player.set_pause(True) player.current.title,
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Track Paused', player.current.uri
description='**[{}]({})**'.format(player.current.title, player.current.uri)) )
message = await ctx.send(embed=embed) )
return await ctx.send(embed=embed)
await self._embed_msg(ctx, 'Nothing playing.')
@commands.command() @commands.command()
async def percent(self, ctx): async def percent(self, ctx):
"""Queue percentage.""" """Queue percentage."""
queue_tracks = self.bot.lavalink.players.get(ctx.guild.id).queue if not self._player_check(ctx):
return await self._embed_msg(ctx, 'Nothing playing.')
player = lavalink.get_player(ctx.guild.id)
queue_tracks = player.queue
queue_len = len(queue_tracks) queue_len = len(queue_tracks)
requesters = {'total': 0, 'users': {}} requesters = {'total': 0, 'users': {}}
@ -310,11 +315,12 @@ class Audio:
requesters['users'][req_username]['songcount'] = 1 requesters['users'][req_username]['songcount'] = 1
requesters['total'] += 1 requesters['total'] += 1
for i in range(queue_len): for track in queue_tracks:
req_username = self.bot.get_user(queue_tracks[i].requester).name req_username = '{}#{}'.format(track.requester.name, track.requester.discriminator)
await _usercount(req_username) await _usercount(req_username)
try: try:
req_username = self.bot.get_user(self.bot.lavalink.players.get(ctx.guild.id).current.requester).name req_username = '{}#{}'.format(player.current.requester.name, player.current.requester.discriminator)
await _usercount(req_username) await _usercount(req_username)
except AttributeError: except AttributeError:
return await self._embed_msg(ctx, 'Nothing in the queue.') return await self._embed_msg(ctx, 'Nothing in the queue.')
@ -334,91 +340,89 @@ class Audio:
@commands.command(aliases=['p']) @commands.command(aliases=['p'])
async def play(self, ctx, *, query): async def play(self, ctx, *, query):
"""Play a URL or search for a song.""" """Play a URL or search for a song."""
player = self.bot.lavalink.players.get(ctx.guild.id) if not ctx.author.voice:
shuffle = await self.config.guild(ctx.guild).shuffle()
if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)):
return await self._embed_msg(ctx, 'You must be in the voice channel to use the play command.') return await self._embed_msg(ctx, 'You must be in the voice channel to use the play command.')
if not self._player_check(ctx):
await lavalink.connect(ctx.author.voice.channel)
player = lavalink.get_player(ctx.guild.id)
player.store('connect', datetime.datetime.utcnow())
player = lavalink.get_player(ctx.guild.id)
shuffle = await self.config.guild(ctx.guild).shuffle()
player.store('channel', ctx.channel.id) player.store('channel', ctx.channel.id)
player.store('guild', ctx.guild.id) player.store('guild', ctx.guild.id)
await self._data_check(ctx) await self._data_check(ctx)
if not player.is_connected:
player.store('connect', datetime.datetime.utcnow())
await player.connect(ctx.author.voice.channel.id)
query = query.strip('<>') query = query.strip('<>')
if not query.startswith('http'): if not query.startswith('http'):
query = 'ytsearch:{}'.format(query) query = 'ytsearch:{}'.format(query)
tracks = await self.bot.lavalink.client.get_tracks(query) tracks = await player.get_tracks(query)
if not tracks: if not tracks:
return await self._embed_msg(ctx, 'Nothing found 👀') return await self._embed_msg(ctx, 'Nothing found.')
queue_duration = await self._queue_duration(ctx) queue_duration = await self._queue_duration(ctx)
queue_total_duration = lavalink.Utils.format_time(queue_duration) queue_total_duration = lavalink.utils.format_time(queue_duration)
if 'list' in query and 'ytsearch:' not in query: if 'list' in query and 'ytsearch:' not in query:
for track in tracks: for track in tracks:
player.add(requester=ctx.author.id, track=track) player.add(ctx.author, track)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Playlist Enqueued', embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Playlist Enqueued',
description='Added {} tracks to the queue.'.format(len(tracks))) description='Added {} tracks to the queue.'.format(len(tracks)))
if not shuffle and queue_duration > 0: if not shuffle and queue_duration > 0:
embed.set_footer(text='{} until start of playlist playback'.format(queue_total_duration)) embed.set_footer(text='{} until start of playlist playback'.format(queue_total_duration))
if not player.current:
await player.play()
else: else:
player.add(requester=ctx.author.id, track=tracks[0]) single_track = tracks[0]
track_title = tracks[0]["info"]["title"] player.add(ctx.author, single_track)
track_url = tracks[0]["info"]["uri"]
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Track Enqueued', embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Track Enqueued',
description='[**{}**]({})'.format(track_title, track_url)) description='**[{}]({})**'.format(single_track.title, single_track.uri))
if not shuffle and queue_duration > 0: if not shuffle and queue_duration > 0:
embed.set_footer(text='{} until track playback'.format(queue_total_duration)) embed.set_footer(text='{} until track playback'.format(queue_total_duration))
await ctx.send(embed=embed) if not player.current:
if not player.is_playing:
await player.play() await player.play()
await ctx.send(embed=embed)
@commands.command() @commands.command()
async def prev(self, ctx): async def prev(self, ctx):
"""Skips to the start of the previously played track.""" """Skips to the start of the previously played track."""
player = self.bot.lavalink.players.get(ctx.guild.id) if not self._player_check(ctx):
return await self._embed_msg(ctx, 'Nothing playing.')
player = lavalink.get_player(ctx.guild.id)
shuffle = await self.config.guild(ctx.guild).shuffle() shuffle = await self.config.guild(ctx.guild).shuffle()
if not ctx.author.voice or ctx.author.voice.channel != player.channel:
if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)):
return await self._embed_msg(ctx, 'You must be in the voice channel to skip the music.') return await self._embed_msg(ctx, 'You must be in the voice channel to skip the music.')
if shuffle: if shuffle:
return await self._embed_msg(ctx, 'Turn shuffle off to use this command.') return await self._embed_msg(ctx, 'Turn shuffle off to use this command.')
if player.current is None:
return await self._embed_msg(ctx, 'The player is stopped.')
if player.fetch('prev_song') is None: if player.fetch('prev_song') is None:
return await self._embed_msg(ctx, 'No previous track.') return await self._embed_msg(ctx, 'No previous track.')
else: else:
last_track = await self.bot.lavalink.client.get_tracks(player.fetch('prev_song')) last_track = await player.get_tracks(player.fetch('prev_song'))
player.add(player.fetch('prev_requester').id, last_track[0]) player.add(player.fetch('prev_requester').id, last_track[0])
queue_len = len(self.bot.lavalink.players.get(ctx.guild.id).queue) queue_len = len(player.queue)
bump_song = self.bot.lavalink.players.get(ctx.guild.id).queue[queue_len - 1] bump_song = player.queue[-1]
player.queue.insert(0, bump_song) player.queue.insert(0, bump_song)
player.queue.pop(queue_len) player.queue.pop(queue_len)
await player.skip() await player.skip()
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Replaying Track', description='**[{}]({})**'.format(player.current.title, player.current.uri)) embed = discord.Embed(
colour=ctx.guild.me.top_role.colour,
title='Replaying Track', description='**[{}]({})**'.format(
player.current.title, player.current.uri
)
)
await ctx.send(embed=embed) await ctx.send(embed=embed)
@commands.command(aliases=['q']) @commands.command(aliases=['q'])
async def queue(self, ctx, page: int = 1): async def queue(self, ctx, page: int=1):
"""Lists the queue.""" """Lists the queue."""
if not self._player_check(ctx):
return await self._embed_msg(ctx, 'There\'s nothing in the queue.')
shuffle = await self.config.guild(ctx.guild).shuffle() shuffle = await self.config.guild(ctx.guild).shuffle()
repeat = await self.config.guild(ctx.guild).repeat() repeat = await self.config.guild(ctx.guild).repeat()
player = self.bot.lavalink.players.get(ctx.guild.id) player = lavalink.get_player(ctx.guild.id)
if not player.queue: if not player.queue:
return await self._embed_msg(ctx, 'There\'s nothing in the queue.') return await self._embed_msg(ctx, 'There\'s nothing in the queue.')
if player.current is None:
return await self._embed_msg(ctx, 'The player is stopped.')
items_per_page = 10 items_per_page = 10
pages = math.ceil(len(player.queue) / items_per_page) pages = math.ceil(len(player.queue) / items_per_page)
start = (page - 1) * items_per_page start = (page - 1) * items_per_page
@ -426,34 +430,39 @@ class Audio:
queue_list = '' queue_list = ''
arrow = await self._draw_time(ctx) arrow = await self._draw_time(ctx)
pos = lavalink.Utils.format_time(player.position) pos = lavalink.utils.format_time(player.position)
if player.current.stream: if player.current.is_stream:
dur = 'LIVE' dur = 'LIVE'
else: else:
dur = lavalink.Utils.format_time(player.current.duration) dur = lavalink.utils.format_time(player.current.length)
if player.current.stream: if player.current.is_stream:
queue_list += '**Currently livestreaming:** [**{}**]({})\nRequested by: **{}**\n\n{}`{}`/`{}`\n\n'.format( queue_list += '**Currently livestreaming:** **[{}]({})**\nRequested by: **{}**\n\n{}`{}`/`{}`\n\n'.format(
player.current.title, player.current.uri, self.bot.get_user(player.current.requester), arrow, pos, dur) player.current.title,
else:
queue_list += 'Playing: [**{}**]({})\nRequested by: **{}**\n\n{}`{}`/`{}`\n\n'.format(player.current.title,
player.current.uri, player.current.uri,
self.bot.get_user( player.current.requester,
player.current.requester), arrow, pos, dur
arrow, pos, dur) )
else:
queue_list += 'Playing: **[{}]({})**\nRequested by: **{}**\n\n{}`{}`/`{}`\n\n'.format(
player.current.title,
player.current.uri,
player.current.requester,
arrow, pos, dur
)
for i, track in enumerate(player.queue[start:end], start=start): for i, track in enumerate(player.queue[start:end], start=start):
req_user = self.bot.get_user(track.requester) req_user = track.requester
next = i + 1 next = i + 1
queue_list += '`{}.` [**{}**]({}), requested by **{}**\n'.format(next, track.title, track.uri, req_user) queue_list += '`{}.` **[{}]({})**, requested by **{}**\n'.format(next, track.title, track.uri, req_user)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Queue for ' + ctx.guild.name, embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Queue for ' + ctx.guild.name,
description=queue_list) description=queue_list)
queue_duration = await self._queue_duration(ctx) queue_duration = await self._queue_duration(ctx)
queue_total_duration = lavalink.Utils.format_time(queue_duration) queue_total_duration = lavalink.utils.format_time(queue_duration)
text = 'Page {}/{} | {} tracks, {} remaining'.format(page, pages, len(player.queue), queue_total_duration) text = 'Page {}/{} | {} tracks, {} remaining'.format(page, pages, len(player.queue) + 1, queue_total_duration)
if repeat: if repeat:
text += ' | Repeat: \N{WHITE HEAVY CHECK MARK}' text += ' | Repeat: \N{WHITE HEAVY CHECK MARK}'
if shuffle: if shuffle:
@ -464,31 +473,33 @@ class Audio:
@commands.command() @commands.command()
async def repeat(self, ctx): async def repeat(self, ctx):
"""Toggles repeat.""" """Toggles repeat."""
player = self.bot.lavalink.players.get(ctx.guild.id) repeat_msg = 'You must be in the voice channel to toggle repeat.'
if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)): if not ctx.author.voice:
return await self._embed_msg(ctx, 'You must be in the voice channel to toggle repeat.') return await self._embed_msg(ctx, repeat_msg)
repeat = await self.config.guild(ctx.guild).repeat() repeat = await self.config.guild(ctx.guild).repeat()
await self.config.guild(ctx.guild).repeat.set(not repeat) await self.config.guild(ctx.guild).repeat.set(not repeat)
repeat = await self.config.guild(ctx.guild).repeat() repeat = await self.config.guild(ctx.guild).repeat()
if player.repeat != repeat:
player.repeat = repeat
await self._embed_msg(ctx, 'Repeat songs: {}.'.format(repeat)) await self._embed_msg(ctx, 'Repeat songs: {}.'.format(repeat))
if self._player_check(ctx):
await self._data_check(ctx)
player = lavalink.get_player(ctx.guild.id)
if ctx.author.voice.channel != player.channel:
return await self._embed_msg(ctx, repeat_msg)
@commands.command() @commands.command()
async def remove(self, ctx, index: int): async def remove(self, ctx, index: int):
"""Remove a specific song number from the queue.""" """Remove a specific song number from the queue."""
player = self.bot.lavalink.players.get(ctx.guild.id) if not self._player_check(ctx):
return await self._embed_msg(ctx, 'Nothing playing.')
player = lavalink.get_player(ctx.guild.id)
if not player.queue: if not player.queue:
return await self._embed_msg(ctx, 'Nothing queued.') return await self._embed_msg(ctx, 'Nothing queued.')
if index > len(player.queue) or index < 1: if index > len(player.queue) or index < 1:
return await self._embed_msg(ctx, 'Song number must be greater than 1 and within the queue limit.') return await self._embed_msg(ctx, 'Song number must be greater than 1 and within the queue limit.')
index -= 1
index = index - 1
removed = player.queue.pop(index) removed = player.queue.pop(index)
await self._embed_msg(ctx, 'Removed **' + removed.title + '** from the queue.') await self._embed_msg(ctx, 'Removed **' + removed.title + '** from the queue.')
@commands.command() @commands.command()
@ -496,26 +507,26 @@ class Audio:
"""Pick a song with a search. """Pick a song with a search.
Use [p]search list <search term> to queue all songs. Use [p]search list <search term> to queue all songs.
""" """
expected = ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "", ""] expected = ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣"]
emoji = { emoji = {
"one": "1⃣", "one": "1⃣",
"two": "2⃣", "two": "2⃣",
"three": "3⃣", "three": "3⃣",
"four": "4⃣", "four": "4⃣",
"five": "5⃣", "five": "5⃣"
"back": "",
"next": ""
} }
player = self.bot.lavalink.players.get(ctx.guild.id) if not ctx.author.voice:
return await self._embed_msg(ctx, 'You must be in the voice channel to enqueue songs.')
if not self._player_check(ctx):
await lavalink.connect(ctx.author.voice.channel)
player = lavalink.get_player(ctx.guild.id)
player.store('connect', datetime.datetime.utcnow())
player = lavalink.get_player(ctx.guild.id)
shuffle = await self.config.guild(ctx.guild).shuffle() shuffle = await self.config.guild(ctx.guild).shuffle()
player.store('channel', ctx.channel.id) player.store('channel', ctx.channel.id)
player.store('guild', ctx.guild.id) player.store('guild', ctx.guild.id)
if ctx.author.voice.channel != player.channel:
if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)):
return await self._embed_msg(ctx, 'You must be in the voice channel to enqueue songs.') return await self._embed_msg(ctx, 'You must be in the voice channel to enqueue songs.')
if not player.is_connected:
player.store('connect', datetime.datetime.utcnow())
await player.connect(ctx.author.voice.channel.id)
query = query.strip('<>') query = query.strip('<>')
if query.startswith('sc '): if query.startswith('sc '):
@ -523,7 +534,7 @@ class Audio:
elif not query.startswith('http') or query.startswith('sc '): elif not query.startswith('http') or query.startswith('sc '):
query = 'ytsearch:{}'.format(query) query = 'ytsearch:{}'.format(query)
tracks = await self.bot.lavalink.client.get_tracks(query) tracks = await player.get_tracks(query)
if not tracks: if not tracks:
return await self._embed_msg(ctx, 'Nothing found 👀') return await self._embed_msg(ctx, 'Nothing found 👀')
if 'list' not in query and 'ytsearch:' or 'scsearch:' in query: if 'list' not in query and 'ytsearch:' or 'scsearch:' in query:
@ -532,13 +543,11 @@ class Audio:
pages = math.ceil(len(tracks) / items_per_page) pages = math.ceil(len(tracks) / items_per_page)
start = (page - 1) * items_per_page start = (page - 1) * items_per_page
end = start + items_per_page end = start + items_per_page
search_list = '' search_list = ''
for i, track in enumerate(tracks[start:end], start=start): for i, track in enumerate(tracks[start:end], start=start):
next = i + 1 next = i + 1
search_list += '`{0}.` [**{1}**]({2})\n'.format(next, tracks[i]["info"]["title"], search_list += '`{0}.` [**{1}**]({2})\n'.format(next, track.title,
tracks[i]["info"]["uri"]) track.uri)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Tracks Found:', description=search_list) embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Tracks Found:', description=search_list)
embed.set_footer(text='Page {}/{} | {} search results'.format(page, pages, len(tracks))) embed.set_footer(text='Page {}/{} | {} search results'.format(page, pages, len(tracks)))
@ -547,7 +556,7 @@ class Audio:
def check(r, u): def check(r, u):
return r.message.id == message.id and u == ctx.message.author return r.message.id == message.id and u == ctx.message.author
for i in range(7): for i in range(5):
await message.add_reaction(expected[i]) await message.add_reaction(expected[i])
try: try:
(r, u) = await self.bot.wait_for('reaction_add', check=check, timeout=30.0) (r, u) = await self.bot.wait_for('reaction_add', check=check, timeout=30.0)
@ -556,157 +565,152 @@ class Audio:
return return
reacts = {v: k for k, v in emoji.items()} reacts = {v: k for k, v in emoji.items()}
react = reacts[r.emoji] react = reacts[r.emoji]
if react == 'one': choice = {'one': 0, 'two': 1, 'three': 2, 'four': 3, 'five': 4}
await self._search_button(ctx, message, tracks, entry=0) await self._search_button(ctx, message, tracks, entry=choice[react])
elif react == 'two':
await self._search_button(ctx, message, tracks, entry=1)
elif react == 'three':
await self._search_button(ctx, message, tracks, entry=2)
elif react == 'four':
await self._search_button(ctx, message, tracks, entry=3)
elif react == 'five':
await self._search_button(ctx, message, tracks, entry=4)
elif react == 'back':
await self._clear_react(message)
return
elif react == 'next':
await self._clear_react(message)
return
else: else:
await self._data_check(ctx) await self._data_check(ctx)
songembed = discord.Embed(colour=ctx.guild.me.top_role.colour, songembed = discord.Embed(colour=ctx.guild.me.top_role.colour,
title='Queued {} track(s).'.format(len(tracks))) title='Queued {} track(s).'.format(len(tracks)))
queue_duration = await self._queue_duration(ctx) queue_duration = await self._queue_duration(ctx)
queue_total_duration = lavalink.Utils.format_time(queue_duration) queue_total_duration = lavalink.utils.format_time(queue_duration)
if not shuffle and queue_duration > 0: if not shuffle and queue_duration > 0:
songembed.set_footer(text='{} until start of search playback'.format(queue_total_duration)) songembed.set_footer(text='{} until start of search playback'.format(queue_total_duration))
for track in tracks: for track in tracks:
player.add(requester=ctx.author.id, track=track) player.add(ctx.author, track)
if not player.is_playing: if not player.current:
await player.play() await player.play()
message = await ctx.send(embed=songembed) message = await ctx.send(embed=songembed)
async def _search_button(self, ctx, message, tracks, entry: int): async def _search_button(self, ctx, message, tracks, entry: int):
player = self.bot.lavalink.players.get(ctx.guild.id) player = lavalink.get_player(ctx.guild.id)
shuffle = await self.config.guild(ctx.guild).shuffle() shuffle = await self.config.guild(ctx.guild).shuffle()
await self._clear_react(message) await self._clear_react(message)
player.add(requester=ctx.author.id, track=tracks[entry]) search_choice = tracks[entry]
track_title = tracks[entry]["info"]["title"]
track_url = tracks[entry]["info"]["uri"]
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Track Enqueued', embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Track Enqueued',
description='[**{}**]({})'.format(track_title, track_url)) description='**[{}]({})**'.format(search_choice.title, search_choice.uri))
queue_duration = await self._queue_duration(ctx) queue_duration = await self._queue_duration(ctx)
queue_total_duration = lavalink.Utils.format_time(queue_duration) queue_total_duration = lavalink.utils.format_time(queue_duration)
if not shuffle: if not shuffle and queue_duration > 0:
embed.set_footer(text='{} until track playback'.format(queue_total_duration)) embed.set_footer(text='{} until track playback'.format(queue_total_duration))
if not player.is_playing: player.add(ctx.author, search_choice)
if not player.current:
await player.play() await player.play()
return await ctx.send(embed=embed) return await ctx.send(embed=embed)
@commands.command() @commands.command()
async def seek(self, ctx, seconds: int = 5): async def seek(self, ctx, seconds: int=30):
"""Seeks ahead or behind on a track by seconds.""" """Seeks ahead or behind on a track by seconds."""
player = self.bot.lavalink.players.get(ctx.guild.id) if not self._player_check(ctx):
if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)): return await self._embed_msg(ctx, 'Nothing playing.')
player = lavalink.get_player(ctx.guild.id)
if not ctx.author.voice or ctx.author.voice.channel != player.channel:
return await self._embed_msg(ctx, 'You must be in the voice channel to use seek.') return await self._embed_msg(ctx, 'You must be in the voice channel to use seek.')
if player.is_playing: if player.current:
if player.current.stream: if player.current.is_stream:
return await self._embed_msg(ctx, 'Can\'t seek on a stream.') return await self._embed_msg(ctx, 'Can\'t seek on a stream.')
else: else:
time_sec = seconds * 1000 time_sec = seconds * 1000
seek = player.position + time_sec seek = player.position + time_sec
if abs(time_sec) > player.position: if seek <= 0:
await self._embed_msg(ctx, 'Moved {}s to 00:00:00'.format(seconds)) await self._embed_msg(ctx, 'Moved {}s to 00:00:00'.format(seconds))
else: else:
await self._embed_msg(ctx, 'Moved {}s to {}'.format(seconds, lavalink.Utils.format_time(seek))) await self._embed_msg(ctx, 'Moved {}s to {}'.format(seconds, lavalink.utils.format_time(seek)))
return await player.seek(seek) return await player.seek(seek)
else:
await self._embed_msg(ctx, 'Nothing playing.')
@commands.command() @commands.command()
async def shuffle(self, ctx): async def shuffle(self, ctx):
"""Toggles shuffle.""" """Toggles shuffle."""
player = self.bot.lavalink.players.get(ctx.guild.id) shuffle_msg = 'You must be in the voice channel to toggle shuffle.'
if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)): if not ctx.author.voice:
return await self._embed_msg(ctx, 'You must be in the voice channel to toggle shuffle.') return await self._embed_msg(ctx, shuffle_msg)
shuffle = await self.config.guild(ctx.guild).shuffle() shuffle = await self.config.guild(ctx.guild).shuffle()
await self.config.guild(ctx.guild).shuffle.set(not shuffle) await self.config.guild(ctx.guild).shuffle.set(not shuffle)
shuffle = await self.config.guild(ctx.guild).shuffle() shuffle = await self.config.guild(ctx.guild).shuffle()
if player.shuffle != shuffle:
player.shuffle = shuffle
await self._embed_msg(ctx, 'Shuffle songs: {}.'.format(shuffle)) await self._embed_msg(ctx, 'Shuffle songs: {}.'.format(shuffle))
if self._player_check(ctx):
await self._data_check(ctx)
player = lavalink.get_player(ctx.guild.id)
if ctx.author.voice.channel != player.channel:
return await self._embed_msg(ctx, shuffle_msg)
@commands.command(aliases=['forceskip', 'fs']) @commands.command(aliases=['forceskip', 'fs'])
async def skip(self, ctx): async def skip(self, ctx):
"""Skips to the next track.""" """Skips to the next track."""
player = self.bot.lavalink.players.get(ctx.guild.id) if not self._player_check(ctx):
return await self._embed_msg(ctx, 'Nothing playing.')
else:
player = lavalink.get_player(ctx.guild.id)
if player.current is None: if not player.current:
return await self._embed_msg(ctx, 'The player is stopped.') return await self._embed_msg(ctx, 'There\'s nothing in the queue.')
if not player.queue: if not player.queue:
pos = player.position pos, dur = player.position, player.current.length
dur = player.current.duration time_remain = lavalink.utils.format_time(dur - pos)
remain = dur - pos if player.current.is_stream:
time_remain = lavalink.Utils.format_time(remain)
if player.current.stream:
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='There\'s nothing in the queue.') embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='There\'s nothing in the queue.')
embed.set_footer(text='Currently livestreaming {}'.format(player.current.title)) embed.set_footer(text='Currently livestreaming {}'.format(player.current.title))
return await ctx.send(embed=embed) else:
elif player.current.track:
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='There\'s nothing in the queue.') embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='There\'s nothing in the queue.')
embed.set_footer(text='{} left on {}'.format(time_remain, player.current.title)) embed.set_footer(text='{} left on {}'.format(time_remain, player.current.title))
return await ctx.send(embed=embed) return await ctx.send(embed=embed)
else:
return await self._embed_msg(ctx, 'There\'s nothing in the queue.')
if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)): if not ctx.author.voice or ctx.author.voice.channel != player.channel:
return await self._embed_msg(ctx, 'You must be in the voice channel to skip the music.') return await self._embed_msg(ctx, 'You must be in the voice channel to skip the music.')
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Track Skipped', embed = discord.Embed(
description='**[{}]({})**'.format(player.current.title, player.current.uri)) colour=ctx.guild.me.top_role.colour, title='Track Skipped',
message = await ctx.send(embed=embed) description='**[{}]({})**'.format(
player.current.title, player.current.uri
)
)
await ctx.send(embed=embed)
await player.skip() await player.skip()
@commands.command(aliases=['s']) @commands.command(aliases=['s'])
async def stop(self, ctx): async def stop(self, ctx):
"""Stops playback and clears the queue.""" """Stops playback and clears the queue."""
player = self.bot.lavalink.players.get(ctx.guild.id) if not self._player_check(ctx):
if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)): return await self._embed_msg(ctx, 'Nothing playing.')
player = lavalink.get_player(ctx.guild.id)
if not ctx.author.voice or ctx.author.voice.channel != player.channel:
return await self._embed_msg(ctx, 'You must be in the voice channel to stop the music.') return await self._embed_msg(ctx, 'You must be in the voice channel to stop the music.')
if player.is_playing: if player.is_playing:
await self._embed_msg(ctx, 'Stopping...') await self._embed_msg(ctx, 'Stopping...')
player.queue.clear()
await player.stop() await player.stop()
player.store('prev_requester', None) player.store('prev_requester', None)
player.store('prev_song', None) player.store('prev_song', None)
player.store('playing_song', None) player.store('playing_song', None)
player.store('requester', None) player.store('requester', None)
await self.bot.lavalink.client._trigger_event("QueueEndEvent", ctx.guild.id)
@commands.command(aliases=['vol']) @commands.command()
async def volume(self, ctx, vol: int = None): async def volume(self, ctx, vol: int=None):
"""Sets the volume, 1% - 150%.""" """Sets the volume, 1% - 150%."""
player = self.bot.lavalink.players.get(ctx.guild.id)
if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)):
return await self._embed_msg(ctx, 'You must be in the voice channel to change the volume.')
if not vol: if not vol:
vol = await self.config.guild(ctx.guild).volume() vol = await self.config.guild(ctx.guild).volume()
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Current Volume:', embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Current Volume:',
description=str(vol) + '%') description=str(vol) + '%')
if not player.is_playing: if not self._player_check(ctx):
embed.set_footer(text='Nothing playing.') embed.set_footer(text='Nothing playing.')
return await ctx.send(embed=embed) return await ctx.send(embed=embed)
if int(vol) > 150: if vol > 150:
vol = 150 vol = 150
await self.config.guild(ctx.guild).volume.set(vol) await self.config.guild(ctx.guild).volume.set(vol)
await player.set_volume(vol) if self._player_check:
await lavalink.get_player(ctx.guild.id).set_volume(vol)
else: else:
await self.config.guild(ctx.guild).volume.set(vol) await self.config.guild(ctx.guild).volume.set(vol)
await player.set_volume(vol) if self._player_check:
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Volume:', description=str(vol) + '%') await lavalink.get_player(ctx.guild.id).set_volume(vol)
if not player.is_playing: embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Volume:',
description=str(vol) + '%')
if not self._player_check(ctx):
embed.set_footer(text='Nothing playing.') embed.set_footer(text='Nothing playing.')
await ctx.send(embed=embed) await ctx.send(embed=embed)
@ -732,11 +736,18 @@ class Audio:
await self._embed_msg(ctx, 'Server password set to {}.'.format(get_passw)) await self._embed_msg(ctx, 'Server password set to {}.'.format(get_passw))
@llsetup.command() @llsetup.command()
async def port(self, ctx, port): async def restport(self, ctx, rest_port):
"""Set the lavalink server port.""" """Set the lavalink REST server port."""
await self.config.port.set(str(port)) await self.config.rest_port.set(str(rest_port))
get_port = await self.config.port() get_rest_port = await self.config.rest_port()
await self._embed_msg(ctx, 'Port set to {}.'.format(get_port)) await self._embed_msg(ctx, 'REST port set to {}.'.format(get_rest_port))
@llsetup.command()
async def wsport(self, ctx, rest_port):
"""Set the lavalink websocket server port."""
await self.config.ws_port.set(str(ws_port))
get_rest_port = await self.config.ws_port()
await self._embed_msg(ctx, 'Websocket port set to {}.'.format(get_ws_port))
async def _clear_react(self, message): async def _clear_react(self, message):
try: try:
@ -745,7 +756,7 @@ class Audio:
return return
async def _data_check(self, ctx): async def _data_check(self, ctx):
player = self.bot.lavalink.players.get(ctx.guild.id) player = lavalink.get_player(ctx.guild.id)
shuffle = await self.config.guild(ctx.guild).shuffle() shuffle = await self.config.guild(ctx.guild).shuffle()
repeat = await self.config.guild(ctx.guild).repeat() repeat = await self.config.guild(ctx.guild).repeat()
volume = await self.config.guild(ctx.guild).volume() volume = await self.config.guild(ctx.guild).volume()
@ -754,13 +765,13 @@ class Audio:
if player.shuffle != shuffle: if player.shuffle != shuffle:
player.shuffle = shuffle player.shuffle = shuffle
if player.volume != volume: if player.volume != volume:
player.volume = volume await player.set_volume(volume)
async def _draw_time(self, ctx): async def _draw_time(self, ctx):
player = self.bot.lavalink.players.get(ctx.guild.id) player = lavalink.get_player(ctx.guild.id)
paused = player.paused paused = player.paused
pos = player.position pos = player.position
dur = player.current.duration dur = player.current.length
sections = 12 sections = 12
loc_time = round((pos / dur) * sections) loc_time = round((pos / dur) * sections)
bar = '\N{BOX DRAWINGS HEAVY HORIZONTAL}' bar = '\N{BOX DRAWINGS HEAVY HORIZONTAL}'
@ -795,21 +806,25 @@ class Audio:
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title=title) embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title=title)
await ctx.send(embed=embed) await ctx.send(embed=embed)
async def _get_playing(self): async def _get_playing(self, ctx):
return len([p for p in self.bot.lavalink.players._players.values() if p.is_playing]) if self._player_check(ctx):
player = lavalink.get_player(ctx.guild.id)
return len([player for p in lavalink.players if p.is_playing])
else:
return 0
async def _queue_duration(self, ctx): async def _queue_duration(self, ctx):
player = self.bot.lavalink.players.get(ctx.guild.id) player = lavalink.get_player(ctx.guild.id)
duration = [] duration = []
for i in range(len(player.queue)): for i in range(len(player.queue)):
if not player.queue[i].stream: if not player.queue[i].is_stream:
duration.append(player.queue[i].duration) duration.append(player.queue[i].length)
queue_duration = sum(duration) queue_duration = sum(duration)
if player.queue == []: if player.queue == []:
queue_duration = 0 queue_duration = 0
try: try:
if not player.current.stream: if not player.current.is_stream:
remain = player.current.duration - player.position remain = player.current.length - player.position
else: else:
remain = 0 remain = 0
except AttributeError: except AttributeError:
@ -817,7 +832,14 @@ class Audio:
queue_total_duration = remain + queue_duration queue_total_duration = remain + queue_duration
return queue_total_duration return queue_total_duration
def _player_check(self, ctx):
try:
lavalink.get_player(ctx.guild.id)
return True
except KeyError:
return False
def __unload(self): def __unload(self):
self.bot.lavalink.ws._ws.close() lavalink.unregister_event_listener(self.event_handler)
self.bot.lavalink.client.destroy() self.bot.loop.create_task(lavalink.close())
shutdown_lavalink_server() shutdown_lavalink_server()

View File

@ -7,4 +7,3 @@ colorama==0.3.9
aiohttp-json-rpc==0.8.7 aiohttp-json-rpc==0.8.7
pyyaml==3.12 pyyaml==3.12
Red-Trivia Red-Trivia
lavalink==2.0.2.9

View File

@ -130,6 +130,6 @@ setup(
], ],
'mongo': ['motor'], 'mongo': ['motor'],
'docs': ['sphinx', 'sphinxcontrib-asyncio', 'sphinx_rtd_theme'], 'docs': ['sphinx', 'sphinxcontrib-asyncio', 'sphinx_rtd_theme'],
'voice': ['PyNaCl'] 'voice': ['red-lavalink>=0.0.4']
} }
) )