mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 11:18:54 -05:00
Playlist additions and cleanup (#1579)
Add playlist append, create, remove, and upload.
This commit is contained in:
parent
d61827b92c
commit
79676c4f72
@ -1,16 +1,18 @@
|
|||||||
|
import aiohttp
|
||||||
import asyncio
|
import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
import discord
|
import discord
|
||||||
import heapq
|
import heapq
|
||||||
import lavalink
|
import lavalink
|
||||||
import math
|
import math
|
||||||
|
import re
|
||||||
import redbot.core
|
import redbot.core
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from redbot.core import Config, checks, bank
|
from redbot.core import Config, checks, bank
|
||||||
|
|
||||||
from .manager import shutdown_lavalink_server
|
from .manager import shutdown_lavalink_server
|
||||||
|
|
||||||
__version__ = "0.0.5"
|
__version__ = "0.0.5a"
|
||||||
__author__ = ["aikaterna", "billy/bollo/ati"]
|
__author__ = ["aikaterna", "billy/bollo/ati"]
|
||||||
|
|
||||||
|
|
||||||
@ -46,6 +48,7 @@ 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.skip_votes = {}
|
self.skip_votes = {}
|
||||||
|
self.session = aiohttp.ClientSession()
|
||||||
|
|
||||||
async def init_config(self):
|
async def init_config(self):
|
||||||
host = await self.config.host()
|
host = await self.config.host()
|
||||||
@ -96,10 +99,11 @@ class Audio:
|
|||||||
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,
|
await self.bot.change_presence(activity=discord.Activity(name=get_single_title,
|
||||||
type=discord.ActivityType.listening))
|
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),
|
await self.bot.change_presence(
|
||||||
type=discord.ActivityType.playing))
|
activity=discord.Activity(name='music in {} servers'.format(playing_servers),
|
||||||
|
type=discord.ActivityType.playing))
|
||||||
|
|
||||||
if event_type == lavalink.LavalinkEvents.QUEUE_END and notify:
|
if event_type == lavalink.LavalinkEvents.QUEUE_END and notify:
|
||||||
notify_channel = player.fetch('channel')
|
notify_channel = player.fetch('channel')
|
||||||
@ -113,10 +117,11 @@ class Audio:
|
|||||||
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,
|
await self.bot.change_presence(activity=discord.Activity(name=get_single_title,
|
||||||
type=discord.ActivityType.listening))
|
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),
|
await self.bot.change_presence(
|
||||||
type=discord.ActivityType.playing))
|
activity=discord.Activity(name='music in {} servers'.format(playing_servers),
|
||||||
|
type=discord.ActivityType.playing))
|
||||||
|
|
||||||
if event_type == lavalink.LavalinkEvents.TRACK_EXCEPTION:
|
if event_type == lavalink.LavalinkEvents.TRACK_EXCEPTION:
|
||||||
message_channel = player.fetch('channel')
|
message_channel = player.fetch('channel')
|
||||||
@ -124,7 +129,7 @@ class Audio:
|
|||||||
message_channel = self.bot.get_channel(message_channel)
|
message_channel = self.bot.get_channel(message_channel)
|
||||||
embed = discord.Embed(colour=message_channel.guild.me.top_role.colour, title='Track Error',
|
embed = discord.Embed(colour=message_channel.guild.me.top_role.colour, title='Track Error',
|
||||||
description='{}\n**[{}]({})**'.format(extra, player.current.title,
|
description='{}\n**[{}]({})**'.format(extra, player.current.title,
|
||||||
player.current.uri))
|
player.current.uri))
|
||||||
embed.set_footer(text='Skipping...')
|
embed.set_footer(text='Skipping...')
|
||||||
await message_channel.send(embed=embed)
|
await message_channel.send(embed=embed)
|
||||||
await player.skip()
|
await player.skip()
|
||||||
@ -143,7 +148,6 @@ class Audio:
|
|||||||
dj_role_id = await self.config.guild(ctx.guild).dj_role()
|
dj_role_id = await self.config.guild(ctx.guild).dj_role()
|
||||||
if dj_role_id is None:
|
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.')
|
await self._embed_msg(ctx, 'Please set a role to use with DJ mode. Enter the role name now.')
|
||||||
|
|
||||||
def check(m):
|
def check(m):
|
||||||
return m.author == ctx.author
|
return m.author == ctx.author
|
||||||
try:
|
try:
|
||||||
@ -172,8 +176,6 @@ class Audio:
|
|||||||
@checks.mod_or_permissions(administrator=True)
|
@checks.mod_or_permissions(administrator=True)
|
||||||
async def jukebox(self, ctx, price: int):
|
async def jukebox(self, ctx, price: int):
|
||||||
"""Set a price for queueing songs for non-mods. 0 to disable."""
|
"""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:
|
if price < 0:
|
||||||
return await self._embed_msg(ctx, 'Can\'t be less than zero.')
|
return await self._embed_msg(ctx, 'Can\'t be less than zero.')
|
||||||
if price == 0:
|
if price == 0:
|
||||||
@ -182,7 +184,7 @@ class Audio:
|
|||||||
else:
|
else:
|
||||||
jukebox = True
|
jukebox = True
|
||||||
await self._embed_msg(ctx, 'Track queueing command price set to {} {}.'.format(
|
await self._embed_msg(ctx, 'Track queueing command price set to {} {}.'.format(
|
||||||
price, await bank.get_currency_name(ctx.guild)))
|
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_price.set(price)
|
||||||
await self.config.guild(ctx.guild).jukebox.set(jukebox)
|
await self.config.guild(ctx.guild).jukebox.set(jukebox)
|
||||||
@ -266,10 +268,10 @@ class Audio:
|
|||||||
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()))
|
||||||
try:
|
try:
|
||||||
server_list.append('{} [`{}`]: **[{}]({})**'.format(p.channel.guild.name, connect_dur,
|
server_list.append('{} [`{}`]: **[{}]({})**'.format(p.channel.guild.name, connect_dur,
|
||||||
p.current.title, p.current.uri))
|
p.current.title, p.current.uri))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
server_list.append('{} [`{}`]: **{}**'.format(p.channel.guild.name, connect_dur,
|
server_list.append('{} [`{}`]: **{}**'.format(p.channel.guild.name, connect_dur,
|
||||||
'Nothing playing.'))
|
'Nothing playing.'))
|
||||||
if server_num == 0:
|
if server_num == 0:
|
||||||
servers = 'Not connected anywhere.'
|
servers = 'Not connected anywhere.'
|
||||||
else:
|
else:
|
||||||
@ -286,7 +288,7 @@ 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)
|
||||||
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
return await self._embed_msg(ctx, 'You must be in the voice channel to bump a song.')
|
return await self._embed_msg(ctx, 'You must be in the voice channel to bump a song.')
|
||||||
if dj_enabled:
|
if dj_enabled:
|
||||||
if not await self._can_instaskip(ctx, ctx.author):
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
@ -363,6 +365,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
|
||||||
|
|
||||||
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:
|
||||||
@ -390,7 +393,7 @@ 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)
|
||||||
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
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 dj_enabled:
|
||||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx, ctx.author):
|
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx, ctx.author):
|
||||||
@ -487,11 +490,13 @@ class Audio:
|
|||||||
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
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
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.')
|
return await self._embed_msg(ctx, 'You must be in the voice channel to use the play command.')
|
||||||
if not await self._currency_check(ctx, jukebox_price):
|
if not await self._currency_check(ctx, jukebox_price):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not query:
|
||||||
|
return await self._embed_msg(ctx, 'No songs to play.')
|
||||||
query = query.strip('<>')
|
query = query.strip('<>')
|
||||||
if not query.startswith('http'):
|
if not query.startswith('http'):
|
||||||
query = 'ytsearch:{}'.format(query)
|
query = 'ytsearch:{}'.format(query)
|
||||||
@ -510,7 +515,8 @@ class Audio:
|
|||||||
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: starts at #{} in queue'.format(queue_total_duration, before_queue_length))
|
embed.set_footer(text='{} until start of playlist playback: starts at #{} in queue'.format(
|
||||||
|
queue_total_duration, before_queue_length))
|
||||||
if not player.current:
|
if not player.current:
|
||||||
await player.play()
|
await player.play()
|
||||||
else:
|
else:
|
||||||
@ -519,7 +525,8 @@ class Audio:
|
|||||||
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(single_track.title, single_track.uri))
|
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: #{} in queue'.format(queue_total_duration, before_queue_length))
|
embed.set_footer(text='{} until track playback: #{} in queue'.format(
|
||||||
|
queue_total_duration, before_queue_length))
|
||||||
if not player.current:
|
if not player.current:
|
||||||
await player.play()
|
await player.play()
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
@ -531,17 +538,60 @@ class Audio:
|
|||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
await ctx.send_help()
|
await ctx.send_help()
|
||||||
|
|
||||||
|
@playlist.command(name='append')
|
||||||
|
async def _playlist_append(self, ctx, playlist_name, *url):
|
||||||
|
"""Add a song URL, playlist link, or quick search to the end of a saved playlist."""
|
||||||
|
if not await self._playlist_check(ctx):
|
||||||
|
return
|
||||||
|
async with self.config.guild(ctx.guild).playlists() as playlists:
|
||||||
|
try:
|
||||||
|
if (playlists[playlist_name]['author'] != ctx.author.id and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
|
return await self._embed_msg(ctx, 'You are not the author of that playlist.')
|
||||||
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
|
to_append = await self._playlist_tracks(ctx, player, url)
|
||||||
|
if not to_append:
|
||||||
|
return
|
||||||
|
track_list = playlists[playlist_name]['tracks']
|
||||||
|
if track_list:
|
||||||
|
playlists[playlist_name]['tracks'] = track_list + to_append
|
||||||
|
else:
|
||||||
|
playlists[playlist_name]['tracks'] = to_append
|
||||||
|
except KeyError:
|
||||||
|
return await self._embed_msg(ctx, 'No playlist with that name.')
|
||||||
|
if playlists[playlist_name]['playlist_url'] is not None:
|
||||||
|
playlists[playlist_name]['playlist_url'] = None
|
||||||
|
if len(to_append) == 1:
|
||||||
|
track_title = to_append[0]['info']['title']
|
||||||
|
return await self._embed_msg(ctx, '{} appended to {}.'.format(track_title, playlist_name))
|
||||||
|
await self._embed_msg(ctx, '{} tracks appended to {}.'.format(len(to_append), playlist_name))
|
||||||
|
|
||||||
|
@playlist.command(name='create')
|
||||||
|
async def _playlist_create(self, ctx, playlist_name):
|
||||||
|
"""Create an empty playlist."""
|
||||||
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
|
if dj_enabled:
|
||||||
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
return await self._embed_msg(ctx, 'You need the DJ role to save playlists.')
|
||||||
|
async with self.config.guild(ctx.guild).playlists() as playlists:
|
||||||
|
if playlist_name in playlists:
|
||||||
|
return await self._embed_msg(ctx, 'Playlist name already exists, try again with a different name.')
|
||||||
|
playlist_list = self._to_json(ctx, None, None)
|
||||||
|
playlists[playlist_name] = playlist_list
|
||||||
|
await self._embed_msg(ctx, 'Empty playlist {} created.'.format(playlist_name))
|
||||||
|
|
||||||
@playlist.command(name='delete')
|
@playlist.command(name='delete')
|
||||||
async def _playlist_delete(self, ctx, playlist_name):
|
async def _playlist_delete(self, ctx, playlist_name):
|
||||||
"""Delete a saved playlist."""
|
"""Delete a saved playlist."""
|
||||||
async with self.config.guild(ctx.guild).playlists() as playlists:
|
async with self.config.guild(ctx.guild).playlists() as playlists:
|
||||||
try:
|
try:
|
||||||
if playlists[playlist_name]['author'] != ctx.author.id and not await self._can_instaskip(ctx, ctx.author):
|
if (playlists[playlist_name]['author'] != ctx.author.id and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
return await self._embed_msg(ctx, 'You are not the author of that playlist.')
|
return await self._embed_msg(ctx, 'You are not the author of that playlist.')
|
||||||
del playlists[playlist_name]
|
del playlists[playlist_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return await self._embed_msg(ctx, 'No playlist with that name.')
|
return await self._embed_msg(ctx, 'No playlist with that name.')
|
||||||
await self._embed_msg(ctx, '{} playlist removed.'.format(playlist_name))
|
await self._embed_msg(ctx, '{} playlist deleted.'.format(playlist_name))
|
||||||
|
|
||||||
@playlist.command(name='info')
|
@playlist.command(name='info')
|
||||||
async def _playlist_info(self, ctx, playlist_name):
|
async def _playlist_info(self, ctx, playlist_name):
|
||||||
@ -556,18 +606,15 @@ class Audio:
|
|||||||
try:
|
try:
|
||||||
track_len = len(playlists[playlist_name]['tracks'])
|
track_len = len(playlists[playlist_name]['tracks'])
|
||||||
except TypeError:
|
except TypeError:
|
||||||
track_len = 1
|
track_len = 0
|
||||||
if playlist_url is None:
|
if playlist_url is None:
|
||||||
playlist_url = '**Not generated from a URL.**'
|
playlist_url = '**Custom playlist.**'
|
||||||
else:
|
else:
|
||||||
playlist_url = 'URL: <{}>'.format(playlist_url)
|
playlist_url = 'URL: <{}>'.format(playlist_url)
|
||||||
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Playlist info for {}:'.format(playlist_name),
|
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Playlist info for {}:'.format(playlist_name),
|
||||||
description='Author: **{}**\n{}'.format(author_obj,
|
description='Author: **{}**\n{}'.format(author_obj,
|
||||||
playlist_url))
|
playlist_url))
|
||||||
if track_len > 1:
|
embed.set_footer(text='{} track(s)'.format(track_len))
|
||||||
embed.set_footer(text='{} tracks'.format(track_len))
|
|
||||||
if track_len == 1:
|
|
||||||
embed.set_footer(text='{} track'.format(track_len))
|
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
@playlist.command(name='list')
|
@playlist.command(name='list')
|
||||||
@ -597,11 +644,11 @@ 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)
|
||||||
tracklist = []
|
tracklist = []
|
||||||
np_song = self._track_creator(ctx, player, 'np', None)
|
np_song = self._track_creator(player, 'np')
|
||||||
tracklist.append(np_song)
|
tracklist.append(np_song)
|
||||||
for track in player.queue:
|
for track in player.queue:
|
||||||
queue_idx = player.queue.index(track)
|
queue_idx = player.queue.index(track)
|
||||||
track_obj = self._track_creator(ctx, player, queue_idx, None)
|
track_obj = self._track_creator(player, queue_idx)
|
||||||
tracklist.append(track_obj)
|
tracklist.append(track_obj)
|
||||||
if not playlist_name:
|
if not playlist_name:
|
||||||
await self._embed_msg(ctx, 'Please enter a name for this playlist.')
|
await self._embed_msg(ctx, 'Please enter a name for this playlist.')
|
||||||
@ -616,11 +663,38 @@ class Audio:
|
|||||||
return await self._embed_msg(ctx, 'Playlist name already exists, try again with a different name.')
|
return await self._embed_msg(ctx, 'Playlist name already exists, try again with a different name.')
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
return await self._embed_msg(ctx, 'No playlist name entered, try again later.')
|
return await self._embed_msg(ctx, 'No playlist name entered, try again later.')
|
||||||
|
playlist_list = self._to_json(ctx, None, tracklist)
|
||||||
playlist_list = self._to_json(ctx, None, tracklist, playlist_name)
|
|
||||||
async with self.config.guild(ctx.guild).playlists() as playlists:
|
async with self.config.guild(ctx.guild).playlists() as playlists:
|
||||||
playlists[playlist_name] = playlist_list
|
playlists[playlist_name] = playlist_list
|
||||||
await self._embed_msg(ctx, 'Playlist {} saved from current queue: {} tracks added.'.format(playlist_name, len(tracklist)))
|
await self._embed_msg(ctx, 'Playlist {} saved from current queue: {} tracks added.'.format(
|
||||||
|
playlist_name, len(tracklist)))
|
||||||
|
|
||||||
|
@playlist.command(name='remove')
|
||||||
|
async def _playlist_remove(self, ctx, playlist_name, url):
|
||||||
|
"""Remove a song from a playlist by url."""
|
||||||
|
async with self.config.guild(ctx.guild).playlists() as playlists:
|
||||||
|
try:
|
||||||
|
if (playlists[playlist_name]['author'] != ctx.author.id and not
|
||||||
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
|
return await self._embed_msg(ctx, 'You are not the author of that playlist.')
|
||||||
|
except KeyError:
|
||||||
|
return await self._embed_msg(ctx, 'No playlist with that name.')
|
||||||
|
track_list = playlists[playlist_name]['tracks']
|
||||||
|
clean_list = [track for track in track_list if not url == track['info']['uri']]
|
||||||
|
if len(playlists[playlist_name]['tracks']) == len(clean_list):
|
||||||
|
return await self._embed_msg(ctx, 'URL not in playlist.')
|
||||||
|
del_count = len(playlists[playlist_name]['tracks']) - len(clean_list)
|
||||||
|
if not clean_list:
|
||||||
|
del playlists[playlist_name]
|
||||||
|
return await self._embed_msg(ctx, 'No songs left, removing playlist.')
|
||||||
|
playlists[playlist_name]['tracks'] = clean_list
|
||||||
|
if playlists[playlist_name]['playlist_url'] is not None:
|
||||||
|
playlists[playlist_name]['playlist_url'] = None
|
||||||
|
if del_count > 1:
|
||||||
|
await self._embed_msg(ctx, '{} entries have been removed from the {} playlist.'.format(
|
||||||
|
del_count, playlist_name))
|
||||||
|
else:
|
||||||
|
await self._embed_msg(ctx, 'The track has been removed from the {} playlist.'.format(playlist_name))
|
||||||
|
|
||||||
@playlist.command(name='save')
|
@playlist.command(name='save')
|
||||||
async def _playlist_save(self, ctx, playlist_name, playlist_url):
|
async def _playlist_save(self, ctx, playlist_name, playlist_url):
|
||||||
@ -628,18 +702,13 @@ class Audio:
|
|||||||
if not await self._playlist_check(ctx):
|
if not await self._playlist_check(ctx):
|
||||||
return
|
return
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
tracks = await player.get_tracks(playlist_url)
|
tracklist = await self._playlist_tracks(ctx, player, playlist_url)
|
||||||
if not tracks:
|
playlist_list = self._to_json(ctx, playlist_url, tracklist)
|
||||||
return await self._embed_msg(ctx, 'Nothing found.')
|
if tracklist is not None:
|
||||||
tracklist = []
|
async with self.config.guild(ctx.guild).playlists() as playlists:
|
||||||
for track in tracks:
|
playlists[playlist_name] = playlist_list
|
||||||
track_obj = self._track_creator(ctx, player, None, track)
|
return await self._embed_msg(ctx, 'Playlist {} saved: {} tracks added.'.format(
|
||||||
tracklist.append(track_obj)
|
playlist_name, len(tracklist)))
|
||||||
playlist_list = self._to_json(ctx, playlist_url, tracklist, playlist_name)
|
|
||||||
|
|
||||||
async with self.config.guild(ctx.guild).playlists() as playlists:
|
|
||||||
playlists[playlist_name] = playlist_list
|
|
||||||
return await self._embed_msg(ctx, 'Playlist {} saved: {} tracks added.'.format(playlist_name, len(tracks)))
|
|
||||||
|
|
||||||
@playlist.command(name='start')
|
@playlist.command(name='start')
|
||||||
async def _playlist_start(self, ctx, playlist_name=None):
|
async def _playlist_start(self, ctx, playlist_name=None):
|
||||||
@ -647,25 +716,89 @@ class Audio:
|
|||||||
if not await self._playlist_check(ctx):
|
if not await self._playlist_check(ctx):
|
||||||
return
|
return
|
||||||
playlists = await self.config.guild(ctx.guild).playlists.get_raw()
|
playlists = await self.config.guild(ctx.guild).playlists.get_raw()
|
||||||
try:
|
author_obj = self.bot.get_user(ctx.author.id)
|
||||||
author_id = playlists[playlist_name]["author"]
|
|
||||||
except KeyError:
|
|
||||||
return await self._embed_msg(ctx, 'That playlist doesn\'t exist.')
|
|
||||||
author_obj = self.bot.get_user(author_id)
|
|
||||||
track_count = 0
|
track_count = 0
|
||||||
try:
|
try:
|
||||||
playlist_len = len(playlists[playlist_name]["tracks"])
|
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
for track in playlists[playlist_name]["tracks"]:
|
for track in playlists[playlist_name]["tracks"]:
|
||||||
player.add(author_obj, lavalink.rest_api.Track(data=track))
|
player.add(author_obj, lavalink.rest_api.Track(data=track))
|
||||||
track_count = track_count + 1
|
track_count = track_count + 1
|
||||||
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(track_count))
|
description='Added {} tracks to the queue.'.format(track_count))
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
if not player.current:
|
if not player.current:
|
||||||
await player.play()
|
await player.play()
|
||||||
except TypeError:
|
except TypeError:
|
||||||
await ctx.invoke(self.play, query=playlists[playlist_name]["playlist_url"])
|
await ctx.invoke(self.play, query=playlists[playlist_name]["playlist_url"])
|
||||||
|
except KeyError:
|
||||||
|
await self._embed_msg(ctx, 'That playlist doesn\'t exist.')
|
||||||
|
|
||||||
|
@checks.is_owner()
|
||||||
|
@playlist.command(name='upload')
|
||||||
|
async def _playlist_upload(self, ctx):
|
||||||
|
"""Convert a Red v2 playlist file to a playlist."""
|
||||||
|
if not await self._playlist_check(ctx):
|
||||||
|
return
|
||||||
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
|
await self._embed_msg(ctx, 'Please upload the playlist file. Any other message will cancel this operation.')
|
||||||
|
def check(m):
|
||||||
|
return m.author == ctx.author
|
||||||
|
try:
|
||||||
|
file_message = await ctx.bot.wait_for('message', timeout=30.0, check=check)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
return await self._embed_msg(ctx, 'No file detected, try again later.')
|
||||||
|
try:
|
||||||
|
file_url = file_message.attachments[0].url
|
||||||
|
except IndexError:
|
||||||
|
return await self._embed_msg(ctx, 'Upload canceled.')
|
||||||
|
v2_playlist_name = (file_url.split('/')[6]).split('.')[0]
|
||||||
|
file_suffix = file_url.rsplit('.', 1)[1]
|
||||||
|
if file_suffix != "txt":
|
||||||
|
return await self._embed_msg(ctx, 'Only playlist files can be uploaded.')
|
||||||
|
async with self.session.request('GET', file_url) as r:
|
||||||
|
v2_playlist = await r.json(content_type='text/plain')
|
||||||
|
try:
|
||||||
|
v2_playlist_url = v2_playlist["link"]
|
||||||
|
except KeyError:
|
||||||
|
v2_playlist_url = None
|
||||||
|
if (not v2_playlist_url or not self._match_yt_playlist(v2_playlist_url) or not
|
||||||
|
await player.get_tracks(v2_playlist_url)):
|
||||||
|
track_list = []
|
||||||
|
track_count = 0
|
||||||
|
async with self.config.guild(ctx.guild).playlists() as v3_playlists:
|
||||||
|
try:
|
||||||
|
if v3_playlists[v2_playlist_name]:
|
||||||
|
return await self._embed_msg(ctx, 'A playlist already exists with this name.')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
embed1 = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Please wait, adding tracks...')
|
||||||
|
playlist_msg = await ctx.send(embed=embed1)
|
||||||
|
for song_url in v2_playlist["playlist"]:
|
||||||
|
track = await player.get_tracks(song_url)
|
||||||
|
try:
|
||||||
|
track_obj = self._track_creator(player, other_track=track[0])
|
||||||
|
track_list.append(track_obj)
|
||||||
|
track_count = track_count + 1
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
if track_count % 5 == 0:
|
||||||
|
embed2 = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Loading track {}/{}...'.format(
|
||||||
|
track_count, len(v2_playlist["playlist"])))
|
||||||
|
await playlist_msg.edit(embed=embed2)
|
||||||
|
if not track_list:
|
||||||
|
return await self._embed_msg(ctx, 'No tracks found.')
|
||||||
|
playlist_list = self._to_json(ctx, v2_playlist_url, track_list)
|
||||||
|
v3_playlists[v2_playlist_name] = playlist_list
|
||||||
|
if len(v2_playlist["playlist"]) != track_count:
|
||||||
|
bad_tracks = len(v2_playlist["playlist"]) - track_count
|
||||||
|
msg = ('Added {} tracks from the {} playlist. {} track(s) could not '
|
||||||
|
'be loaded.'.format(track_count, v2_playlist_name, bad_tracks))
|
||||||
|
else:
|
||||||
|
msg = 'Added {} tracks from the {} playlist.'.format(track_count, v2_playlist_name)
|
||||||
|
embed3 = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Playlist Saved', description=msg)
|
||||||
|
await playlist_msg.edit(embed=embed3)
|
||||||
|
else:
|
||||||
|
await ctx.invoke(self._playlist_save, v2_playlist_name, v2_playlist_url)
|
||||||
|
|
||||||
async def _playlist_check(self, ctx):
|
async def _playlist_check(self, ctx):
|
||||||
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
@ -686,7 +819,7 @@ class Audio:
|
|||||||
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 ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
await self._embed_msg(ctx, 'You must be in the voice channel to use the playlist command.')
|
await self._embed_msg(ctx, 'You must be in the voice channel to use the playlist command.')
|
||||||
return False
|
return False
|
||||||
if not await self._currency_check(ctx, jukebox_price):
|
if not await self._currency_check(ctx, jukebox_price):
|
||||||
@ -694,6 +827,27 @@ class Audio:
|
|||||||
await self._data_check(ctx)
|
await self._data_check(ctx)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
async def _playlist_tracks(self, ctx, player, query):
|
||||||
|
search = False
|
||||||
|
if type(query) is tuple:
|
||||||
|
query = " ".join(query)
|
||||||
|
if not query.startswith('http'):
|
||||||
|
query = " ".join(query)
|
||||||
|
query = 'ytsearch:{}'.format(query)
|
||||||
|
search = True
|
||||||
|
tracks = await player.get_tracks(query)
|
||||||
|
if not tracks:
|
||||||
|
return await self._embed_msg(ctx, 'Nothing found.')
|
||||||
|
tracklist = []
|
||||||
|
if not search:
|
||||||
|
for track in tracks:
|
||||||
|
track_obj = self._track_creator(player, other_track=track)
|
||||||
|
tracklist.append(track_obj)
|
||||||
|
else:
|
||||||
|
track_obj = self._track_creator(player, other_track=tracks[0])
|
||||||
|
tracklist.append(track_obj)
|
||||||
|
return tracklist
|
||||||
|
|
||||||
@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."""
|
||||||
@ -706,7 +860,7 @@ class Audio:
|
|||||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx, ctx.author):
|
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx, ctx.author):
|
||||||
return await self._embed_msg(ctx, 'You need the DJ role to skip songs.')
|
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
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
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.')
|
||||||
@ -773,8 +927,8 @@ class Audio:
|
|||||||
|
|
||||||
for i, track in enumerate(player.queue[start:end], start=start):
|
for i, track in enumerate(player.queue[start:end], start=start):
|
||||||
req_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)
|
||||||
@ -802,7 +956,7 @@ class Audio:
|
|||||||
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 ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
return await self._embed_msg(ctx, 'You must be in the voice channel to toggle repeat.')
|
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))
|
await self._embed_msg(ctx, 'Repeat songs: {}.'.format(repeat))
|
||||||
|
|
||||||
@ -819,7 +973,7 @@ class Audio:
|
|||||||
if 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 remove songs.')
|
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
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
return await self._embed_msg(ctx, 'You must be in the voice channel to manage the queue.')
|
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.')
|
||||||
@ -852,7 +1006,7 @@ class Audio:
|
|||||||
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 ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
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('<>')
|
||||||
@ -872,8 +1026,8 @@ class Audio:
|
|||||||
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, track.title,
|
search_list += '`{0}.` [**{1}**]({2})\n'.format(_next, track.title,
|
||||||
track.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)
|
||||||
@ -906,7 +1060,8 @@ class Audio:
|
|||||||
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: starts at #{} in queue'.format(queue_total_duration, (len(player.queue) + 1)))
|
songembed.set_footer(text='{} until start of search playback: starts at #{} in queue'.format(
|
||||||
|
queue_total_duration, (len(player.queue) + 1)))
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
player.add(ctx.author, track)
|
player.add(ctx.author, track)
|
||||||
if not player.current:
|
if not player.current:
|
||||||
@ -926,7 +1081,8 @@ class Audio:
|
|||||||
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:
|
||||||
embed.set_footer(text='{} until track playback: #{} in queue'.format(queue_total_duration, (len(player.queue) + 1)))
|
embed.set_footer(text='{} until track playback: #{} in queue'.format(queue_total_duration, (
|
||||||
|
len(player.queue) + 1)))
|
||||||
player.add(ctx.author, search_choice)
|
player.add(ctx.author, search_choice)
|
||||||
if not player.current:
|
if not player.current:
|
||||||
await player.play()
|
await player.play()
|
||||||
@ -940,7 +1096,7 @@ 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)
|
||||||
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
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 dj_enabled:
|
||||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx, ctx.author):
|
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx, ctx.author):
|
||||||
@ -973,7 +1129,7 @@ class Audio:
|
|||||||
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 ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
return await self._embed_msg(ctx, 'You must be in the voice channel to toggle shuffle.')
|
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))
|
await self._embed_msg(ctx, 'Shuffle songs: {}.'.format(shuffle))
|
||||||
|
|
||||||
@ -984,7 +1140,7 @@ 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)
|
||||||
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
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.')
|
||||||
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||||
vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
|
vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
|
||||||
@ -1052,11 +1208,11 @@ class Audio:
|
|||||||
nonbots = sum(not m.bot for m in ctx.guild.get_member(self.bot.user.id).voice.channel.members)
|
nonbots = sum(not m.bot for m in ctx.guild.get_member(self.bot.user.id).voice.channel.members)
|
||||||
if nonbots == 1:
|
if nonbots == 1:
|
||||||
nonbots = 2
|
nonbots = 2
|
||||||
|
elif ctx.guild.get_member(member.id).voice.channel.members == 1:
|
||||||
|
nonbots = 1
|
||||||
else:
|
else:
|
||||||
if ctx.guild.get_member(member.id).voice.channel.members == 1:
|
nonbots = 0
|
||||||
nonbots = 1
|
return nonbots <= 1
|
||||||
alone = nonbots <= 1
|
|
||||||
return alone
|
|
||||||
|
|
||||||
async def _has_dj_role(self, ctx, member):
|
async def _has_dj_role(self, ctx, member):
|
||||||
dj_role_id = await self.config.guild(ctx.guild).dj_role()
|
dj_role_id = await self.config.guild(ctx.guild).dj_role()
|
||||||
@ -1098,7 +1254,7 @@ 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)
|
||||||
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
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 vote_enabled or vote_enabled and dj_enabled:
|
||||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx, ctx.author):
|
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx, ctx.author):
|
||||||
@ -1128,7 +1284,7 @@ class Audio:
|
|||||||
if self._player_check(ctx):
|
if self._player_check(ctx):
|
||||||
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
|
if ((not ctx.author.voice or ctx.author.voice.channel != player.channel) and not
|
||||||
await self._can_instaskip(ctx, ctx.author)):
|
await self._can_instaskip(ctx, ctx.author)):
|
||||||
return await self._embed_msg(ctx, 'You must be in the voice channel to change the volume.')
|
return await self._embed_msg(ctx, 'You must be in the voice channel to change the volume.')
|
||||||
if dj_enabled:
|
if dj_enabled:
|
||||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._has_dj_role(ctx, ctx.author):
|
if not await self._can_instaskip(ctx, ctx.author) and not await self._has_dj_role(ctx, ctx.author):
|
||||||
@ -1165,7 +1321,8 @@ class Audio:
|
|||||||
await self.config.password.set('youshallnotpass')
|
await self.config.password.set('youshallnotpass')
|
||||||
await self.config.rest_port.set(2333)
|
await self.config.rest_port.set(2333)
|
||||||
await self.config.ws_port.set(2332)
|
await self.config.ws_port.set(2332)
|
||||||
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='External lavalink server: {}.'.format(not external))
|
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='External lavalink server: {}.'.format(
|
||||||
|
not external))
|
||||||
embed.set_footer(text='Defaults reset.')
|
embed.set_footer(text='Defaults reset.')
|
||||||
return await ctx.send(embed=embed)
|
return await ctx.send(embed=embed)
|
||||||
else:
|
else:
|
||||||
@ -1187,7 +1344,8 @@ class Audio:
|
|||||||
"""Set the lavalink server password."""
|
"""Set the lavalink server password."""
|
||||||
await self.config.password.set(str(password))
|
await self.config.password.set(str(password))
|
||||||
if await self._check_external():
|
if await self._check_external():
|
||||||
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Server password set to {}.'.format(password))
|
embed = discord.Embed(colour=ctx.guild.me.top_role.colour,
|
||||||
|
title='Server password set to {}.'.format(password))
|
||||||
embed.set_footer(text='External lavalink server set to True.')
|
embed.set_footer(text='External lavalink server set to True.')
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
else:
|
else:
|
||||||
@ -1209,7 +1367,8 @@ class Audio:
|
|||||||
"""Set the lavalink websocket server port."""
|
"""Set the lavalink websocket server port."""
|
||||||
await self.config.rest_port.set(ws_port)
|
await self.config.rest_port.set(ws_port)
|
||||||
if await self._check_external():
|
if await self._check_external():
|
||||||
embed = discord.Embed(colour=ctx.guild.me.top_role.colour, title='Websocket port set to {}.'.format(ws_port))
|
embed = discord.Embed(colour=ctx.guild.me.top_role.colour,
|
||||||
|
title='Websocket port set to {}.'.format(ws_port))
|
||||||
embed.set_footer(text='External lavalink server set to True.')
|
embed.set_footer(text='External lavalink server set to True.')
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
else:
|
else:
|
||||||
@ -1255,7 +1414,8 @@ class Audio:
|
|||||||
if player.volume != volume:
|
if player.volume != volume:
|
||||||
await player.set_volume(volume)
|
await player.set_volume(volume)
|
||||||
|
|
||||||
async def _draw_time(self, ctx):
|
@staticmethod
|
||||||
|
async def _draw_time(ctx):
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
paused = player.paused
|
paused = player.paused
|
||||||
pos = player.position
|
pos = player.position
|
||||||
@ -1305,6 +1465,15 @@ class Audio:
|
|||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _match_yt_playlist(url):
|
||||||
|
yt_list_playlist = re.compile(
|
||||||
|
r'^(https?\:\/\/)?(www\.)?(youtube\.com|youtu\.?be)'
|
||||||
|
r'(\/playlist\?).*(list=)(.*)(&|$)')
|
||||||
|
if yt_list_playlist.match(url):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def _queue_duration(ctx):
|
async def _queue_duration(ctx):
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
@ -1312,7 +1481,7 @@ class Audio:
|
|||||||
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 not player.queue:
|
if not player.queue:
|
||||||
queue_duration = 0
|
queue_duration = 0
|
||||||
try:
|
try:
|
||||||
@ -1333,14 +1502,16 @@ class Audio:
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _to_json(self, ctx, playlist_url, tracklist, playlist_name):
|
@staticmethod
|
||||||
|
def _to_json(ctx, playlist_url, tracklist):
|
||||||
playlist = {"author": ctx.author.id, "playlist_url": playlist_url, "tracks": tracklist}
|
playlist = {"author": ctx.author.id, "playlist_url": playlist_url, "tracks": tracklist}
|
||||||
return playlist
|
return playlist
|
||||||
|
|
||||||
def _track_creator(self, ctx, player, position, other_track=None):
|
@staticmethod
|
||||||
|
def _track_creator(player, position=None, other_track=None):
|
||||||
if position == 'np':
|
if position == 'np':
|
||||||
queued_track = player.current
|
queued_track = player.current
|
||||||
elif position == None:
|
elif position is None:
|
||||||
queued_track = other_track
|
queued_track = other_track
|
||||||
else:
|
else:
|
||||||
queued_track = player.queue[position]
|
queued_track = player.queue[position]
|
||||||
@ -1365,6 +1536,7 @@ class Audio:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def __unload(self):
|
def __unload(self):
|
||||||
|
self.session.close()
|
||||||
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())
|
||||||
shutdown_lavalink_server()
|
shutdown_lavalink_server()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user