mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-21 18:27:59 -05:00
Audio Cog - v2.3.0 (#4446)
* First commit - Bring everything from dev cog minus NSFW support
* Add a toggle for auto deafen
* Add a one off Send to Owners
* aaaaaaa
* Update this to ensure `get_perms` is not called if the API is disabled
* Apply suggestions from code review
Co-authored-by: Vuks <51289041+Vuks69@users.noreply.github.com>
* silence any errors here (in case API is down so it doesnt affect audio)
* update the message to tell the mto join the Official Red server.
* remove useless sutff, and change dj check order to ensure bot doesnt join VC for non DJ's
* ffs
* Update redbot/cogs/audio/core/tasks/startup.py
Co-authored-by: Twentysix <Twentysix26@users.noreply.github.com>
* Aikas Review
* Add #3995 in here
* update
* *sigh*
* lock behind owner
* to help with debugging
* Revert "to help with debugging"
This reverts commit 8cbf17be
* resolve last review
Co-authored-by: Vuks <51289041+Vuks69@users.noreply.github.com>
Co-authored-by: Twentysix <Twentysix26@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import asyncio
|
||||
import datetime
|
||||
import logging
|
||||
import time
|
||||
|
||||
from typing import Optional
|
||||
|
||||
import discord
|
||||
@@ -130,6 +131,13 @@ class AudioEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
)
|
||||
except Exception as err:
|
||||
debug_exc_log(log, err, f"Failed to delete global daily playlist ID: {too_old_id}")
|
||||
persist_cache = self._persist_queue_cache.setdefault(
|
||||
guild.id, await self.config.guild(guild).persist_queue()
|
||||
)
|
||||
if persist_cache:
|
||||
await self.api_interface.persistent_queue_api.played(
|
||||
guild_id=guild.id, track_id=track_identifier
|
||||
)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_audio_queue_end(
|
||||
@@ -141,6 +149,21 @@ class AudioEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
await self.api_interface.local_cache_api.youtube.clean_up_old_entries()
|
||||
await asyncio.sleep(5)
|
||||
await self.playlist_api.delete_scheduled()
|
||||
await self.api_interface.persistent_queue_api.drop(guild.id)
|
||||
await asyncio.sleep(5)
|
||||
await self.api_interface.persistent_queue_api.delete_scheduled()
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_audio_track_enqueue(self, guild: discord.Guild, track, requester):
|
||||
if not (track and guild):
|
||||
return
|
||||
persist_cache = self._persist_queue_cache.setdefault(
|
||||
guild.id, await self.config.guild(guild).persist_queue()
|
||||
)
|
||||
if persist_cache:
|
||||
await self.api_interface.persistent_queue_api.enqueued(
|
||||
guild_id=guild.id, room_id=track.extras["vc"], track=track
|
||||
)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_red_audio_track_end(
|
||||
@@ -152,3 +175,6 @@ class AudioEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
await self.api_interface.local_cache_api.youtube.clean_up_old_entries()
|
||||
await asyncio.sleep(5)
|
||||
await self.playlist_api.delete_scheduled()
|
||||
await self.api_interface.persistent_queue_api.drop(guild.id)
|
||||
await asyncio.sleep(5)
|
||||
await self.api_interface.persistent_queue_api.delete_scheduled()
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
import asyncio
|
||||
import contextlib
|
||||
import logging
|
||||
import re
|
||||
|
||||
from collections import OrderedDict
|
||||
from pathlib import Path
|
||||
from typing import Final, Pattern
|
||||
|
||||
import discord
|
||||
import lavalink
|
||||
|
||||
from aiohttp import ClientConnectorError
|
||||
|
||||
from discord.ext.commands import CheckFailure
|
||||
from redbot.core import commands
|
||||
from redbot.core.utils.chat_formatting import box, humanize_list
|
||||
|
||||
from ..abc import MixinMeta
|
||||
from ..cog_utils import CompositeMetaClass, _
|
||||
from ...audio_logging import debug_exc_log
|
||||
from ...errors import TrackEnqueueError
|
||||
from ..abc import MixinMeta
|
||||
from ..cog_utils import HUMANIZED_PERM, CompositeMetaClass, _
|
||||
|
||||
log = logging.getLogger("red.cogs.Audio.cog.Events.dpy")
|
||||
|
||||
@@ -39,11 +44,55 @@ class DpyEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
raise RuntimeError(
|
||||
"Not running audio command due to invalid machine architecture for Lavalink."
|
||||
)
|
||||
# with contextlib.suppress(Exception):
|
||||
# player = lavalink.get_player(ctx.guild.id)
|
||||
# notify_channel = player.fetch("channel")
|
||||
# if not notify_channel:
|
||||
# player.store("channel", ctx.channel.id)
|
||||
|
||||
current_perms = ctx.channel.permissions_for(ctx.me)
|
||||
surpass_ignore = (
|
||||
isinstance(ctx.channel, discord.abc.PrivateChannel)
|
||||
or await ctx.bot.is_owner(ctx.author)
|
||||
or await ctx.bot.is_admin(ctx.author)
|
||||
)
|
||||
guild = ctx.guild
|
||||
if guild and not current_perms.is_superset(self.permission_cache):
|
||||
current_perms_set = set(iter(current_perms))
|
||||
expected_perms_set = set(iter(self.permission_cache))
|
||||
diff = expected_perms_set - current_perms_set
|
||||
missing_perms = dict((i for i in diff if i[-1] is not False))
|
||||
missing_perms = OrderedDict(sorted(missing_perms.items()))
|
||||
missing_permissions = missing_perms.keys()
|
||||
log.debug(
|
||||
"Missing the following perms in %d, Owner ID: %d: %s",
|
||||
ctx.guild.id,
|
||||
ctx.guild.owner.id,
|
||||
humanize_list(list(missing_permissions)),
|
||||
)
|
||||
if not surpass_ignore:
|
||||
text = _(
|
||||
"I'm missing permissions in this server, "
|
||||
"Please address this as soon as possible.\n\n"
|
||||
"Expected Permissions:\n"
|
||||
)
|
||||
for perm, value in missing_perms.items():
|
||||
text += "{perm}: [{status}]\n".format(
|
||||
status=_("Enabled") if value else _("Disabled"),
|
||||
perm=HUMANIZED_PERM.get(perm),
|
||||
)
|
||||
text = text.strip()
|
||||
if current_perms.send_messages and current_perms.read_messages:
|
||||
await ctx.send(box(text=text, lang="ini"))
|
||||
else:
|
||||
log.info(
|
||||
"Missing write permission in %d, Owner ID: %d",
|
||||
ctx.guild.id,
|
||||
ctx.guild.owner.id,
|
||||
)
|
||||
raise CheckFailure(message=text)
|
||||
|
||||
with contextlib.suppress(Exception):
|
||||
player = lavalink.get_player(ctx.guild.id)
|
||||
notify_channel = player.fetch("channel")
|
||||
if not notify_channel:
|
||||
player.store("channel", ctx.channel.id)
|
||||
|
||||
self._daily_global_playlist_cache.setdefault(
|
||||
self.bot.user.id, await self.config.daily_playlists()
|
||||
)
|
||||
@@ -51,12 +100,16 @@ class DpyEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
self.local_folder_current_path = Path(await self.config.localpath())
|
||||
if not ctx.guild:
|
||||
return
|
||||
|
||||
dj_enabled = self._dj_status_cache.setdefault(
|
||||
ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
|
||||
)
|
||||
self._daily_playlist_cache.setdefault(
|
||||
ctx.guild.id, await self.config.guild(ctx.guild).daily_playlists()
|
||||
)
|
||||
self._persist_queue_cache.setdefault(
|
||||
ctx.guild.id, await self.config.guild(ctx.guild).persist_queue()
|
||||
)
|
||||
if dj_enabled:
|
||||
dj_role = self._dj_role_cache.setdefault(
|
||||
ctx.guild.id, await self.config.guild(ctx.guild).dj_role()
|
||||
@@ -78,12 +131,16 @@ class DpyEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
if isinstance(error, commands.ArgParserFailure):
|
||||
handled = True
|
||||
msg = _("`{user_input}` is not a valid value for `{command}`").format(
|
||||
user_input=error.user_input, command=error.cmd
|
||||
user_input=error.user_input,
|
||||
command=error.cmd,
|
||||
)
|
||||
if error.custom_help_msg:
|
||||
msg += f"\n{error.custom_help_msg}"
|
||||
await self.send_embed_msg(
|
||||
ctx, title=_("Unable To Parse Argument"), description=msg, error=True
|
||||
ctx,
|
||||
title=_("Unable To Parse Argument"),
|
||||
description=msg,
|
||||
error=True,
|
||||
)
|
||||
if error.send_cmd_help:
|
||||
await ctx.send_help()
|
||||
@@ -101,7 +158,10 @@ class DpyEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
)
|
||||
else:
|
||||
await self.send_embed_msg(
|
||||
ctx, title=_("Invalid Argument"), description=error.args[0], error=True
|
||||
ctx,
|
||||
title=_("Invalid Argument"),
|
||||
description=error.args[0],
|
||||
error=True,
|
||||
)
|
||||
else:
|
||||
await ctx.send_help()
|
||||
@@ -137,6 +197,17 @@ class DpyEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
error=True,
|
||||
)
|
||||
debug_exc_log(log, error, "This is a handled error")
|
||||
elif isinstance(error, discord.errors.HTTPException):
|
||||
handled = True
|
||||
await self.send_embed_msg(
|
||||
ctx,
|
||||
title=_("There was an issue communicating with Discord."),
|
||||
description=_("This error has been reported to the bot owner."),
|
||||
error=True,
|
||||
)
|
||||
log.exception(
|
||||
"This is not handled in the core Audio cog, please report it.", exc_info=error
|
||||
)
|
||||
if not isinstance(
|
||||
error,
|
||||
(
|
||||
@@ -186,3 +257,13 @@ class DpyEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
self.skip_votes[before.channel.guild].remove(member.id)
|
||||
except (ValueError, KeyError, AttributeError):
|
||||
pass
|
||||
channel = self.rgetattr(member, "voice.channel", None)
|
||||
bot_voice_state = self.rgetattr(member, "guild.me.voice.self_deaf", None)
|
||||
if channel and bot_voice_state is False:
|
||||
try:
|
||||
player = lavalink.get_player(channel.guild.id)
|
||||
except (KeyError, AttributeError):
|
||||
pass
|
||||
else:
|
||||
if player.channel.id == channel.id:
|
||||
await self.self_deafen(player)
|
||||
|
||||
@@ -18,6 +18,8 @@ class LavalinkEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
) -> None:
|
||||
current_track = player.current
|
||||
current_channel = player.channel
|
||||
if not current_channel:
|
||||
return
|
||||
guild = self.rgetattr(current_channel, "guild", None)
|
||||
if await self.bot.cog_disabled_in_guild(self, guild):
|
||||
await player.stop()
|
||||
@@ -31,12 +33,15 @@ class LavalinkEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
current_length = self.rgetattr(current_track, "length", None)
|
||||
current_thumbnail = self.rgetattr(current_track, "thumbnail", None)
|
||||
current_extras = self.rgetattr(current_track, "extras", {})
|
||||
current_id = self.rgetattr(current_track, "_info", {}).get("identifier")
|
||||
guild_data = await self.config.guild(guild).all()
|
||||
repeat = guild_data["repeat"]
|
||||
notify = guild_data["notify"]
|
||||
disconnect = guild_data["disconnect"]
|
||||
autoplay = guild_data["auto_play"]
|
||||
description = self.get_track_description(current_track, self.local_folder_current_path)
|
||||
description = await self.get_track_description(
|
||||
current_track, self.local_folder_current_path
|
||||
)
|
||||
status = await self.config.status()
|
||||
log.debug(f"Received a new lavalink event for {guild_id}: {event_type}: {extra}")
|
||||
prev_song: lavalink.Track = player.fetch("prev_song")
|
||||
@@ -51,12 +56,18 @@ class LavalinkEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
player.store("playing_song", current_track)
|
||||
player.store("requester", current_requester)
|
||||
self.bot.dispatch("red_audio_track_start", guild, current_track, current_requester)
|
||||
if guild_id and current_track:
|
||||
await self.api_interface.persistent_queue_api.played(
|
||||
guild_id=guild_id, track_id=current_track.track_identifier
|
||||
)
|
||||
if event_type == lavalink.LavalinkEvents.TRACK_END:
|
||||
prev_requester = player.fetch("prev_requester")
|
||||
self.bot.dispatch("red_audio_track_end", guild, prev_song, prev_requester)
|
||||
if event_type == lavalink.LavalinkEvents.QUEUE_END:
|
||||
prev_requester = player.fetch("prev_requester")
|
||||
self.bot.dispatch("red_audio_queue_end", guild, prev_song, prev_requester)
|
||||
if guild_id:
|
||||
await self.api_interface.persistent_queue_api.drop(guild_id)
|
||||
if (
|
||||
autoplay
|
||||
and not player.queue
|
||||
@@ -82,7 +93,7 @@ class LavalinkEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
notify_channel,
|
||||
title=_("Unable to Get Track"),
|
||||
description=_(
|
||||
"I'm unable get a track from Lavalink at the moment, try again in a few "
|
||||
"I'm unable to get a track from Lavalink at the moment, try again in a few "
|
||||
"minutes."
|
||||
),
|
||||
)
|
||||
@@ -127,13 +138,13 @@ class LavalinkEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
)
|
||||
player.store("notify_message", notify_message)
|
||||
if event_type == lavalink.LavalinkEvents.TRACK_START and status:
|
||||
player_check = self.get_active_player_count()
|
||||
player_check = await self.get_active_player_count()
|
||||
await self.update_bot_presence(*player_check)
|
||||
|
||||
if event_type == lavalink.LavalinkEvents.TRACK_END and status:
|
||||
await asyncio.sleep(1)
|
||||
if not player.is_playing:
|
||||
player_check = self.get_active_player_count()
|
||||
player_check = await self.get_active_player_count()
|
||||
await self.update_bot_presence(*player_check)
|
||||
|
||||
if event_type == lavalink.LavalinkEvents.QUEUE_END:
|
||||
@@ -146,7 +157,7 @@ class LavalinkEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
self.bot.dispatch("red_audio_audio_disconnect", guild)
|
||||
await player.disconnect()
|
||||
if status:
|
||||
player_check = self.get_active_player_count()
|
||||
player_check = await self.get_active_player_count()
|
||||
await self.update_bot_presence(*player_check)
|
||||
|
||||
if event_type in [
|
||||
@@ -209,5 +220,9 @@ class LavalinkEvents(MixinMeta, metaclass=CompositeMetaClass):
|
||||
colour=await self.bot.get_embed_color(message_channel),
|
||||
description="{}\n{}".format(extra.replace("\n", ""), description),
|
||||
)
|
||||
if current_id:
|
||||
asyncio.create_task(
|
||||
self.api_interface.global_cache_api.report_invalid(current_id)
|
||||
)
|
||||
await message_channel.send(embed=embed)
|
||||
await player.skip()
|
||||
|
||||
Reference in New Issue
Block a user