mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-07 11:48:55 -05:00
[V3 Audio] Add voteskip and DJ role (#1473)
* [V3 Audio] Add voteskip and DJ role * Fix connection time storage for audiostats * Update pause command for more explicit handling Partially fixes #1478. Users will need to use pause twice before resuming until issue no. 20 on the Red-Lavalink repo is addressed. * Update pause command * Update pause command * Add jukebox mode Adds a price option for enqueuing songs. If DJ mode is active when jukebox mode is active, no one is charged credits as mods are exempt and plebs can't queue songs without the DJ role.
This commit is contained in:
parent
29ce2401ca
commit
d9c71bddb8
@ -5,11 +5,11 @@ import heapq
|
|||||||
import lavalink
|
import lavalink
|
||||||
import math
|
import math
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from redbot.core import Config, checks
|
from redbot.core import Config, checks, bank
|
||||||
|
|
||||||
from .manager import shutdown_lavalink_server
|
from .manager import shutdown_lavalink_server
|
||||||
|
|
||||||
__version__ = "0.0.3a"
|
__version__ = "0.0.4"
|
||||||
__author__ = ["aikaterna", "billy/bollo/ati"]
|
__author__ = ["aikaterna", "billy/bollo/ati"]
|
||||||
|
|
||||||
|
|
||||||
@ -28,14 +28,21 @@ class Audio:
|
|||||||
}
|
}
|
||||||
|
|
||||||
default_guild = {
|
default_guild = {
|
||||||
|
"dj_enabled": False,
|
||||||
|
"dj_role": None,
|
||||||
|
"jukebox": False,
|
||||||
|
"jukebox_price": 0,
|
||||||
"notify": False,
|
"notify": False,
|
||||||
"repeat": False,
|
"repeat": False,
|
||||||
"shuffle": False,
|
"shuffle": False,
|
||||||
"volume": 100
|
"volume": 100,
|
||||||
|
"vote_enabled": False,
|
||||||
|
"vote_percent": 0
|
||||||
}
|
}
|
||||||
|
|
||||||
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.skip_votes = {}
|
||||||
|
|
||||||
async def init_config(self):
|
async def init_config(self):
|
||||||
host = await self.config.host()
|
host = await self.config.host()
|
||||||
@ -65,6 +72,7 @@ class Audio:
|
|||||||
player.store('prev_requester', requester)
|
player.store('prev_requester', requester)
|
||||||
player.store('playing_song', player.current.uri)
|
player.store('playing_song', player.current.uri)
|
||||||
player.store('requester', player.current.requester)
|
player.store('requester', player.current.requester)
|
||||||
|
self.skip_votes[player.channel.guild] = []
|
||||||
|
|
||||||
if event_type == lavalink.LavalinkEvents.TRACK_START and notify:
|
if event_type == lavalink.LavalinkEvents.TRACK_START and notify:
|
||||||
notify_channel = player.fetch('channel')
|
notify_channel = player.fetch('channel')
|
||||||
@ -108,48 +116,126 @@ class Audio:
|
|||||||
type=discord.ActivityType.playing))
|
type=discord.ActivityType.playing))
|
||||||
|
|
||||||
@commands.group()
|
@commands.group()
|
||||||
@checks.is_owner()
|
@commands.guild_only()
|
||||||
async def audioset(self, ctx):
|
async def audioset(self, ctx):
|
||||||
"""Music configuration options."""
|
"""Music configuration options."""
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
await ctx.send_help()
|
||||||
|
|
||||||
@audioset.command()
|
@audioset.command()
|
||||||
|
@checks.admin_or_permissions(manage_roles=True)
|
||||||
|
async def dj(self, ctx):
|
||||||
|
"""Toggle DJ mode (users need a role to use audio commands)."""
|
||||||
|
dj_role_id = await self.config.guild(ctx.guild).dj_role()
|
||||||
|
if dj_role_id is None:
|
||||||
|
await self._embed_msg(ctx, 'Please set a role to use with DJ mode. Enter the role name now.')
|
||||||
|
|
||||||
|
def check(m):
|
||||||
|
return m.author == ctx.author
|
||||||
|
try:
|
||||||
|
dj_role = await ctx.bot.wait_for('message', timeout=15.0, check=check)
|
||||||
|
dj_role_obj = discord.utils.get(ctx.guild.roles, name=dj_role.content)
|
||||||
|
if dj_role_obj is None:
|
||||||
|
return await self._embed_msg(ctx, 'No role with that name.')
|
||||||
|
await ctx.invoke(self.role, dj_role_obj)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
return await self._embed_msg(ctx, 'No role entered, try again later.')
|
||||||
|
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
|
await self.config.guild(ctx.guild).dj_enabled.set(not dj_enabled)
|
||||||
|
await self._embed_msg(ctx, 'DJ role enabled: {}.'.format(not dj_enabled))
|
||||||
|
|
||||||
|
@audioset.command()
|
||||||
|
@checks.admin_or_permissions(manage_roles=True)
|
||||||
|
async def role(self, ctx, role_name: discord.Role):
|
||||||
|
"""Sets the role to use for DJ mode."""
|
||||||
|
await self.config.guild(ctx.guild).dj_role.set(role_name.id)
|
||||||
|
dj_role_id = await self.config.guild(ctx.guild).dj_role()
|
||||||
|
dj_role_obj = discord.utils.get(ctx.guild.roles, id=dj_role_id)
|
||||||
|
await self._embed_msg(ctx, 'DJ role set to: {}.'.format(dj_role_obj.name))
|
||||||
|
|
||||||
|
@audioset.command()
|
||||||
|
@checks.mod_or_permissions(administrator=True)
|
||||||
|
async def jukebox(self, ctx, price: int):
|
||||||
|
"""Set a price for queueing songs for non-mods. 0 to disable."""
|
||||||
|
jukebox = await self.config.guild(ctx.guild).jukebox()
|
||||||
|
jukebox_price = await self.config.guild(ctx.guild).jukebox_price()
|
||||||
|
if price < 0:
|
||||||
|
return await self._embed_msg(ctx, 'Can\'t be less than zero.')
|
||||||
|
if price == 0:
|
||||||
|
jukebox = False
|
||||||
|
await self._embed_msg(ctx, 'Jukebox mode disabled.')
|
||||||
|
else:
|
||||||
|
jukebox = True
|
||||||
|
await self._embed_msg(ctx, 'Track queueing command price set to {} {}.'.format(
|
||||||
|
price, await bank.get_currency_name(ctx.guild)))
|
||||||
|
|
||||||
|
await self.config.guild(ctx.guild).jukebox_price.set(price)
|
||||||
|
await self.config.guild(ctx.guild).jukebox.set(jukebox)
|
||||||
|
|
||||||
|
@audioset.command()
|
||||||
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
async def notify(self, ctx):
|
async def notify(self, ctx):
|
||||||
"""Toggle song announcement and other bot messages."""
|
"""Toggle song announcement and other bot messages."""
|
||||||
notify = await self.config.guild(ctx.guild).notify()
|
notify = await self.config.guild(ctx.guild).notify()
|
||||||
await self.config.guild(ctx.guild).notify.set(not 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(not notify))
|
||||||
await self._embed_msg(ctx, 'Verbose mode on: {}.'.format(get_notify))
|
|
||||||
|
|
||||||
@audioset.command()
|
@audioset.command()
|
||||||
async def settings(self, ctx):
|
async def settings(self, ctx):
|
||||||
"""Show the current settings."""
|
"""Show the current settings."""
|
||||||
notify = await self.config.guild(ctx.guild).notify()
|
data = await self.config.guild(ctx.guild).all()
|
||||||
|
dj_role_obj = discord.utils.get(ctx.guild.roles, id=data['dj_role'])
|
||||||
|
dj_enabled = data['dj_enabled']
|
||||||
|
jukebox = data['jukebox']
|
||||||
|
jukebox_price = data['jukebox_price']
|
||||||
status = await self.config.status()
|
status = await self.config.status()
|
||||||
shuffle = await self.config.guild(ctx.guild).shuffle()
|
vote_percent = data['vote_percent']
|
||||||
repeat = await self.config.guild(ctx.guild).repeat()
|
msg = ('```ini\n'
|
||||||
|
'----Guild Settings----\n')
|
||||||
msg = '```ini\n'
|
if dj_enabled:
|
||||||
msg += '----Guild Settings----\n'
|
msg += 'DJ Role: [{}]\n'.format(dj_role_obj.name)
|
||||||
msg += 'audioset notify: [{}]\n'.format(notify)
|
if jukebox:
|
||||||
msg += 'audioset status: [{}]\n'.format(status)
|
msg += 'Jukebox: [{0}]\n'.format(jukebox)
|
||||||
msg += 'Repeat: [{}]\n'.format(repeat)
|
msg += 'Command price: [{0}]\n'.format(jukebox_price)
|
||||||
msg += 'Shuffle: [{}]\n'.format(shuffle)
|
msg += ('Repeat: [{repeat}]\n'
|
||||||
msg += '---Lavalink Settings---\n'
|
'Shuffle: [{shuffle}]\n'
|
||||||
msg += 'Cog version: {}\n```'.format(__version__)
|
'Song notify msgs: [{notify}]\n'
|
||||||
|
'Songs as status: [{0}]\n'.format(status, **data))
|
||||||
|
if vote_percent > 0:
|
||||||
|
msg += ('Vote skip: [{vote_enabled}]\n'
|
||||||
|
'Skip percentage: [{vote_percent}%]\n').format(**data)
|
||||||
|
msg += ('---Lavalink Settings---\n'
|
||||||
|
'Cog version: {}\n```'.format(__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)
|
||||||
|
|
||||||
@audioset.command()
|
@audioset.command()
|
||||||
|
@checks.mod_or_permissions(administrator=True)
|
||||||
|
async def vote(self, ctx, percent: int):
|
||||||
|
"""Percentage needed for non-mods to skip songs. 0 to disable."""
|
||||||
|
if percent < 0:
|
||||||
|
return await self._embed_msg(ctx, 'Can\'t be less than zero.')
|
||||||
|
elif percent > 100:
|
||||||
|
percent = 100
|
||||||
|
if percent == 0:
|
||||||
|
enabled = False
|
||||||
|
await self._embed_msg(ctx, 'Voting disabled. All users can use queue management commands.')
|
||||||
|
else:
|
||||||
|
enabled = True
|
||||||
|
await self._embed_msg(ctx, 'Vote percentage set to {}%.'.format(percent))
|
||||||
|
|
||||||
|
await self.config.guild(ctx.guild).vote_percent.set(percent)
|
||||||
|
await self.config.guild(ctx.guild).vote_enabled.set(enabled)
|
||||||
|
|
||||||
@checks.is_owner()
|
@checks.is_owner()
|
||||||
|
@audioset.command()
|
||||||
async def status(self, ctx):
|
async def status(self, ctx):
|
||||||
"""Enables/disables songs' titles as status."""
|
"""Enables/disables songs' titles as status."""
|
||||||
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()
|
await self._embed_msg(ctx, 'Song titles as status: {}.'.format(not 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):
|
||||||
@ -177,10 +263,16 @@ class Audio:
|
|||||||
@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."""
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
if not self._player_check(ctx):
|
if not self._player_check(ctx):
|
||||||
return await self._embed_msg(ctx, 'Nothing playing.')
|
return await self._embed_msg(ctx, 'Nothing playing.')
|
||||||
|
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
|
return await self._embed_msg(ctx, 'You must be in the voice channel to bump a song.')
|
||||||
|
if dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to bump songs.')
|
||||||
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.')
|
||||||
|
|
||||||
@ -193,16 +285,23 @@ 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."""
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
if self._player_check(ctx):
|
if self._player_check(ctx):
|
||||||
|
if dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to disconnect.')
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'There are other people listening to music.')
|
||||||
|
else:
|
||||||
await lavalink.get_player(ctx.guild.id).stop()
|
await lavalink.get_player(ctx.guild.id).stop()
|
||||||
await lavalink.get_player(ctx.guild.id).disconnect()
|
return await lavalink.get_player(ctx.guild.id).disconnect()
|
||||||
|
|
||||||
@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."""
|
||||||
if not self._player_check(ctx):
|
if not self._player_check(ctx):
|
||||||
return await self._embed_msg(ctx, 'Nothing playing.')
|
return await self._embed_msg(ctx, 'Nothing playing.')
|
||||||
expected = ['⏮', '⏹', '⏸', '⏭']
|
expected = ('⏮', '⏹', '⏸', '⏭')
|
||||||
emoji = {
|
emoji = {
|
||||||
'prev': '⏮',
|
'prev': '⏮',
|
||||||
'stop': '⏹',
|
'stop': '⏹',
|
||||||
@ -210,7 +309,6 @@ class Audio:
|
|||||||
'next': '⏭'
|
'next': '⏭'
|
||||||
}
|
}
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
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)
|
||||||
@ -235,20 +333,24 @@ class Audio:
|
|||||||
message = await ctx.send(embed=embed)
|
message = await ctx.send(embed=embed)
|
||||||
player.store('np_message', message)
|
player.store('np_message', message)
|
||||||
|
|
||||||
def check(r, u):
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
return r.message.id == message.id and u == ctx.message.author
|
vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
|
||||||
|
if dj_enabled or vote_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return
|
||||||
|
|
||||||
if player.current:
|
if player.current:
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
await message.add_reaction(expected[i])
|
await message.add_reaction(expected[i])
|
||||||
|
|
||||||
|
def check(r, u):
|
||||||
|
return r.message.id == message.id and u == ctx.message.author
|
||||||
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)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
return await self._clear_react(message)
|
return await self._clear_react(message)
|
||||||
|
|
||||||
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 == 'prev':
|
if react == 'prev':
|
||||||
await self._clear_react(message)
|
await self._clear_react(message)
|
||||||
await ctx.invoke(self.prev)
|
await ctx.invoke(self.prev)
|
||||||
@ -265,13 +367,19 @@ 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."""
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
if not self._player_check(ctx):
|
if not self._player_check(ctx):
|
||||||
return await self._embed_msg(ctx, 'Nothing playing.')
|
return await self._embed_msg(ctx, 'Nothing playing.')
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
if not ctx.author.voice or ctx.author.voice.channel != player.channel:
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
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 dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to pause songs.')
|
||||||
|
|
||||||
if player.current and not player.paused:
|
command = ctx.invoked_with
|
||||||
|
if player.current and not player.paused and command == 'pause':
|
||||||
await player.pause()
|
await player.pause()
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
colour=ctx.guild.me.top_role.colour, title='Track Paused',
|
colour=ctx.guild.me.top_role.colour, title='Track Paused',
|
||||||
@ -282,7 +390,7 @@ class Audio:
|
|||||||
)
|
)
|
||||||
return await ctx.send(embed=embed)
|
return await ctx.send(embed=embed)
|
||||||
|
|
||||||
if player.paused:
|
if player.paused and command == 'resume':
|
||||||
await player.pause(False)
|
await player.pause(False)
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
colour=ctx.guild.me.top_role.colour,
|
colour=ctx.guild.me.top_role.colour,
|
||||||
@ -294,6 +402,10 @@ class Audio:
|
|||||||
)
|
)
|
||||||
return await ctx.send(embed=embed)
|
return await ctx.send(embed=embed)
|
||||||
|
|
||||||
|
if player.paused and command == 'pause':
|
||||||
|
return await self._embed_msg(ctx, 'Track is paused.')
|
||||||
|
if player.current and command == 'resume':
|
||||||
|
return await self._embed_msg(ctx, 'Track is playing.')
|
||||||
await self._embed_msg(ctx, 'Nothing playing.')
|
await self._embed_msg(ctx, 'Nothing playing.')
|
||||||
|
|
||||||
@commands.command()
|
@commands.command()
|
||||||
@ -303,7 +415,6 @@ class Audio:
|
|||||||
return await self._embed_msg(ctx, 'Nothing playing.')
|
return await self._embed_msg(ctx, 'Nothing playing.')
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
queue_tracks = player.queue
|
queue_tracks = player.queue
|
||||||
queue_len = len(queue_tracks)
|
|
||||||
requesters = {'total': 0, 'users': {}}
|
requesters = {'total': 0, 'users': {}}
|
||||||
|
|
||||||
async def _usercount(req_username):
|
async def _usercount(req_username):
|
||||||
@ -340,17 +451,28 @@ 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."""
|
||||||
if not ctx.author.voice:
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
return await self._embed_msg(ctx, 'You must be in the voice channel to use the play command.')
|
jukebox_price = await self.config.guild(ctx.guild).jukebox_price()
|
||||||
|
shuffle = await self.config.guild(ctx.guild).shuffle()
|
||||||
if not self._player_check(ctx):
|
if not self._player_check(ctx):
|
||||||
|
try:
|
||||||
await lavalink.connect(ctx.author.voice.channel)
|
await lavalink.connect(ctx.author.voice.channel)
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
player.store('connect', datetime.datetime.utcnow())
|
player.store('connect', datetime.datetime.utcnow())
|
||||||
|
except AttributeError:
|
||||||
|
return await self._embed_msg(ctx, 'Connect to a voice channel first.')
|
||||||
|
if dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to queue songs.')
|
||||||
|
if not await self._currency_check(ctx, jukebox_price):
|
||||||
|
return
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
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 ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
|
return await self._embed_msg(ctx, 'You must be in the voice channel to use the play command.')
|
||||||
|
|
||||||
query = query.strip('<>')
|
query = query.strip('<>')
|
||||||
if not query.startswith('http'):
|
if not query.startswith('http'):
|
||||||
@ -388,9 +510,14 @@ class Audio:
|
|||||||
"""Skips to the start of the previously played track."""
|
"""Skips to the start of the previously played track."""
|
||||||
if not self._player_check(ctx):
|
if not self._player_check(ctx):
|
||||||
return await self._embed_msg(ctx, 'Nothing playing.')
|
return await self._embed_msg(ctx, 'Nothing playing.')
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
player = lavalink.get_player(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()
|
||||||
if not ctx.author.voice or ctx.author.voice.channel != player.channel:
|
if dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to skip songs.')
|
||||||
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
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.')
|
||||||
@ -459,7 +586,6 @@ class Audio:
|
|||||||
|
|
||||||
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) + 1, queue_total_duration)
|
text = 'Page {}/{} | {} tracks, {} remaining'.format(page, pages, len(player.queue) + 1, queue_total_duration)
|
||||||
@ -473,29 +599,36 @@ class Audio:
|
|||||||
@commands.command()
|
@commands.command()
|
||||||
async def repeat(self, ctx):
|
async def repeat(self, ctx):
|
||||||
"""Toggles repeat."""
|
"""Toggles repeat."""
|
||||||
repeat_msg = 'You must be in the voice channel to toggle repeat.'
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
if not ctx.author.voice:
|
if dj_enabled:
|
||||||
return await self._embed_msg(ctx, repeat_msg)
|
if not await self._can_instaskip(ctx, ctx.author) and not await self._has_dj_role(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to toggle repeat.')
|
||||||
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()
|
||||||
await self._embed_msg(ctx, 'Repeat songs: {}.'.format(repeat))
|
|
||||||
|
|
||||||
if self._player_check(ctx):
|
if self._player_check(ctx):
|
||||||
await self._data_check(ctx)
|
await self._data_check(ctx)
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
if ctx.author.voice.channel != player.channel:
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
return await self._embed_msg(ctx, repeat_msg)
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
|
return await self._embed_msg(ctx, 'You must be in the voice channel to toggle repeat.')
|
||||||
|
await self._embed_msg(ctx, 'Repeat songs: {}.'.format(repeat))
|
||||||
|
|
||||||
@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."""
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
if not self._player_check(ctx):
|
if not self._player_check(ctx):
|
||||||
return await self._embed_msg(ctx, 'Nothing playing.')
|
return await self._embed_msg(ctx, 'Nothing playing.')
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
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 dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to remove songs.')
|
||||||
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
|
return await self._embed_msg(ctx, 'You must be in the voice channel to manage the queue.')
|
||||||
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 -= 1
|
||||||
@ -507,7 +640,7 @@ 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⃣",
|
||||||
@ -515,17 +648,19 @@ class Audio:
|
|||||||
"four": "4⃣",
|
"four": "4⃣",
|
||||||
"five": "5⃣"
|
"five": "5⃣"
|
||||||
}
|
}
|
||||||
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):
|
if not self._player_check(ctx):
|
||||||
|
try:
|
||||||
await lavalink.connect(ctx.author.voice.channel)
|
await lavalink.connect(ctx.author.voice.channel)
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
player.store('connect', datetime.datetime.utcnow())
|
player.store('connect', datetime.datetime.utcnow())
|
||||||
|
except AttributeError:
|
||||||
|
return await self._embed_msg(ctx, 'Connect to a voice channel first.')
|
||||||
player = lavalink.get_player(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()
|
||||||
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 ctx.author.voice.channel != player.channel) and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
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.')
|
||||||
|
|
||||||
query = query.strip('<>')
|
query = query.strip('<>')
|
||||||
@ -552,6 +687,10 @@ class Audio:
|
|||||||
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)))
|
||||||
message = await ctx.send(embed=embed)
|
message = await ctx.send(embed=embed)
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
|
if dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return
|
||||||
|
|
||||||
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
|
||||||
@ -584,8 +723,11 @@ class Audio:
|
|||||||
|
|
||||||
async def _search_button(self, ctx, message, tracks, entry: int):
|
async def _search_button(self, ctx, message, tracks, entry: int):
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
|
jukebox_price = await self.config.guild(ctx.guild).jukebox_price()
|
||||||
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)
|
||||||
|
if not await self._currency_check(ctx, jukebox_price):
|
||||||
|
return
|
||||||
search_choice = tracks[entry]
|
search_choice = tracks[entry]
|
||||||
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(search_choice.title, search_choice.uri))
|
description='**[{}]({})**'.format(search_choice.title, search_choice.uri))
|
||||||
@ -601,11 +743,16 @@ class Audio:
|
|||||||
@commands.command()
|
@commands.command()
|
||||||
async def seek(self, ctx, seconds: int=30):
|
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."""
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
if not self._player_check(ctx):
|
if not self._player_check(ctx):
|
||||||
return await self._embed_msg(ctx, 'Nothing playing.')
|
return await self._embed_msg(ctx, 'Nothing playing.')
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
if not ctx.author.voice or ctx.author.voice.channel != player.channel:
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
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 dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to use seek.')
|
||||||
if player.current:
|
if player.current:
|
||||||
if player.current.is_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.')
|
||||||
@ -623,32 +770,105 @@ class Audio:
|
|||||||
@commands.command()
|
@commands.command()
|
||||||
async def shuffle(self, ctx):
|
async def shuffle(self, ctx):
|
||||||
"""Toggles shuffle."""
|
"""Toggles shuffle."""
|
||||||
shuffle_msg = 'You must be in the voice channel to toggle shuffle.'
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
if not ctx.author.voice:
|
if dj_enabled:
|
||||||
return await self._embed_msg(ctx, shuffle_msg)
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to toggle shuffle.')
|
||||||
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()
|
||||||
await self._embed_msg(ctx, 'Shuffle songs: {}.'.format(shuffle))
|
|
||||||
|
|
||||||
if self._player_check(ctx):
|
if self._player_check(ctx):
|
||||||
await self._data_check(ctx)
|
await self._data_check(ctx)
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
if ctx.author.voice.channel != player.channel:
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
return await self._embed_msg(ctx, shuffle_msg)
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
|
return await self._embed_msg(ctx, 'You must be in the voice channel to toggle shuffle.')
|
||||||
|
await self._embed_msg(ctx, 'Shuffle songs: {}.'.format(shuffle))
|
||||||
|
|
||||||
@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."""
|
||||||
if not self._player_check(ctx):
|
if not self._player_check(ctx):
|
||||||
return await self._embed_msg(ctx, 'Nothing playing.')
|
return await self._embed_msg(ctx, 'Nothing playing.')
|
||||||
else:
|
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
|
return await self._embed_msg(ctx, 'You must be in the voice channel to skip the music.')
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
|
vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
|
||||||
|
if dj_enabled and not vote_enabled and not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to skip songs.')
|
||||||
|
if vote_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
if ctx.author.id in self.skip_votes[ctx.message.guild]:
|
||||||
|
self.skip_votes[ctx.message.guild].remove(ctx.author.id)
|
||||||
|
reply = "I removed your vote to skip."
|
||||||
|
else:
|
||||||
|
self.skip_votes[ctx.message.guild].append(ctx.author.id)
|
||||||
|
reply = "You voted to skip."
|
||||||
|
|
||||||
if not player.current:
|
num_votes = len(self.skip_votes[ctx.message.guild])
|
||||||
return await self._embed_msg(ctx, 'There\'s nothing in the queue.')
|
vote_mods = []
|
||||||
|
for member in player.channel.members:
|
||||||
|
can_skip = await self._can_instaskip(ctx, member)
|
||||||
|
if can_skip:
|
||||||
|
vote_mods.append(member)
|
||||||
|
num_members = len(player.channel.members) - len(vote_mods)
|
||||||
|
vote = int(100 * num_votes / num_members)
|
||||||
|
percent = await self.config.guild(ctx.guild).vote_percent()
|
||||||
|
if vote >= percent:
|
||||||
|
self.skip_votes[ctx.message.guild] = []
|
||||||
|
await self._embed_msg(ctx, "Vote threshold met.")
|
||||||
|
return await self._skip_action(ctx)
|
||||||
|
else:
|
||||||
|
reply += " Votes: %d/%d" % (num_votes, num_members)
|
||||||
|
reply += " (%d%% out of %d%% needed)" % (vote, percent)
|
||||||
|
return await self._embed_msg(ctx, reply)
|
||||||
|
else:
|
||||||
|
return await self._skip_action(ctx)
|
||||||
|
else:
|
||||||
|
return await self._skip_action(ctx)
|
||||||
|
|
||||||
|
async def _can_instaskip(self, ctx, member):
|
||||||
|
mod_role = await ctx.bot.db.guild(ctx.guild).mod_role()
|
||||||
|
admin_role = await ctx.bot.db.guild(ctx.guild).admin_role()
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
|
|
||||||
|
if dj_enabled:
|
||||||
|
is_active_dj = await self._has_dj_role(ctx, member)
|
||||||
|
else:
|
||||||
|
is_active_dj = False
|
||||||
|
is_owner = member.id == self.bot.owner_id
|
||||||
|
is_server_owner = member.id == ctx.guild.owner_id
|
||||||
|
is_coowner = any(x == member.id for x in self.bot._co_owners)
|
||||||
|
is_admin = discord.utils.get(ctx.guild.get_member(member.id).roles, id=admin_role) is not None
|
||||||
|
is_mod = discord.utils.get(ctx.guild.get_member(member.id).roles, id=mod_role) is not None
|
||||||
|
is_bot = member.bot is True
|
||||||
|
try:
|
||||||
|
nonbots = sum(not m.bot for m in ctx.guild.get_member(member.id).voice.channel.members)
|
||||||
|
except AttributeError:
|
||||||
|
if ctx.guild.get_member(self.bot.user.id).voice is not None:
|
||||||
|
nonbots = sum(not m.bot for m in ctx.guild.get_member(self.bot.user.id).voice.channel.members)
|
||||||
|
if nonbots == 1:
|
||||||
|
nonbots = 2
|
||||||
|
else:
|
||||||
|
nonbots = 2
|
||||||
|
alone = nonbots <= 1
|
||||||
|
|
||||||
|
return is_active_dj or is_owner or is_server_owner or is_coowner or is_admin or is_mod or is_bot or alone
|
||||||
|
|
||||||
|
async def _has_dj_role(self, ctx, member):
|
||||||
|
dj_role_id = await self.config.guild(ctx.guild).dj_role()
|
||||||
|
dj_role_obj = discord.utils.get(ctx.guild.roles, id=dj_role_id)
|
||||||
|
if dj_role_obj in ctx.guild.get_member(member.id).roles:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def _skip_action(ctx):
|
||||||
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
if not player.queue:
|
if not player.queue:
|
||||||
pos, dur = player.position, player.current.length
|
pos, dur = player.position, player.current.length
|
||||||
time_remain = lavalink.utils.format_time(dur - pos)
|
time_remain = lavalink.utils.format_time(dur - pos)
|
||||||
@ -660,9 +880,6 @@ class Audio:
|
|||||||
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)
|
||||||
|
|
||||||
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.')
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
colour=ctx.guild.me.top_role.colour, title='Track Skipped',
|
colour=ctx.guild.me.top_role.colour, title='Track Skipped',
|
||||||
description='**[{}]({})**'.format(
|
description='**[{}]({})**'.format(
|
||||||
@ -670,17 +887,25 @@ class Audio:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
await ctx.send(embed=embed)
|
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."""
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
|
vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
|
||||||
if not self._player_check(ctx):
|
if not self._player_check(ctx):
|
||||||
return await self._embed_msg(ctx, 'Nothing playing.')
|
return await self._embed_msg(ctx, 'Nothing playing.')
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
if not ctx.author.voice or ctx.author.voice.channel != player.channel:
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
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 vote_enabled or vote_enabled and dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'There are other people listening - vote to skip instead.')
|
||||||
|
if dj_enabled and not vote_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to stop the music.')
|
||||||
if player.is_playing:
|
if player.is_playing:
|
||||||
await self._embed_msg(ctx, 'Stopping...')
|
await self._embed_msg(ctx, 'Stopping...')
|
||||||
await player.stop()
|
await player.stop()
|
||||||
@ -692,6 +917,7 @@ class Audio:
|
|||||||
@commands.command()
|
@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%."""
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
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:',
|
||||||
@ -699,14 +925,22 @@ class Audio:
|
|||||||
if not self._player_check(ctx):
|
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 self._player_check(ctx):
|
||||||
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
|
return await self._embed_msg(ctx, 'You must be in the voice channel to change the volume.')
|
||||||
|
if dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author) and not await self._has_dj_role(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to change the volume.')
|
||||||
if 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)
|
||||||
if self._player_check:
|
if self._player_check(ctx):
|
||||||
await lavalink.get_player(ctx.guild.id).set_volume(vol)
|
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)
|
||||||
if self._player_check:
|
if self._player_check(ctx):
|
||||||
await lavalink.get_player(ctx.guild.id).set_volume(vol)
|
await lavalink.get_player(ctx.guild.id).set_volume(vol)
|
||||||
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Volume:',
|
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Volume:',
|
||||||
description=str(vol) + '%')
|
description=str(vol) + '%')
|
||||||
@ -725,36 +959,46 @@ class Audio:
|
|||||||
async def host(self, ctx, host):
|
async def host(self, ctx, host):
|
||||||
"""Set the lavalink server host."""
|
"""Set the lavalink server host."""
|
||||||
await self.config.host.set(host)
|
await self.config.host.set(host)
|
||||||
get_host = await self.config.host()
|
await self._embed_msg(ctx, 'Host set to {}.'.format(host))
|
||||||
await self._embed_msg(ctx, 'Host set to {}.'.format(get_host))
|
|
||||||
|
|
||||||
@llsetup.command()
|
@llsetup.command()
|
||||||
async def password(self, ctx, passw):
|
async def password(self, ctx, passw):
|
||||||
"""Set the lavalink server password."""
|
"""Set the lavalink server password."""
|
||||||
await self.config.passw.set(str(passw))
|
await self.config.passw.set(str(passw))
|
||||||
get_passw = await self.config.passw()
|
await self._embed_msg(ctx, 'Server password set to {}.'.format(passw))
|
||||||
await self._embed_msg(ctx, 'Server password set to {}.'.format(get_passw))
|
|
||||||
|
|
||||||
@llsetup.command()
|
@llsetup.command()
|
||||||
async def restport(self, ctx, rest_port):
|
async def restport(self, ctx, rest_port):
|
||||||
"""Set the lavalink REST server port."""
|
"""Set the lavalink REST server port."""
|
||||||
await self.config.rest_port.set(str(rest_port))
|
await self.config.rest_port.set(str(rest_port))
|
||||||
get_rest_port = await self.config.rest_port()
|
await self._embed_msg(ctx, 'REST port set to {}.'.format(rest_port))
|
||||||
await self._embed_msg(ctx, 'REST port set to {}.'.format(get_rest_port))
|
|
||||||
|
|
||||||
@llsetup.command()
|
@llsetup.command()
|
||||||
async def wsport(self, ctx, rest_port):
|
async def wsport(self, ctx, rest_port):
|
||||||
"""Set the lavalink websocket server port."""
|
"""Set the lavalink websocket server port."""
|
||||||
await self.config.ws_port.set(str(ws_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(ws_port))
|
||||||
await self._embed_msg(ctx, 'Websocket port set to {}.'.format(get_ws_port))
|
|
||||||
|
|
||||||
async def _clear_react(self, message):
|
@staticmethod
|
||||||
|
async def _clear_react(message):
|
||||||
try:
|
try:
|
||||||
await message.clear_reactions()
|
await message.clear_reactions()
|
||||||
except:
|
except (discord.Forbidden, discord.HTTPException):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
async def _currency_check(self, ctx, jukebox_price: int):
|
||||||
|
jukebox = await self.config.guild(ctx.guild).jukebox()
|
||||||
|
if jukebox and not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
try:
|
||||||
|
await bank.withdraw_credits(ctx.author, jukebox_price)
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
credits_name = await bank.get_currency_name(ctx.guild)
|
||||||
|
await self._embed_msg(ctx, 'Not enough {} ({} required).'.format(credits_name, jukebox_price))
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
async def _data_check(self, ctx):
|
async def _data_check(self, ctx):
|
||||||
player = lavalink.get_player(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()
|
||||||
@ -787,7 +1031,8 @@ class Audio:
|
|||||||
msg += bar
|
msg += bar
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def _dynamic_time(self, time):
|
@staticmethod
|
||||||
|
def _dynamic_time(time):
|
||||||
m, s = divmod(time, 60)
|
m, s = divmod(time, 60)
|
||||||
h, m = divmod(m, 60)
|
h, m = divmod(m, 60)
|
||||||
d, h = divmod(h, 24)
|
d, h = divmod(h, 24)
|
||||||
@ -800,9 +1045,12 @@ class Audio:
|
|||||||
msg = "{2}m {3}s"
|
msg = "{2}m {3}s"
|
||||||
elif d == 0 and h == 0 and m == 0 and s > 0:
|
elif d == 0 and h == 0 and m == 0 and s > 0:
|
||||||
msg = "{3}s"
|
msg = "{3}s"
|
||||||
|
else:
|
||||||
|
msg = ""
|
||||||
return msg.format(d, h, m, s)
|
return msg.format(d, h, m, s)
|
||||||
|
|
||||||
async def _embed_msg(self, ctx, title):
|
@staticmethod
|
||||||
|
async def _embed_msg(ctx, title):
|
||||||
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)
|
||||||
|
|
||||||
@ -813,14 +1061,15 @@ class Audio:
|
|||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
async def _queue_duration(self, ctx):
|
@staticmethod
|
||||||
|
async def _queue_duration(ctx):
|
||||||
player = lavalink.get_player(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].is_stream:
|
if not player.queue[i].is_stream:
|
||||||
duration.append(player.queue[i].length)
|
duration.append(player.queue[i].length)
|
||||||
queue_duration = sum(duration)
|
queue_duration = sum(duration)
|
||||||
if player.queue == []:
|
if not player.queue:
|
||||||
queue_duration = 0
|
queue_duration = 0
|
||||||
try:
|
try:
|
||||||
if not player.current.is_stream:
|
if not player.current.is_stream:
|
||||||
@ -832,13 +1081,21 @@ 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):
|
@staticmethod
|
||||||
|
def _player_check(ctx):
|
||||||
try:
|
try:
|
||||||
lavalink.get_player(ctx.guild.id)
|
lavalink.get_player(ctx.guild.id)
|
||||||
return True
|
return True
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
async def on_voice_state_update(self, member, before, after):
|
||||||
|
if after.channel != before.channel:
|
||||||
|
try:
|
||||||
|
self.skip_votes[before.channel.guild].remove(member.id)
|
||||||
|
except (ValueError, KeyError, AttributeError):
|
||||||
|
pass
|
||||||
|
|
||||||
def __unload(self):
|
def __unload(self):
|
||||||
lavalink.unregister_event_listener(self.event_handler)
|
lavalink.unregister_event_listener(self.event_handler)
|
||||||
self.bot.loop.create_task(lavalink.close())
|
self.bot.loop.create_task(lavalink.close())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user