Skip to content

Commit

Permalink
Merge branch 'V3/develop' into feature/Cog-Creators#6460-download-tim…
Browse files Browse the repository at this point in the history
…eout
  • Loading branch information
Jackenmen authored Dec 24, 2024

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
2 parents ee3646a + fdaa869 commit 5a19214
Showing 19 changed files with 374 additions and 44 deletions.
9 changes: 0 additions & 9 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -26,14 +26,6 @@ unsafe-load-any-extension=no
# run arbitrary code
extension-pkg-whitelist=

# Allow optimization of some AST trees. This will activate a peephole AST
# optimizer, which will apply various small optimizations. For instance, it can
# be used to obtain the result of joining multiple strings with the addition
# operator. Joining a lot of strings can lead to a maximum recursion error in
# Pylint and this flag can prevent that. It has one side effect, the resulting
# AST will be different than the one from reality.
optimize-ast=no


[MESSAGES CONTROL]

@@ -66,7 +58,6 @@ disable=C, # black is enforcing this for us already, incompatibly
[REPORTS]

output-format=parseable
files-output=no
reports=no


22 changes: 22 additions & 0 deletions docs/cog_guides/mod.rst
Original file line number Diff line number Diff line change
@@ -266,6 +266,28 @@ and reason as to why they were kicked/banned.

* ``[enabled]``: Whether a message should be sent to a user when they are kicked/banned. |bool-input|

.. _mod-command-modset-requirereason:

""""""""""""""""""""
modset requirereason
""""""""""""""""""""

**Syntax**

.. code-block:: none
[p]modset requirereason [enabled]
**Description**

Toggle whether a reason is required for mod actions.

If this is enabled, the bot will require a reason to be provided for all mod actions.

**Arguments**

* ``[enabled]``: Whether a reason should be required when performing mod actions. |bool-input|

.. _mod-command-modset-hierarchy:

