mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-12-05 17:02:32 -05:00
Merge branch 'V3/release/3.0.0' into V3/develop
# Conflicts: # redbot/cogs/audio/audio.py
This commit is contained in:
@@ -1285,6 +1285,9 @@ class Audio(commands.Cog):
|
||||
url_check = self._url_check(track["info"]["uri"])
|
||||
if not url_check:
|
||||
continue
|
||||
if track["info"]["uri"].startswith("localtracks/"):
|
||||
if not os.path.isfile(track["info"]["uri"]):
|
||||
continue
|
||||
player.add(author_obj, lavalink.rest_api.Track(data=track))
|
||||
track_count = track_count + 1
|
||||
embed = discord.Embed(
|
||||
@@ -2005,6 +2008,7 @@ class Audio(commands.Cog):
|
||||
async def seek(self, ctx, seconds: int = 30):
|
||||
"""Seek ahead or behind on a track by seconds."""
|
||||
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):
|
||||
return await self._embed_msg(ctx, _("Nothing playing."))
|
||||
player = lavalink.get_player(ctx.guild.id)
|
||||
@@ -2017,6 +2021,13 @@ class Audio(commands.Cog):
|
||||
ctx, ctx.author
|
||||
):
|
||||
return await self._embed_msg(ctx, _("You need the DJ role to use seek."))
|
||||
if vote_enabled:
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(
|
||||
ctx, ctx.author
|
||||
):
|
||||
return await self._embed_msg(
|
||||
ctx, _("There are other people listening - vote to skip instead.")
|
||||
)
|
||||
if player.current:
|
||||
if player.current.is_stream:
|
||||
return await self._embed_msg(ctx, _("Can't seek on a stream."))
|
||||
|
||||
@@ -71,13 +71,19 @@ async def get_java_version(loop) -> _JavaVersion:
|
||||
# ... version "MAJOR.MINOR.PATCH[_BUILD]" ...
|
||||
# ...
|
||||
# We only care about the major and minor parts though.
|
||||
version_line_re = re.compile(r'version "(?P<major>\d+).(?P<minor>\d+).\d+(?:_\d+)?"')
|
||||
version_line_re = re.compile(
|
||||
r'version "(?P<major>\d+).(?P<minor>\d+).\d+(?:_\d+)?(?:-[A-Za-z0-9]+)?"'
|
||||
)
|
||||
short_version_re = re.compile(r'version "(?P<major>\d+)"')
|
||||
|
||||
lines = version_info.splitlines()
|
||||
for line in lines:
|
||||
match = version_line_re.search(line)
|
||||
short_match = short_version_re.search(line)
|
||||
if match:
|
||||
return int(match["major"]), int(match["minor"])
|
||||
elif short_match:
|
||||
return int(short_match["major"]), 0
|
||||
|
||||
raise RuntimeError(
|
||||
"The output of `java -version` was unexpected. Please report this issue on Red's "
|
||||
|
||||
@@ -133,8 +133,6 @@ class Cleanup(commands.Cog):
|
||||
def check(m):
|
||||
if text in m.content:
|
||||
return True
|
||||
elif m == ctx.message:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -145,6 +143,7 @@ class Cleanup(commands.Cog):
|
||||
before=ctx.message,
|
||||
delete_pinned=delete_pinned,
|
||||
)
|
||||
to_delete.append(ctx.message)
|
||||
|
||||
reason = "{}({}) deleted {} messages containing '{}' in channel {}.".format(
|
||||
author.name, author.id, len(to_delete), text, channel.id
|
||||
@@ -188,8 +187,6 @@ class Cleanup(commands.Cog):
|
||||
def check(m):
|
||||
if m.author.id == _id:
|
||||
return True
|
||||
elif m == ctx.message:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -200,6 +197,8 @@ class Cleanup(commands.Cog):
|
||||
before=ctx.message,
|
||||
delete_pinned=delete_pinned,
|
||||
)
|
||||
to_delete.append(ctx.message)
|
||||
|
||||
reason = (
|
||||
"{}({}) deleted {} messages "
|
||||
" made by {}({}) in channel {}."
|
||||
@@ -231,6 +230,7 @@ class Cleanup(commands.Cog):
|
||||
to_delete = await self.get_messages_for_deletion(
|
||||
channel=channel, number=None, after=after, delete_pinned=delete_pinned
|
||||
)
|
||||
to_delete.append(ctx.message)
|
||||
|
||||
reason = "{}({}) deleted {} messages in channel {}.".format(
|
||||
author.name, author.id, len(to_delete), channel.name
|
||||
@@ -263,6 +263,7 @@ class Cleanup(commands.Cog):
|
||||
to_delete = await self.get_messages_for_deletion(
|
||||
channel=channel, number=number, before=before, delete_pinned=delete_pinned
|
||||
)
|
||||
to_delete.append(ctx.message)
|
||||
|
||||
reason = "{}({}) deleted {} messages in channel {}.".format(
|
||||
author.name, author.id, len(to_delete), channel.name
|
||||
|
||||
@@ -502,7 +502,7 @@ class Downloader(commands.Cog):
|
||||
if isinstance(cog_installable, Installable):
|
||||
made_by = ", ".join(cog_installable.author) or _("Missing from info.json")
|
||||
repo = self._repo_manager.get_repo(cog_installable.repo_name)
|
||||
repo_url = repo.url
|
||||
repo_url = _("Missing from installed repos") if repo is None else repo.url
|
||||
cog_name = cog_installable.name
|
||||
else:
|
||||
made_by = "26 & co."
|
||||
|
||||
@@ -388,7 +388,7 @@ class Economy(commands.Cog):
|
||||
@guild_only_check()
|
||||
async def payouts(self, ctx: commands.Context):
|
||||
"""Show the payouts for the slot machine."""
|
||||
await ctx.author.send(SLOT_PAYOUTS_MSG())
|
||||
await ctx.author.send(SLOT_PAYOUTS_MSG)
|
||||
|
||||
@commands.command()
|
||||
@guild_only_check()
|
||||
|
||||
@@ -28,7 +28,7 @@ class RPSParser:
|
||||
elif argument == "scissors":
|
||||
self.choice = RPS.scissors
|
||||
else:
|
||||
raise ValueError
|
||||
self.choice = None
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
@@ -121,6 +121,8 @@ class General(commands.Cog):
|
||||
"""Play Rock Paper Scissors."""
|
||||
author = ctx.author
|
||||
player_choice = your_choice.choice
|
||||
if not player_choice:
|
||||
return await ctx.send("This isn't a valid option. Try rock, paper, or scissors.")
|
||||
red_choice = choice((RPS.rock, RPS.paper, RPS.scissors))
|
||||
cond = {
|
||||
(RPS.rock, RPS.paper): False,
|
||||
@@ -263,12 +265,13 @@ class General(commands.Cog):
|
||||
|
||||
except aiohttp.ClientError:
|
||||
await ctx.send(
|
||||
_("No Urban dictionary entries were found, or there was an error in the process")
|
||||
_("No Urban Dictionary entries were found, or there was an error in the process.")
|
||||
)
|
||||
return
|
||||
|
||||
if data.get("error") != 404:
|
||||
|
||||
if not data["list"]:
|
||||
return await ctx.send(_("No Urban Dictionary entries were found."))
|
||||
if await ctx.embed_requested():
|
||||
# a list of embeds
|
||||
embeds = []
|
||||
@@ -303,14 +306,14 @@ class General(commands.Cog):
|
||||
else:
|
||||
messages = []
|
||||
for ud in data["list"]:
|
||||
ud.set_default("example", "N/A")
|
||||
ud.setdefault("example", "N/A")
|
||||
description = _("{definition}\n\n**Example:** {example}").format(**ud)
|
||||
if len(description) > 2048:
|
||||
description = "{}...".format(description[:2045])
|
||||
|
||||
message = _(
|
||||
"<{permalink}>\n {word} by {author}\n\n{description}\n\n"
|
||||
"{thumbs_down} Down / {thumbs_up} Up, Powered by urban dictionary"
|
||||
"{thumbs_down} Down / {thumbs_up} Up, Powered by Urban Dictionary."
|
||||
).format(word=ud.pop("word").capitalize(), description=description, **ud)
|
||||
messages.append(message)
|
||||
|
||||
@@ -325,6 +328,5 @@ class General(commands.Cog):
|
||||
)
|
||||
else:
|
||||
await ctx.send(
|
||||
_("No Urban dictionary entries were found, or there was an error in the process.")
|
||||
_("No Urban Dictionary entries were found, or there was an error in the process.")
|
||||
)
|
||||
return
|
||||
|
||||
@@ -311,13 +311,15 @@ class Mod(commands.Cog):
|
||||
if not cur_setting:
|
||||
await self.settings.guild(guild).reinvite_on_unban.set(True)
|
||||
await ctx.send(
|
||||
_("Users unbanned with {command} will be reinvited.").format(f"{ctx.prefix}unban")
|
||||
_("Users unbanned with {command} will be reinvited.").format(
|
||||
command=f"{ctx.prefix}unban"
|
||||
)
|
||||
)
|
||||
else:
|
||||
await self.settings.guild(guild).reinvite_on_unban.set(False)
|
||||
await ctx.send(
|
||||
_("Users unbanned with {command} will not be reinvited.").format(
|
||||
f"{ctx.prefix}unban"
|
||||
command=f"{ctx.prefix}unban"
|
||||
)
|
||||
)
|
||||
|
||||
@@ -864,20 +866,46 @@ class Mod(commands.Cog):
|
||||
@commands.guild_only()
|
||||
@commands.bot_has_permissions(manage_nicknames=True)
|
||||
@checks.admin_or_permissions(manage_nicknames=True)
|
||||
async def rename(self, ctx: commands.Context, user: discord.Member, *, nickname=""):
|
||||
async def rename(self, ctx: commands.Context, user: discord.Member, *, nickname: str = ""):
|
||||
"""Change a user's nickname.
|
||||
|
||||
Leaving the nickname empty will remove it.
|
||||
"""
|
||||
nickname = nickname.strip()
|
||||
if nickname == "":
|
||||
me = cast(discord.Member, ctx.me)
|
||||
if not nickname:
|
||||
nickname = None
|
||||
await user.edit(reason=get_audit_reason(ctx.author, None), nick=nickname)
|
||||
await ctx.send("Done.")
|
||||
elif not 2 <= len(nickname) <= 32:
|
||||
await ctx.send(_("Nicknames must be between 2 and 32 characters long."))
|
||||
return
|
||||
if not (
|
||||
(me.guild_permissions.manage_nicknames or me.guild_permissions.administrator)
|
||||
and me.top_role > user.top_role
|
||||
and user != ctx.guild.owner
|
||||
):
|
||||
await ctx.send(
|
||||
_(
|
||||
"I do not have permission to rename that member. They may be higher than or "
|
||||
"equal to me in the role hierarchy."
|
||||
)
|
||||
)
|
||||
else:
|
||||
try:
|
||||
await user.edit(reason=get_audit_reason(ctx.author, None), nick=nickname)
|
||||
except discord.Forbidden:
|
||||
# Just in case we missed something in the permissions check above
|
||||
await ctx.send(_("I do not have permission to rename that member."))
|
||||
except discord.HTTPException as exc:
|
||||
if exc.status == 400: # BAD REQUEST
|
||||
await ctx.send(_("That nickname is invalid."))
|
||||
else:
|
||||
await ctx.send(_("An unexpected error has occured."))
|
||||
else:
|
||||
await ctx.send(_("Done."))
|
||||
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.mod_or_permissions(manage_channel=True)
|
||||
@checks.mod_or_permissions(manage_channels=True)
|
||||
async def mute(self, ctx: commands.Context):
|
||||
"""Mute users."""
|
||||
pass
|
||||
@@ -1033,7 +1061,7 @@ class Mod(commands.Cog):
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@commands.bot_has_permissions(manage_roles=True)
|
||||
@checks.mod_or_permissions(manage_channel=True)
|
||||
@checks.mod_or_permissions(manage_channels=True)
|
||||
async def unmute(self, ctx: commands.Context):
|
||||
"""Unmute users."""
|
||||
pass
|
||||
@@ -1306,8 +1334,8 @@ class Mod(commands.Cog):
|
||||
user = author
|
||||
|
||||
# A special case for a special someone :^)
|
||||
special_date = datetime(2016, 1, 10, 6, 8, 4, 443000)
|
||||
is_special = user.id == 96130341705637888 and guild.id == 133049272517001216
|
||||
special_date = datetime(2016, 1, 10, 6, 8, 4, 443_000)
|
||||
is_special = user.id == 96_130_341_705_637_888 and guild.id == 133_049_272_517_001_216
|
||||
|
||||
roles = sorted(user.roles)[1:]
|
||||
names, nicks = await self.get_names_and_nicks(user)
|
||||
@@ -1567,8 +1595,9 @@ class Mod(commands.Cog):
|
||||
"""
|
||||
An event for modlog case creation
|
||||
"""
|
||||
mod_channel = await modlog.get_modlog_channel(case.guild)
|
||||
if mod_channel is None:
|
||||
try:
|
||||
mod_channel = await modlog.get_modlog_channel(case.guild)
|
||||
except RuntimeError:
|
||||
return
|
||||
use_embeds = await case.bot.embed_requested(mod_channel, case.guild.me)
|
||||
case_content = await case.message_content(use_embeds)
|
||||
|
||||
@@ -1,10 +1,133 @@
|
||||
from typing import NamedTuple, Union, Optional, cast, Type
|
||||
import itertools
|
||||
import re
|
||||
from typing import NamedTuple, Union, Optional
|
||||
|
||||
import discord
|
||||
|
||||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator
|
||||
|
||||
_ = Translator("PermissionsConverters", __file__)
|
||||
|
||||
MENTION_RE = re.compile(r"^<?(?:(?:@[!&]?)?|#)(\d{15,21})>?$")
|
||||
|
||||
|
||||
def _match_id(arg: str) -> Optional[int]:
|
||||
m = MENTION_RE.match(arg)
|
||||
if m:
|
||||
return int(m.group(1))
|
||||
|
||||
|
||||
class GlobalUniqueObjectFinder(commands.Converter):
|
||||
async def convert(
|
||||
self, ctx: commands.Context, arg: str
|
||||
) -> Union[discord.Guild, discord.abc.GuildChannel, discord.abc.User, discord.Role]:
|
||||
bot: commands.Bot = ctx.bot
|
||||
_id = _match_id(arg)
|
||||
|
||||
if _id is not None:
|
||||
guild: discord.Guild = bot.get_guild(_id)
|
||||
if guild is not None:
|
||||
return guild
|
||||
channel: discord.abc.GuildChannel = bot.get_channel(_id)
|
||||
if channel is not None:
|
||||
return channel
|
||||
|
||||
user: discord.User = bot.get_user(_id)
|
||||
if user is not None:
|
||||
return user
|
||||
|
||||
for guild in bot.guilds:
|
||||
role: discord.Role = guild.get_role(_id)
|
||||
if role is not None:
|
||||
return role
|
||||
|
||||
objects = itertools.chain(
|
||||
bot.get_all_channels(),
|
||||
bot.users,
|
||||
bot.guilds,
|
||||
*(filter(lambda r: not r.is_default(), guild.roles) for guild in bot.guilds),
|
||||
)
|
||||
|
||||
maybe_matches = []
|
||||
for obj in objects:
|
||||
if obj.name == arg or str(obj) == arg:
|
||||
maybe_matches.append(obj)
|
||||
|
||||
if ctx.guild is not None:
|
||||
for member in ctx.guild.members:
|
||||
if member.nick == arg and not any(obj.id == member.id for obj in maybe_matches):
|
||||
maybe_matches.append(member)
|
||||
|
||||
if not maybe_matches:
|
||||
raise commands.BadArgument(
|
||||
_(
|
||||
'"{arg}" was not found. It must be the ID, mention, or name of a server, '
|
||||
"channel, user or role which the bot can see."
|
||||
).format(arg=arg)
|
||||
)
|
||||
elif len(maybe_matches) == 1:
|
||||
return maybe_matches[0]
|
||||
else:
|
||||
raise commands.BadArgument(
|
||||
_(
|
||||
'"{arg}" does not refer to a unique server, channel, user or role. Please use '
|
||||
"the ID for whatever/whoever you're trying to specify, or mention it/them."
|
||||
).format(arg=arg)
|
||||
)
|
||||
|
||||
|
||||
class GuildUniqueObjectFinder(commands.Converter):
|
||||
async def convert(
|
||||
self, ctx: commands.Context, arg: str
|
||||
) -> Union[discord.abc.GuildChannel, discord.Member, discord.Role]:
|
||||
guild: discord.Guild = ctx.guild
|
||||
_id = _match_id(arg)
|
||||
|
||||
if _id is not None:
|
||||
channel: discord.abc.GuildChannel = guild.get_channel(_id)
|
||||
if channel is not None:
|
||||
return channel
|
||||
|
||||
member: discord.Member = guild.get_member(_id)
|
||||
if member is not None:
|
||||
return member
|
||||
|
||||
role: discord.Role = guild.get_role(_id)
|
||||
if role is not None and not role.is_default():
|
||||
return role
|
||||
|
||||
objects = itertools.chain(
|
||||
guild.channels, guild.members, filter(lambda r: not r.is_default(), guild.roles)
|
||||
)
|
||||
|
||||
maybe_matches = []
|
||||
for obj in objects:
|
||||
if obj.name == arg or str(obj) == arg:
|
||||
maybe_matches.append(obj)
|
||||
try:
|
||||
if obj.nick == arg:
|
||||
maybe_matches.append(obj)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if not maybe_matches:
|
||||
raise commands.BadArgument(
|
||||
_(
|
||||
'"{arg}" was not found. It must be the ID, mention, or name of a channel, '
|
||||
"user or role in this server."
|
||||
).format(arg=arg)
|
||||
)
|
||||
elif len(maybe_matches) == 1:
|
||||
return maybe_matches[0]
|
||||
else:
|
||||
raise commands.BadArgument(
|
||||
_(
|
||||
'"{arg}" does not refer to a unique channel, user or role. Please use the ID '
|
||||
"for whatever/whoever you're trying to specify, or mention it/them."
|
||||
).format(arg=arg)
|
||||
)
|
||||
|
||||
|
||||
class CogOrCommand(NamedTuple):
|
||||
type: str
|
||||
|
||||
@@ -14,7 +14,13 @@ from redbot.core.utils.chat_formatting import box
|
||||
from redbot.core.utils.menus import start_adding_reactions
|
||||
from redbot.core.utils.predicates import ReactionPredicate, MessagePredicate
|
||||
|
||||
from .converters import CogOrCommand, RuleType, ClearableRuleType
|
||||
from .converters import (
|
||||
CogOrCommand,
|
||||
RuleType,
|
||||
ClearableRuleType,
|
||||
GuildUniqueObjectFinder,
|
||||
GlobalUniqueObjectFinder,
|
||||
)
|
||||
|
||||
_ = Translator("Permissions", __file__)
|
||||
|
||||
@@ -142,23 +148,20 @@ class Permissions(commands.Cog):
|
||||
if not command:
|
||||
return await ctx.send_help()
|
||||
|
||||
message = copy(ctx.message)
|
||||
message.author = user
|
||||
message.content = "{}{}".format(ctx.prefix, command)
|
||||
fake_message = copy(ctx.message)
|
||||
fake_message.author = user
|
||||
fake_message.content = "{}{}".format(ctx.prefix, command)
|
||||
|
||||
com = ctx.bot.get_command(command)
|
||||
if com is None:
|
||||
out = _("No such command")
|
||||
else:
|
||||
fake_context = await ctx.bot.get_context(fake_message)
|
||||
try:
|
||||
testcontext = await ctx.bot.get_context(message, cls=commands.Context)
|
||||
to_check = [*reversed(com.parents)] + [com]
|
||||
can = False
|
||||
for cmd in to_check:
|
||||
can = await cmd.can_run(testcontext)
|
||||
if can is False:
|
||||
break
|
||||
except commands.CheckFailure:
|
||||
can = await com.can_run(
|
||||
fake_context, check_all_parents=True, change_permission_state=False
|
||||
)
|
||||
except commands.CommandError:
|
||||
can = False
|
||||
|
||||
out = (
|
||||
@@ -275,7 +278,7 @@ class Permissions(commands.Cog):
|
||||
ctx: commands.Context,
|
||||
allow_or_deny: RuleType,
|
||||
cog_or_command: CogOrCommand,
|
||||
who_or_what: commands.GlobalPermissionModel,
|
||||
who_or_what: GlobalUniqueObjectFinder,
|
||||
):
|
||||
"""Add a global rule to a command.
|
||||
|
||||
@@ -303,7 +306,7 @@ class Permissions(commands.Cog):
|
||||
ctx: commands.Context,
|
||||
allow_or_deny: RuleType,
|
||||
cog_or_command: CogOrCommand,
|
||||
who_or_what: commands.GuildPermissionModel,
|
||||
who_or_what: GuildUniqueObjectFinder,
|
||||
):
|
||||
"""Add a rule to a command in this server.
|
||||
|
||||
@@ -328,7 +331,7 @@ class Permissions(commands.Cog):
|
||||
self,
|
||||
ctx: commands.Context,
|
||||
cog_or_command: CogOrCommand,
|
||||
who_or_what: commands.GlobalPermissionModel,
|
||||
who_or_what: GlobalUniqueObjectFinder,
|
||||
):
|
||||
"""Remove a global rule from a command.
|
||||
|
||||
@@ -351,7 +354,7 @@ class Permissions(commands.Cog):
|
||||
ctx: commands.Context,
|
||||
cog_or_command: CogOrCommand,
|
||||
*,
|
||||
who_or_what: commands.GuildPermissionModel,
|
||||
who_or_what: GuildUniqueObjectFinder,
|
||||
):
|
||||
"""Remove a server rule from a command.
|
||||
|
||||
|
||||
@@ -316,7 +316,7 @@ class Reports(commands.Cog):
|
||||
self.tunnel_store[k]["msgs"] = msgs
|
||||
|
||||
@commands.guild_only()
|
||||
@checks.mod_or_permissions(manage_members=True)
|
||||
@checks.mod_or_permissions(manage_roles=True)
|
||||
@report.command(name="interact")
|
||||
async def response(self, ctx, ticket_number: int):
|
||||
"""Open a message tunnel.
|
||||
|
||||
@@ -28,7 +28,7 @@ from . import streamtypes as _streamtypes
|
||||
from collections import defaultdict
|
||||
import asyncio
|
||||
import re
|
||||
from typing import Optional, List
|
||||
from typing import Optional, List, Tuple
|
||||
|
||||
CHECK_DELAY = 60
|
||||
|
||||
@@ -320,6 +320,7 @@ class Streams(commands.Cog):
|
||||
@commands.group()
|
||||
@checks.mod()
|
||||
async def streamset(self, ctx: commands.Context):
|
||||
"""Set tokens for accessing streams."""
|
||||
pass
|
||||
|
||||
@streamset.command()
|
||||
@@ -396,9 +397,6 @@ class Streams(commands.Cog):
|
||||
async def role(self, ctx: commands.Context, *, role: discord.Role):
|
||||
"""Toggle a role mention."""
|
||||
current_setting = await self.db.role(role).mention()
|
||||
if not role.mentionable:
|
||||
await ctx.send("That role is not mentionable!")
|
||||
return
|
||||
if current_setting:
|
||||
await self.db.role(role).mention.set(False)
|
||||
await ctx.send(
|
||||
@@ -408,11 +406,17 @@ class Streams(commands.Cog):
|
||||
)
|
||||
else:
|
||||
await self.db.role(role).mention.set(True)
|
||||
await ctx.send(
|
||||
_(
|
||||
"When a stream or community is live, `@\u200b{role.name}` will be mentioned."
|
||||
).format(role=role)
|
||||
)
|
||||
msg = _(
|
||||
"When a stream or community is live, `@\u200b{role.name}` will be mentioned."
|
||||
).format(role=role)
|
||||
if not role.mentionable:
|
||||
msg += " " + _(
|
||||
"Since the role is not mentionable, it will be momentarily made mentionable "
|
||||
"when announcing a streamalert. Please make sure I have the correct "
|
||||
"permissions to manage this role, or else members of this role won't receive "
|
||||
"a notification."
|
||||
)
|
||||
await ctx.send(msg)
|
||||
|
||||
@streamset.command()
|
||||
@commands.guild_only()
|
||||
@@ -535,30 +539,46 @@ class Streams(commands.Cog):
|
||||
continue
|
||||
for channel_id in stream.channels:
|
||||
channel = self.bot.get_channel(channel_id)
|
||||
mention_str = await self._get_mention_str(channel.guild)
|
||||
mention_str, edited_roles = await self._get_mention_str(channel.guild)
|
||||
|
||||
if mention_str:
|
||||
content = _("{mention}, {stream.name} is live!").format(
|
||||
mention=mention_str, stream=stream
|
||||
)
|
||||
else:
|
||||
content = _("{stream.name} is live!").format(stream=stream.name)
|
||||
content = _("{stream.name} is live!").format(stream=stream)
|
||||
|
||||
m = await channel.send(content, embed=embed)
|
||||
stream._messages_cache.append(m)
|
||||
if edited_roles:
|
||||
for role in edited_roles:
|
||||
await role.edit(mentionable=False)
|
||||
await self.save_streams()
|
||||
|
||||
async def _get_mention_str(self, guild: discord.Guild):
|
||||
async def _get_mention_str(self, guild: discord.Guild) -> Tuple[str, List[discord.Role]]:
|
||||
"""Returns a 2-tuple with the string containing the mentions, and a list of
|
||||
all roles which need to have their `mentionable` property set back to False.
|
||||
"""
|
||||
settings = self.db.guild(guild)
|
||||
mentions = []
|
||||
edited_roles = []
|
||||
if await settings.mention_everyone():
|
||||
mentions.append("@everyone")
|
||||
if await settings.mention_here():
|
||||
mentions.append("@here")
|
||||
can_manage_roles = guild.me.guild_permissions.manage_roles
|
||||
for role in guild.roles:
|
||||
if await self.db.role(role).mention():
|
||||
if can_manage_roles and not role.mentionable:
|
||||
try:
|
||||
await role.edit(mentionable=True)
|
||||
except discord.Forbidden:
|
||||
# Might still be unable to edit role based on hierarchy
|
||||
pass
|
||||
else:
|
||||
edited_roles.append(role)
|
||||
mentions.append(role.mention)
|
||||
return " ".join(mentions)
|
||||
return " ".join(mentions), edited_roles
|
||||
|
||||
async def check_communities(self):
|
||||
for community in self.communities:
|
||||
@@ -589,12 +609,15 @@ class Streams(commands.Cog):
|
||||
emb = await community.make_embed(streams)
|
||||
chn_msg = [m for m in community._messages_cache if m.channel == chn]
|
||||
if not chn_msg:
|
||||
mentions = await self._get_mention_str(chn.guild)
|
||||
mentions, roles = await self._get_mention_str(chn.guild)
|
||||
if mentions:
|
||||
msg = await chn.send(mentions, embed=emb)
|
||||
else:
|
||||
msg = await chn.send(embed=emb)
|
||||
community._messages_cache.append(msg)
|
||||
if roles:
|
||||
for role in roles:
|
||||
await role.edit(mentionable=False)
|
||||
await self.save_communities()
|
||||
else:
|
||||
chn_msg = sorted(chn_msg, key=lambda x: x.created_at, reverse=True)[0]
|
||||
|
||||
@@ -114,7 +114,7 @@ class TriviaSession:
|
||||
async with self.ctx.typing():
|
||||
await asyncio.sleep(3)
|
||||
self.count += 1
|
||||
msg = bold(_("**Question number {num}!").format(num=self.count)) + "\n\n" + question
|
||||
msg = bold(_("Question number {num}!").format(num=self.count)) + "\n\n" + question
|
||||
await self.ctx.send(msg)
|
||||
continue_ = await self.wait_for_answer(answers, delay, timeout)
|
||||
if continue_ is False:
|
||||
|
||||
@@ -111,16 +111,14 @@ class Trivia(commands.Cog):
|
||||
await settings.allow_override.set(enabled)
|
||||
if enabled:
|
||||
await ctx.send(
|
||||
_(
|
||||
"Done. Trivia lists can now override the trivia settings for this server."
|
||||
).format(now=enabled)
|
||||
_("Done. Trivia lists can now override the trivia settings for this server.")
|
||||
)
|
||||
else:
|
||||
await ctx.send(
|
||||
_(
|
||||
"Done. Trivia lists can no longer override the trivia settings for this "
|
||||
"server."
|
||||
).format(now=enabled)
|
||||
)
|
||||
)
|
||||
|
||||
@triviaset.command(name="botplays", usage="<true_or_false>")
|
||||
@@ -506,7 +504,7 @@ class Trivia(commands.Cog):
|
||||
|
||||
with path.open(encoding="utf-8") as file:
|
||||
try:
|
||||
dict_ = yaml.load(file)
|
||||
dict_ = yaml.safe_load(file)
|
||||
except yaml.error.YAMLError as exc:
|
||||
raise InvalidListError("YAML parsing failed.") from exc
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user