[Audio] Update for Red-Lavalink 0.3.x (#2547)

* [Audio] Update for Red-Lavalink #55

* Update setup.cfg

* Catch all the exceptions

* Update version range on Red-Lavalink

* Catch excepts on Spotify tracks/playlist upload

* No prefix needed
This commit is contained in:
aikaterna 2019-05-07 21:56:41 -07:00 committed by Will
parent 80ff07f53d
commit 65b88c09fb
2 changed files with 42 additions and 55 deletions

View File

@ -34,7 +34,7 @@ from .manager import ServerManager
_ = Translator("Audio", __file__) _ = Translator("Audio", __file__)
__version__ = "0.0.8b" __version__ = "0.0.9"
__author__ = ["aikaterna"] __author__ = ["aikaterna"]
log = logging.getLogger("red.audio") log = logging.getLogger("red.audio")
@ -172,19 +172,19 @@ class Audio(commands.Cog):
async def _players_check(): async def _players_check():
try: try:
get_players = [p for p in lavalink.players if p.current is not None] get_single_title = lavalink.active_players()[0].current.title
get_single_title = get_players[0].current.title
if get_single_title == "Unknown title": if get_single_title == "Unknown title":
get_single_title = get_players[0].current.uri get_single_title = lavalink.active_players()[0].current.uri
if not get_single_title.startswith("http"): if not get_single_title.startswith("http"):
get_single_title = get_single_title.rsplit("/", 1)[-1] get_single_title = get_single_title.rsplit("/", 1)[-1]
elif "localtracks/" in get_players[0].current.uri: elif "localtracks/" in lavalink.active_players()[0].current.uri:
get_single_title = "{} - {}".format( get_single_title = "{} - {}".format(
get_players[0].current.author, get_players[0].current.title lavalink.active_players()[0].current.author,
lavalink.active_players()[0].current.title,
) )
else: else:
get_single_title = get_players[0].current.title get_single_title = lavalink.active_players()[0].current.title
playing_servers = len(get_players) playing_servers = len(lavalink.active_players())
except IndexError: except IndexError:
get_single_title = None get_single_title = None
playing_servers = 0 playing_servers = 0
@ -668,11 +668,11 @@ class Audio(commands.Cog):
@commands.guild_only() @commands.guild_only()
async def audiostats(self, ctx): async def audiostats(self, ctx):
"""Audio stats.""" """Audio stats."""
server_num = len([p for p in lavalink.players if p.current is not None]) server_num = len(lavalink.active_players())
total_num = len([p for p in lavalink.players]) total_num = len(lavalink.all_players())
msg = "" msg = ""
for p in lavalink.players: for p in lavalink.all_players():
connect_start = p.fetch("connect") connect_start = p.fetch("connect")
connect_dur = self._dynamic_time( connect_dur = self._dynamic_time(
int((datetime.datetime.utcnow() - connect_start).total_seconds()) int((datetime.datetime.utcnow() - connect_start).total_seconds())
@ -1457,17 +1457,13 @@ class Audio(commands.Cog):
song_info = "{} {}".format(i["track"]["name"], i["track"]["artists"][0]["name"]) song_info = "{} {}".format(i["track"]["name"], i["track"]["artists"][0]["name"])
try: try:
track_url = await self._youtube_api_search(yt_key, song_info) track_url = await self._youtube_api_search(yt_key, song_info)
except: except (RuntimeError, aiohttp.client_exceptions.ServerDisconnectedError):
error_embed = discord.Embed( error_embed = discord.Embed(
colour=await ctx.embed_colour(), colour=await ctx.embed_colour(),
title=_( title=_("The connection was reset while loading the playlist."),
"The YouTube API key has not been set properly.\n"
"Use `{prefix}audioset youtubeapi` for instructions."
).format(prefix=ctx.prefix),
) )
await playlist_msg.edit(embed=error_embed) await playlist_msg.edit(embed=error_embed)
return None return None
# let's complain about errors
pass pass
try: try:
yt_track = await player.get_tracks(track_url) yt_track = await player.get_tracks(track_url)
@ -2040,7 +2036,10 @@ class Audio(commands.Cog):
) )
playlist_msg = await ctx.send(embed=embed1) playlist_msg = await ctx.send(embed=embed1)
for song_url in v2_playlist["playlist"]: for song_url in v2_playlist["playlist"]:
try:
track = await player.get_tracks(song_url) track = await player.get_tracks(song_url)
except RuntimeError:
pass
try: try:
track_obj = self._track_creator(player, other_track=track[0]) track_obj = self._track_creator(player, other_track=track[0])
track_list.append(track_obj) track_list.append(track_obj)
@ -2396,11 +2395,13 @@ class Audio(commands.Cog):
@commands.guild_only() @commands.guild_only()
async def _queue_clear(self, ctx): async def _queue_clear(self, ctx):
"""Clears the queue.""" """Clears the queue."""
try:
player = lavalink.get_player(ctx.guild.id) player = lavalink.get_player(ctx.guild.id)
except KeyError:
return await self._embed_msg(ctx, _("There's nothing in the queue."))
dj_enabled = await self.config.guild(ctx.guild).dj_enabled() dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
if not self._player_check(ctx) or not player.queue: if not self._player_check(ctx) or not player.queue:
return await self._embed_msg(ctx, _("There's nothing in the queue.")) return await self._embed_msg(ctx, _("There's nothing in the queue."))
player = lavalink.get_player(ctx.guild.id)
if dj_enabled: if dj_enabled:
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone( if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(
ctx, ctx.author ctx, ctx.author
@ -2413,7 +2414,10 @@ class Audio(commands.Cog):
@commands.guild_only() @commands.guild_only()
async def _queue_clean(self, ctx): async def _queue_clean(self, ctx):
"""Removes songs from the queue if the requester is not in the voice channel.""" """Removes songs from the queue if the requester is not in the voice channel."""
try:
player = lavalink.get_player(ctx.guild.id) player = lavalink.get_player(ctx.guild.id)
except KeyError:
return await self._embed_msg(ctx, _("There's nothing in the queue."))
dj_enabled = await self.config.guild(ctx.guild).dj_enabled() dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
if not self._player_check(ctx) or not player.queue: if not self._player_check(ctx) or not player.queue:
return await self._embed_msg(ctx, _("There's nothing in the queue.")) return await self._embed_msg(ctx, _("There's nothing in the queue."))
@ -3225,7 +3229,10 @@ class Audio(commands.Cog):
self._restart_connect() self._restart_connect()
async def _channel_check(self, ctx): async def _channel_check(self, ctx):
try:
player = lavalink.get_player(ctx.guild.id) player = lavalink.get_player(ctx.guild.id)
except KeyError:
return False
try: try:
in_channel = sum( in_channel = sum(
not m.bot for m in ctx.guild.get_member(self.bot.user.id).voice.channel.members not m.bot for m in ctx.guild.get_member(self.bot.user.id).voice.channel.members
@ -3312,7 +3319,7 @@ class Audio(commands.Cog):
stop_times = {} stop_times = {}
while True: while True:
for p in lavalink.players: for p in lavalink.all_players():
server = p.channel.guild server = p.channel.guild
if [self.bot.user] == p.channel.members: if [self.bot.user] == p.channel.members:
@ -3387,13 +3394,6 @@ class Audio(commands.Cog):
else: else:
return self.bot.color return self.bot.color
async def _get_playing(self, ctx):
if self._player_check(ctx):
player = lavalink.get_player(ctx.guild.id)
return len([player for p in lavalink.players if p.is_playing])
else:
return 0
async def _localtracks_folders(self, ctx): async def _localtracks_folders(self, ctx):
if not await self._localtracks_check(ctx): if not await self._localtracks_check(ctx):
return return
@ -3436,6 +3436,8 @@ class Audio(commands.Cog):
try: try:
lavalink.get_player(ctx.guild.id) lavalink.get_player(ctx.guild.id)
return True return True
except IndexError:
return False
except KeyError: except KeyError:
return False return False
@ -3543,11 +3545,14 @@ class Audio(commands.Cog):
async def _youtube_api_search(self, yt_key, query): async def _youtube_api_search(self, yt_key, query):
params = {"q": query, "part": "id", "key": yt_key, "maxResults": 1, "type": "video"} params = {"q": query, "part": "id", "key": yt_key, "maxResults": 1, "type": "video"}
yt_url = "https://www.googleapis.com/youtube/v3/search" yt_url = "https://www.googleapis.com/youtube/v3/search"
try:
async with self.session.request("GET", yt_url, params=params) as r: async with self.session.request("GET", yt_url, params=params) as r:
if r.status == 400: if r.status == 400:
return None return None
else: else:
search_response = await r.json() search_response = await r.json()
except RuntimeError:
return None
for search_result in search_response.get("items", []): for search_result in search_response.get("items", []):
if search_result["id"]["kind"] == "youtube#video": if search_result["id"]["kind"] == "youtube#video":
return "https://www.youtube.com/watch?v={}".format(search_result["id"]["videoId"]) return "https://www.youtube.com/watch?v={}".format(search_result["id"]["videoId"])
@ -3624,7 +3629,7 @@ class Audio(commands.Cog):
def cog_unload(self): def cog_unload(self):
if not self._cleaned_up: if not self._cleaned_up:
self.session.detach() self.bot.loop.create_task(self.session.close())
if self._disconnect_task: if self._disconnect_task:
self._disconnect_task.cancel() self._disconnect_task.cancel()
@ -3639,21 +3644,3 @@ class Audio(commands.Cog):
self._cleaned_up = True self._cleaned_up = True
__del__ = cog_unload __del__ = cog_unload
@commands.Cog.listener()
async def on_guild_remove(self, guild: discord.Guild):
"""
This is to clean up players when
the bot either leaves or is removed from a guild
"""
channels = {
x # x is a voice_channel
for y in [g.voice_channels for g in self.bot.guilds]
for x in y # y is a list of voice channels
} # Yes, this is ugly. It's also the most performant and commented.
zombie_players = {p for p in lavalink.player_manager.players if p.channel not in channels}
# Do not unroll to combine with next line.
# Can result in iterator changing size during context switching.
for zombie in zombie_players:
await zombie.destroy()

View File

@ -41,7 +41,7 @@ install_requires =
multidict==4.5.2 multidict==4.5.2
python-levenshtein-wheels==0.13.1 python-levenshtein-wheels==0.13.1
pyyaml==3.13 pyyaml==3.13
red-lavalink==0.2.3 red-lavalink>=0.3.0,<0.4
schema==0.6.8 schema==0.6.8
yarl==1.3.0 yarl==1.3.0
discord.py==1.0.1 discord.py==1.0.1