""""""""""""""""
30 changes: 25 additions & 5 deletions redbot/cogs/audio/managed_node/ll_server_config.py
Original file line number Diff line number Diff line change
@@ -50,16 +50,36 @@
"yaml__plugins__youtube__clients": [
"MUSIC",
"WEB",
"ANDROID_TESTSUITE",
"WEBEMBEDDED",
"MWEB",
"TVHTML5EMBEDDED",
"ANDROID_LITE",
"MEDIA_CONNECT",
"TV",
"IOS",
],
"yaml__plugins__youtube__WEB__playback": True,
"yaml__plugins__youtube__MUSIC__playback": False,
"yaml__plugins__youtube__MUSIC__playlistLoading": False,
"yaml__plugins__youtube__MUSIC__searching": True,
"yaml__plugins__youtube__MUSIC__videoLoading": False,
"yaml__plugins__youtube__MWEB__playback": True,
"yaml__plugins__youtube__MWEB__playlistLoading": True,
"yaml__plugins__youtube__MWEB__searching": False,
"yaml__plugins__youtube__MWEB__videoLoading": False,
"yaml__plugins__youtube__TV__playback": True,
"yaml__plugins__youtube__TV__playlistLoading": False,
"yaml__plugins__youtube__TV__searching": False,
"yaml__plugins__youtube__TV__videoLoading": False,
"yaml__plugins__youtube__TVHTML5EMBEDDED__playback": True,
"yaml__plugins__youtube__TVHTML5EMBEDDED__playlistLoading": False,
"yaml__plugins__youtube__TVHTML5EMBEDDED__videoLoading": False,
"yaml__plugins__youtube__TVHTML5EMBEDDED__searching": False,
"yaml__plugins__youtube__TVHTML5EMBEDDED__videoLoading": False,
"yaml__plugins__youtube__WEB__playback": True,
"yaml__plugins__youtube__WEB__playlistLoading": True,
"yaml__plugins__youtube__WEB__searching": False,
"yaml__plugins__youtube__WEB__videoLoading": False,
"yaml__plugins__youtube__WEBEMBEDDED__playback": True,
"yaml__plugins__youtube__WEBEMBEDDED__playlistLoading": False,
"yaml__plugins__youtube__WEBEMBEDDED__searching": False,
"yaml__plugins__youtube__WEBEMBEDDED__videoLoading": False,
}


2 changes: 1 addition & 1 deletion redbot/cogs/audio/managed_node/version_pins.py
Original file line number Diff line number Diff line change
@@ -6,4 +6,4 @@


JAR_VERSION: Final[LavalinkVersion] = LavalinkVersion(3, 7, 12, red=1)
YT_PLUGIN_VERSION: Final[str] = "1.7.2"
YT_PLUGIN_VERSION: Final[str] = "1.11.2"
18 changes: 13 additions & 5 deletions redbot/cogs/downloader/downloader.py
Original file line number Diff line number Diff line change
@@ -648,14 +648,18 @@ async def _repo_list(self, ctx: commands.Context) -> None:
joined = _("There are no repos installed.")
else:
if len(repos) > 1:
joined = _("# Installed Repos\n")
joined = _("## Installed Repos\n")
else:
joined = _("# Installed Repo\n")
joined = _("## Installed Repo\n")
for repo in sorted_repos:
joined += "+ {}: {}\n".format(repo.name, repo.short or "")
joined += "- **{}:** {}\n - {}\n".format(
repo.name,
repo.short or "",
"<{}>".format(repo.url),
)

for page in pagify(joined, ["\n"], shorten_by=16):
await ctx.send(box(page.lstrip(" "), lang="markdown"))
await ctx.send(page)

@repo.command(name="info")
async def _repo_info(self, ctx: commands.Context, repo: Repo) -> None:
@@ -932,7 +936,11 @@ async def _cog_installrev(
await self.send_pagified(ctx, f"{message}{deprecation_notice}\n---")
for cog in installed_cogs:
if cog.install_msg:
await ctx.send(cog.install_msg.replace("[p]", ctx.clean_prefix))
await ctx.send(
cog.install_msg.replace("[p]", ctx.clean_prefix).replace(
"[botname]", ctx.me.display_name
)
)

@cog.command(name="uninstall", require_var_positional=True)
async def _cog_uninstall(self, ctx: commands.Context, *cogs: InstalledCog) -> None:
35 changes: 35 additions & 0 deletions redbot/cogs/mod/kickban.py
Original file line number Diff line number Diff line change
@@ -117,6 +117,9 @@ async def ban_user(

removed_temp = False

if reason is None and await self.config.guild(guild).require_reason():
return False, _("You must provide a reason for the ban.")

if not (0 <= days <= 7):
return False, _("Invalid days. Must be between 0 and 7.")

@@ -303,6 +306,10 @@ async def kick(self, ctx: commands.Context, member: discord.Member, *, reason: s
author = ctx.author
guild = ctx.guild

if reason is None and await self.config.guild(guild).require_reason():
await ctx.send(_("You must provide a reason for the kick."))
return

if author == member:
await ctx.send(
_("I cannot let you do that. Self-harm is bad {emoji}").format(
@@ -428,6 +435,10 @@ async def massban(
errors = {}
upgrades = []

if reason is None and await self.config.guild(ctx.guild).require_reason():
await ctx.send(_("You must provide a reason for the massban."))
return

async def show_results():
text = _("Banned {num} users from the server.").format(
num=humanize_number(len(banned))
@@ -605,6 +616,10 @@ async def tempban(
guild = ctx.guild
author = ctx.author

if reason is None and await self.config.guild(guild).require_reason():
await ctx.send(_("You must provide a reason for the temporary ban."))
return

if author == member:
await ctx.send(
_("I cannot let you do that. Self-harm is bad {}").format("\N{PENSIVE FACE}")
@@ -684,6 +699,10 @@ async def softban(self, ctx: commands.Context, member: discord.Member, *, reason
guild = ctx.guild
author = ctx.author

if reason is None and await self.config.guild(guild).require_reason():
await ctx.send(_("You must provide a reason for the softban."))
return

if author == member:
await ctx.send(
_("I cannot let you do that. Self-harm is bad {emoji}").format(
@@ -771,6 +790,10 @@ async def voicekick(
self, ctx: commands.Context, member: discord.Member, *, reason: str = None
):
"""Kick a member from a voice channel."""
if reason is None and await self.config.guild(ctx.guild).require_reason():
await ctx.send(_("You must provide a reason for the voice kick."))
return

author = ctx.author
guild = ctx.guild
user_voice_state: discord.VoiceState = member.voice
@@ -818,6 +841,10 @@ async def voiceunban(
self, ctx: commands.Context, member: discord.Member, *, reason: str = None
):
"""Unban a user from speaking and listening in the server's voice channels."""
if reason is None and await self.config.guild(ctx.guild).require_reason():
await ctx.send(_("You must provide a reason for the voice unban."))
return

