Will ccb322d08e [Audio] V3/auto autostart only (#1420)
* Download jar at audio load

* Messy...

* Remove leftover log file stuff

* Keep application.yml

* Damn you windows
2018-03-12 00:49:08 +01:00

824 lines
36 KiB
Python

# Lavalink.py cog for Red v3 beta 7+
# Cog base thanks to Kromatic's example cog.
import asyncio
import datetime
import discord
import heapq
import lavalink
import math
from discord.ext import commands
from redbot.core import Config, checks
from .manager import shutdown_lavalink_server
__version__ = "2.0.2.9.b"
__author__ = ["aikaterna", "billy/bollo/ati"]
class Audio:
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, 2711759128, force_registration=True)
default_global = {
"host": 'localhost',
"port": '2332',
"passw": 'youshallnotpass',
"status": False,
"current_build": 0
}
default_guild = {
"notify": False,
"repeat": False,
"shuffle": False,
"volume": 100
}
self.config.register_guild(**default_guild)
self.config.register_global(**default_global)
self._lavalink = None
async def init_config(self):
host = await self.config.host()
passw = await self.config.passw()
port = await self.config.port()
try:
self._lavalink = lavalink.Client(
bot=self.bot, password=passw, host=host, port=port, loop=self.bot.loop
)
except RuntimeError:
pass
self.bot.lavalink.client.register_hook(self.track_hook)
@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()
playing_servers = await self._get_playing()
get_players = [p for p in self.bot.lavalink.players._players.values() if p.is_playing]
try:
get_single_title = get_players[0].current.title
except IndexError:
pass
if event == 'TrackStartEvent':
playing_song = player.fetch('playing_song')
requester = player.fetch('requester')
player.store('prev_song', playing_song)
player.store('prev_requester', requester)
player.store('playing_song', self.bot.lavalink.players.get(player.fetch('guild')).current.uri)
player.store('requester', self.bot.get_user(self.bot.lavalink.players.get(player.fetch('guild')).current.requester))
if event == 'TrackStartEvent' and notify:
c = player.fetch('channel')
if c:
c = self.bot.get_channel(c)
if player.fetch('notify_message') is not None:
try:
await player.fetch('notify_message').delete()
except discord.errors.NotFound:
pass
embed = discord.Embed(colour=c.guild.me.top_role.colour, title='Now Playing',
description='**[{}]({})**'.format(player.current.title, player.current.uri))
notify_message = await c.send(embed=embed)
player.store('notify_message', notify_message)
if event == 'TrackStartEvent' 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:
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()
@checks.is_owner()
async def audioset(self, ctx):
"""Music configuration options."""
if ctx.invoked_subcommand is None:
await ctx.send_help()
@audioset.command()
async def notify(self, ctx):
"""Toggle song announcement and other bot messages."""
notify = await self.config.guild(ctx.guild).notify()
await self.config.guild(ctx.guild).notify.set(not notify)
get_notify = await self.config.guild(ctx.guild).notify()
await self._embed_msg(ctx, 'Verbose mode on: {}.'.format(get_notify))
@audioset.command()
async def settings(self, ctx):
"""Show the current settings."""
notify = await self.config.guild(ctx.guild).notify()
status = await self.config.status()
shuffle = await self.config.guild(ctx.guild).shuffle()
repeat = await self.config.guild(ctx.guild).repeat()
msg = '```ini\n'
msg += '----Guild Settings----\n'
msg += 'audioset notify: [{}]\n'.format(notify)
msg += 'audioset status: [{}]\n'.format(status)
msg += 'Repeat: [{}]\n'.format(repeat)
msg += 'Shuffle: [{}]\n'.format(shuffle)
msg += '---Lavalink Settings---\n'
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)
return await ctx.send(embed=embed)
@audioset.command()
@checks.is_owner()
async def status(self, ctx):
"""Enables/disables songs' titles as status."""
status = await self.config.status()
await self.config.status.set(not status)
get_status = await self.config.status()
await self._embed_msg(ctx, 'Song titles as status: {}'.format(get_status))
@commands.command()
async def audiostats(self, ctx):
"""Audio stats."""
server_num = await self._get_playing()
server_ids = self.bot.lavalink.players._players
server_list = []
for k, v in server_ids.items():
guild_id = k
player = v
connect_start = v.fetch('connect')
try:
connect_dur = self._dynamic_time(int((datetime.datetime.utcnow() - connect_start).total_seconds()))
except TypeError:
connect_dur = 0
try:
server_list.append('{} [`{}`]: **[{}]({})**'.format(self.bot.get_guild(guild_id).name, connect_dur,
v.current.title, v.current.uri))
except AttributeError:
pass
servers = '\n'.join(server_list)
if server_list == []:
servers = 'Not connected anywhere.'
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Playing in {} servers:'.format(server_num),
description=servers)
await ctx.send(embed=embed)
@commands.command()
async def bump(self, ctx, index: int):
"""Bump a song number to the top of the queue."""
player = self.bot.lavalink.players.get(ctx.guild.id)
if not player.queue:
return await self._embed_msg(ctx, 'Nothing queued.')
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.')
bump_index = index - 1
bump_song = self.bot.lavalink.players.get(ctx.guild.id).queue[bump_index]
player.queue.insert(0, bump_song)
removed = player.queue.pop(index)
await self._embed_msg(ctx, 'Moved **' + removed.title + '** to the top of the queue.')
@commands.command(aliases=['dc'])
async def disconnect(self, ctx):
"""Disconnect from the voice channel."""
player = self.bot.lavalink.players.get(ctx.guild.id)
await player.disconnect()
player.queue.clear()
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'])
async def now(self, ctx):
"""Now playing."""
expected = ['', '', '']
emoji = {
'stop': '',
'pause': '',
'next': ''
}
player = self.bot.lavalink.players.get(ctx.guild.id)
song = 'Nothing'
if player.current:
arrow = await self._draw_time(ctx)
pos = lavalink.Utils.format_time(player.position)
if player.current.stream:
dur = 'LIVE'
else:
dur = lavalink.Utils.format_time(player.current.duration)
if not player.current:
song = 'Nothing.'
else:
req_user = self.bot.get_user(player.current.requester)
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:
try:
await player.fetch('np_message').delete()
except discord.errors.NotFound:
pass
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Now Playing', description=song)
message = await ctx.send(embed=embed)
player.store('np_message', message)
def check(r, u):
return r.message.id == message.id and u == ctx.message.author
if player.current:
for i in range(3):
await message.add_reaction(expected[i])
try:
(r, u) = await self.bot.wait_for('reaction_add', check=check, timeout=10.0)
except asyncio.TimeoutError:
return await self._clear_react(message)
reacts = {v: k for k, v in emoji.items()}
react = reacts[r.emoji]
if react == 'stop':
await self._clear_react(message)
await ctx.invoke(self.stop)
elif react == 'pause':
await self._clear_react(message)
await ctx.invoke(self.pause)
elif react == 'next':
await self._clear_react(message)
await ctx.invoke(self.skip)
@commands.command(aliases=['resume'])
async def pause(self, ctx):
"""Pause and resume."""
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 pause the music.')
if not player.is_playing:
return
if player.paused:
await player.set_pause(False)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Track Resumed',
description='**[{}]({})**'.format(player.current.title, player.current.uri))
message = await ctx.send(embed=embed)
else:
await player.set_pause(True)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Track Paused',
description='**[{}]({})**'.format(player.current.title, player.current.uri))
message = await ctx.send(embed=embed)
@commands.command()
async def percent(self, ctx):
"""Queue percentage."""
queue_tracks = self.bot.lavalink.players.get(ctx.guild.id).queue
queue_len = len(queue_tracks)
requesters = {'total': 0, 'users': {}}
async def _usercount(req_username):
if req_username in requesters['users']:
requesters['users'][req_username]['songcount'] += 1
requesters['total'] += 1
else:
requesters['users'][req_username] = {}
requesters['users'][req_username]['songcount'] = 1
requesters['total'] += 1
for i in range(queue_len):
req_username = self.bot.get_user(queue_tracks[i].requester).name
await _usercount(req_username)
try:
req_username = self.bot.get_user(self.bot.lavalink.players.get(ctx.guild.id).current.requester).name
await _usercount(req_username)
except AttributeError:
return await self._embed_msg(ctx, 'Nothing in the queue.')
for req_username in requesters['users']:
percentage = float(requesters['users'][req_username]['songcount']) / float(requesters['total'])
requesters['users'][req_username]['percent'] = round(percentage * 100, 1)
top_queue_users = heapq.nlargest(20, [(x, requesters['users'][x][y]) for x in requesters['users'] for y in
requesters['users'][x] if y == 'percent'], key=lambda x: x[1])
queue_user = ["{}: {:g}%".format(x[0], x[1]) for x in top_queue_users]
queue_user_list = '\n'.join(queue_user)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Queued and playing songs:',
description=queue_user_list)
await ctx.send(embed=embed)
@commands.command(aliases=['p'])
async def play(self, ctx, *, query):
"""Play a URL or search for a song."""
player = self.bot.lavalink.players.get(ctx.guild.id)
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.')
player.store('channel', ctx.channel.id)
player.store('guild', ctx.guild.id)
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('<>')
if not query.startswith('http'):
query = 'ytsearch:{}'.format(query)
tracks = await self.bot.lavalink.client.get_tracks(query)
if not tracks:
return await self._embed_msg(ctx, 'Nothing found 👀')
queue_duration = await self._queue_duration(ctx)
queue_total_duration = lavalink.Utils.format_time(queue_duration)
if 'list' in query and 'ytsearch:' not in query:
for track in tracks:
player.add(requester=ctx.author.id, track=track)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Playlist Enqueued',
description='Added {} tracks to the queue.'.format(len(tracks)))
if not shuffle and queue_duration > 0:
embed.set_footer(text='{} until start of playlist playback'.format(queue_total_duration))
else:
player.add(requester=ctx.author.id, track=tracks[0])
track_title = tracks[0]["info"]["title"]
track_url = tracks[0]["info"]["uri"]
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Track Enqueued',
description='[**{}**]({})'.format(track_title, track_url))
if not shuffle and queue_duration > 0:
embed.set_footer(text='{} until track playback'.format(queue_total_duration))
await ctx.send(embed=embed)
if not player.is_playing:
await player.play()
@commands.command()
async def prev(self, ctx):
"""Skips to the start of the previously played track."""
player = self.bot.lavalink.players.get(ctx.guild.id)
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 skip the music.')
if shuffle:
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:
return await self._embed_msg(ctx, 'No previous track.')
else:
last_track = await self.bot.lavalink.client.get_tracks(player.fetch('prev_song'))
player.add(player.fetch('prev_requester').id, last_track[0])
queue_len = len(self.bot.lavalink.players.get(ctx.guild.id).queue)
bump_song = self.bot.lavalink.players.get(ctx.guild.id).queue[queue_len - 1]
player.queue.insert(0, bump_song)
player.queue.pop(queue_len)
await player.skip()
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)
@commands.command(aliases=['q'])
async def queue(self, ctx, page: int = 1):
"""Lists the queue."""
shuffle = await self.config.guild(ctx.guild).shuffle()
repeat = await self.config.guild(ctx.guild).repeat()
player = self.bot.lavalink.players.get(ctx.guild.id)
if not player.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
pages = math.ceil(len(player.queue) / items_per_page)
start = (page - 1) * items_per_page
end = start + items_per_page
queue_list = ''
arrow = await self._draw_time(ctx)
pos = lavalink.Utils.format_time(player.position)
if player.current.stream:
dur = 'LIVE'
else:
dur = lavalink.Utils.format_time(player.current.duration)
if player.current.stream:
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)
else:
queue_list += 'Playing: [**{}**]({})\nRequested by: **{}**\n\n{}`{}`/`{}`\n\n'.format(player.current.title,
player.current.uri,
self.bot.get_user(
player.current.requester),
arrow, pos, dur)
for i, track in enumerate(player.queue[start:end], start=start):
req_user = self.bot.get_user(track.requester)
next = i + 1
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,
description=queue_list)
queue_duration = await self._queue_duration(ctx)
queue_total_duration = lavalink.Utils.format_time(queue_duration)
text = 'Page {}/{} | {} tracks, {} remaining'.format(page, pages, len(player.queue), queue_total_duration)
if repeat:
text += ' | Repeat: \N{WHITE HEAVY CHECK MARK}'
if shuffle:
text += ' | Shuffle: \N{WHITE HEAVY CHECK MARK}'
embed.set_footer(text=text)
await ctx.send(embed=embed)
@commands.command()
async def repeat(self, ctx):
"""Toggles repeat."""
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 toggle repeat.')
repeat = await self.config.guild(ctx.guild).repeat()
await self.config.guild(ctx.guild).repeat.set(not 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))
@commands.command()
async def remove(self, ctx, index: int):
"""Remove a specific song number from the queue."""
player = self.bot.lavalink.players.get(ctx.guild.id)
if not player.queue:
return await self._embed_msg(ctx, 'Nothing queued.')
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.')
index = index - 1
removed = player.queue.pop(index)
await self._embed_msg(ctx, 'Removed **' + removed.title + '** from the queue.')
@commands.command()
async def search(self, ctx, *, query):
"""Pick a song with a search.
Use [p]search list <search term> to queue all songs.
"""
expected = ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "", ""]
emoji = {
"one": "1⃣",
"two": "2⃣",
"three": "3⃣",
"four": "4⃣",
"five": "5⃣",
"back": "",
"next": ""
}
player = self.bot.lavalink.players.get(ctx.guild.id)
shuffle = await self.config.guild(ctx.guild).shuffle()
player.store('channel', ctx.channel.id)
player.store('guild', 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 enqueue songs.')
if not player.is_connected:
player.store('connect', datetime.datetime.utcnow())
await player.connect(ctx.author.voice.channel.id)
query = query.strip('<>')
if query.startswith('sc '):
query = 'scsearch:{}'.format(query.strip('sc '))
elif not query.startswith('http') or query.startswith('sc '):
query = 'ytsearch:{}'.format(query)
tracks = await self.bot.lavalink.client.get_tracks(query)
if not tracks:
return await self._embed_msg(ctx, 'Nothing found 👀')
if 'list' not in query and 'ytsearch:' or 'scsearch:' in query:
page = 1
items_per_page = 5
pages = math.ceil(len(tracks) / items_per_page)
start = (page - 1) * items_per_page
end = start + items_per_page
search_list = ''
for i, track in enumerate(tracks[start:end], start=start):
next = i + 1
search_list += '`{0}.` [**{1}**]({2})\n'.format(next, tracks[i]["info"]["title"],
tracks[i]["info"]["uri"])
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)))
message = await ctx.send(embed=embed)
def check(r, u):
return r.message.id == message.id and u == ctx.message.author
for i in range(7):
await message.add_reaction(expected[i])
try:
(r, u) = await self.bot.wait_for('reaction_add', check=check, timeout=30.0)
except asyncio.TimeoutError:
await self._clear_react(message)
return
reacts = {v: k for k, v in emoji.items()}
react = reacts[r.emoji]
if react == 'one':
await self._search_button(ctx, message, tracks, entry=0)
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:
await self._data_check(ctx)
songembed = discord.Embed(colour=ctx.guild.me.top_role.colour,
title='Queued {} track(s).'.format(len(tracks)))
queue_duration = await self._queue_duration(ctx)
queue_total_duration = lavalink.Utils.format_time(queue_duration)
if not shuffle and queue_duration > 0:
songembed.set_footer(text='{} until start of search playback'.format(queue_total_duration))
for track in tracks:
player.add(requester=ctx.author.id, track=track)
if not player.is_playing:
await player.play()
message = await ctx.send(embed=songembed)
async def _search_button(self, ctx, message, tracks, entry: int):
player = self.bot.lavalink.players.get(ctx.guild.id)
shuffle = await self.config.guild(ctx.guild).shuffle()
await self._clear_react(message)
player.add(requester=ctx.author.id, track=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',
description='[**{}**]({})'.format(track_title, track_url))
queue_duration = await self._queue_duration(ctx)
queue_total_duration = lavalink.Utils.format_time(queue_duration)
if not shuffle:
embed.set_footer(text='{} until track playback'.format(queue_total_duration))
if not player.is_playing:
await player.play()
return await ctx.send(embed=embed)
@commands.command()
async def seek(self, ctx, seconds: int = 5):
"""Seeks ahead or behind on a track by seconds."""
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 use seek.')
if player.is_playing:
if player.current.stream:
return await self._embed_msg(ctx, 'Can\'t seek on a stream.')
else:
time_sec = seconds * 1000
seek = player.position + time_sec
if abs(time_sec) > player.position:
await self._embed_msg(ctx, 'Moved {}s to 00:00:00'.format(seconds))
else:
await self._embed_msg(ctx, 'Moved {}s to {}'.format(seconds, lavalink.Utils.format_time(seek)))
return await player.seek(seek)
@commands.command()
async def shuffle(self, ctx):
"""Toggles shuffle."""
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 toggle shuffle.')
shuffle = await self.config.guild(ctx.guild).shuffle()
await self.config.guild(ctx.guild).shuffle.set(not 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))
@commands.command(aliases=['forceskip', 'fs'])
async def skip(self, ctx):
"""Skips to the next track."""
player = self.bot.lavalink.players.get(ctx.guild.id)
if player.current is None:
return await self._embed_msg(ctx, 'The player is stopped.')
if not player.queue:
pos = player.position
dur = player.current.duration
remain = dur - pos
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.set_footer(text='Currently livestreaming {}'.format(player.current.title))
return await ctx.send(embed=embed)
elif player.current.track:
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))
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)):
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',
description='**[{}]({})**'.format(player.current.title, player.current.uri))
message = await ctx.send(embed=embed)
await player.skip()
@commands.command(aliases=['s'])
async def stop(self, ctx):
"""Stops playback and clears the queue."""
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 stop the music.')
if player.is_playing:
await self._embed_msg(ctx, 'Stopping...')
player.queue.clear()
await player.stop()
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=['vol'])
async def volume(self, ctx, vol: int = None):
"""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:
vol = await self.config.guild(ctx.guild).volume()
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Current Volume:',
description=str(vol) + '%')
if not player.is_playing:
embed.set_footer(text='Nothing playing.')
return await ctx.send(embed=embed)
if int(vol) > 150:
vol = 150
await self.config.guild(ctx.guild).volume.set(vol)
await player.set_volume(vol)
else:
await self.config.guild(ctx.guild).volume.set(vol)
await player.set_volume(vol)
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Volume:', description=str(vol) + '%')
if not player.is_playing:
embed.set_footer(text='Nothing playing.')
await ctx.send(embed=embed)
@commands.group(aliases=['llset'])
@checks.is_owner()
async def llsetup(self, ctx):
"""Lavalink server configuration options."""
if ctx.invoked_subcommand is None:
await ctx.send_help()
@llsetup.command()
async def host(self, ctx, host):
"""Set the lavalink server host."""
await self.config.host.set(host)
get_host = await self.config.host()
await self._embed_msg(ctx, 'Host set to {}.'.format(get_host))
@llsetup.command()
async def password(self, ctx, passw):
"""Set the lavalink server password."""
await self.config.passw.set(str(passw))
get_passw = await self.config.passw()
await self._embed_msg(ctx, 'Server password set to {}.'.format(get_passw))
@llsetup.command()
async def port(self, ctx, port):
"""Set the lavalink server port."""
await self.config.port.set(str(port))
get_port = await self.config.port()
await self._embed_msg(ctx, 'Port set to {}.'.format(get_port))
async def _clear_react(self, message):
try:
await message.clear_reactions()
except:
return
async def _data_check(self, ctx):
player = self.bot.lavalink.players.get(ctx.guild.id)
shuffle = await self.config.guild(ctx.guild).shuffle()
repeat = await self.config.guild(ctx.guild).repeat()
volume = await self.config.guild(ctx.guild).volume()
if player.repeat != repeat:
player.repeat = repeat
if player.shuffle != shuffle:
player.shuffle = shuffle
if player.volume != volume:
player.volume = volume
async def _draw_time(self, ctx):
player = self.bot.lavalink.players.get(ctx.guild.id)
paused = player.paused
pos = player.position
dur = player.current.duration
sections = 12
loc_time = round((pos / dur) * sections)
bar = '\N{BOX DRAWINGS HEAVY HORIZONTAL}'
seek = '\N{RADIO BUTTON}'
if paused:
msg = '\N{DOUBLE VERTICAL BAR}'
else:
msg = '\N{BLACK RIGHT-POINTING TRIANGLE}'
for i in range(sections):
if i == loc_time:
msg += seek
else:
msg += bar
return msg
def _dynamic_time(self, time):
m, s = divmod(time, 60)
h, m = divmod(m, 60)
d, h = divmod(h, 24)
if d > 0:
msg = "{0}d {1}h"
elif d == 0 and h > 0:
msg = "{1}h {2}m"
elif d == 0 and h == 0 and m > 0:
msg = "{2}m {3}s"
elif d == 0 and h == 0 and m == 0 and s > 0:
msg = "{3}s"
return msg.format(d, h, m, s)
async def _embed_msg(self, ctx, title):
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title=title)
await ctx.send(embed=embed)
async def _get_playing(self):
return len([p for p in self.bot.lavalink.players._players.values() if p.is_playing])
async def _queue_duration(self, ctx):
player = self.bot.lavalink.players.get(ctx.guild.id)
duration = []
for i in range(len(player.queue)):
if not player.queue[i].stream:
duration.append(player.queue[i].duration)
queue_duration = sum(duration)
if player.queue == []:
queue_duration = 0
try:
if not player.current.stream:
remain = player.current.duration - player.position
else:
remain = 0
except AttributeError:
remain = 0
queue_total_duration = remain + queue_duration
return queue_total_duration
def __unload(self):
self.bot.lavalink.ws._ws.close()
self.bot.lavalink.client.destroy()
shutdown_lavalink_server()