user_voice_state = member.voice
if (
await self._voice_perm_check(
@@ -859,6 +886,10 @@ async def voiceunban(
@commands.admin_or_permissions(mute_members=True, deafen_members=True)
async def voiceban(self, ctx: commands.Context, member: discord.Member, *, reason: str = None):
"""Ban a user from speaking and listening in the server's voice channels."""
if reason is None and await self.config.guild(ctx.guild).require_reason():
await ctx.send(_("You must provide a reason for the voice ban."))
return

user_voice_state: discord.VoiceState = member.voice
if (
await self._voice_perm_check(
@@ -908,6 +939,10 @@ async def unban(
1. Copy it from the mod log case (if one was created), or
2. Enable Developer Mode, go to Bans in this server's settings, right-click the user and select 'Copy ID'.
"""
if reason is None and await self.config.guild(ctx.guild).require_reason():
await ctx.send(_("You must provide a reason for the unban."))
return

guild = ctx.guild
author = ctx.author
audit_reason = get_audit_reason(ctx.author, reason, shorten=True)
1 change: 1 addition & 0 deletions redbot/cogs/mod/mod.py
Original file line number Diff line number Diff line change
@@ -57,6 +57,7 @@ class Mod(
"reinvite_on_unban": False,
"current_tempbans": [],
"dm_on_kickban": False,
"require_reason": False,
"default_days": 0,
"default_tempban_duration": 60 * 60 * 24,
"track_nicknames": True,
23 changes: 23 additions & 0 deletions redbot/cogs/mod/settings.py
Original file line number Diff line number Diff line change
@@ -370,6 +370,29 @@ async def dm(self, ctx: commands.Context, enabled: bool = None):
_("Bot will no longer attempt to send a DM to user before kick and ban.")
)

@modset.command()
@commands.guild_only()
async def requirereason(self, ctx: commands.Context, enabled: bool = None):
"""
Toggle whether a reason is required for mod actions.
If this is enabled, the bot will require a reason to be provided for all mod actions.
"""
guild = ctx.guild
if enabled is None:
setting = await self.config.guild(guild).require_reason()
await ctx.send(
_("Mod action reason requirement is currently set to: {setting}").format(
setting=setting
)
)
return
await self.config.guild(guild).require_reason.set(enabled)
if enabled:
await ctx.send(_("Bot will now require a reason for all mod actions."))
else:
await ctx.send(_("Bot will no longer require a reason for all mod actions."))

@modset.command()
@commands.guild_only()
async def defaultdays(self, ctx: commands.Context, days: int = 0):
6 changes: 4 additions & 2 deletions redbot/cogs/trivia/data/lists/harrypotter.yaml
Original file line number Diff line number Diff line change
@@ -98,6 +98,7 @@ What are draco's parents' names?:
- Narcissa and Lucious
What book does Hermione insist Ron and Harry read?:
- Hogwarts, A History
- Hogwarts A History
What breed was Hagrid's pet dragon?:
- Norwegian Ridgeback
What color are unicorn foals?:
@@ -194,7 +195,7 @@ What is Severus Snape's mother's first name?:
What is Tonks's first name?:
- Nymphadora
What is considered Harry's 'trademark spell'?:
- Expelliarmus.
- Expelliarmus
What is the Hogwarts School motto in English?:
- Never Tickle a Sleeping Dragon
What is the age requirement for an Apparation License?:
@@ -222,6 +223,7 @@ What is the name of Dumbledore's phoenix?:
- fawkes
What is the name of Filch's cat?:
- Mrs. Norris
- Mrs Norris
What is the name of Harry Potter’s pet owl?:
- Hedwig
What is the name of Harry's aunt?:
@@ -609,4 +611,4 @@ How many hours into the past do Harry and Hermione travel in an attempt to rescu
- Three
How many muggles did Peter Pettigrew kill when he faked his own death?:
- 12
- Twelve
- Twelve
17 changes: 10 additions & 7 deletions redbot/cogs/trivia/trivia.py
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@

UNIQUE_ID = 0xB3C0E453
_ = Translator("Trivia", __file__)
YAMLSafeLoader = getattr(yaml, "CSafeLoader", yaml.SafeLoader)


class InvalidListError(Exception):
@@ -759,7 +760,7 @@ async def _save_trivia_list(
return

buffer = io.BytesIO(await attachment.read())
trivia_dict = yaml.safe_load(buffer)
trivia_dict = yaml.load(buffer, YAMLSafeLoader)
TRIVIA_LIST_SCHEMA.validate(trivia_dict)

buffer.seek(0)
@@ -803,7 +804,7 @@ def get_core_lists() -> List[pathlib.Path]:
return list(core_lists_path.glob("*.yaml"))


def get_list(path: pathlib.Path) -> Dict[str, Any]:
def get_list(path: pathlib.Path, *, validate_schema: bool = True) -> Dict[str, Any]:
"""
Returns a trivia list dictionary from the given path.
@@ -814,12 +815,14 @@ def get_list(path: pathlib.Path) -> Dict[str, Any]:
"""
with path.open(encoding="utf-8") as file:
try:
trivia_dict = yaml.safe_load(file)
trivia_dict = yaml.load(file, YAMLSafeLoader)
except yaml.error.YAMLError as exc:
raise InvalidListError("YAML parsing failed.") from exc

try:
TRIVIA_LIST_SCHEMA.validate(trivia_dict)
except schema.SchemaError as exc:
raise InvalidListError("The list does not adhere to the schema.") from exc
if validate_schema:
try:
TRIVIA_LIST_SCHEMA.validate(trivia_dict)
except schema.SchemaError as exc:
raise InvalidListError("The list does not adhere to the schema.") from exc

return trivia_dict
Loading

0 comments on commit 5a19214

Please sign in to comment.