mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-21 18:27:59 -05:00
[V3 i18n] Internationalise help for commands and cogs (#1143)
* Framework for internationalised command help * Translator for class docstring of cog * Remove references to old context module * Use CogManagerUI as PoC * Replace all references to RedContext * Rename CogI18n object to avoid confusion * Update docs * Update i18n docs. * Store translators in list instead of dict * Change commands module to package, updated refs in cogs * Updated docs and more references in cogs * Resolve syntax error * Update from merge
This commit is contained in:
@@ -3,21 +3,20 @@ from datetime import datetime, timedelta
|
||||
from collections import deque, defaultdict, namedtuple
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core import checks, Config, modlog, RedContext
|
||||
from redbot.core import checks, Config, modlog, commands
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import box, escape
|
||||
from .checks import mod_or_voice_permissions, admin_or_voice_permissions, bot_has_voice_permissions
|
||||
from redbot.core.utils.mod import is_mod_or_superior, is_allowed_by_hierarchy, \
|
||||
get_audit_reason
|
||||
from .log import log
|
||||
|
||||
_ = CogI18n("Mod", __file__)
|
||||
|
||||
_ = Translator("Mod", __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Mod:
|
||||
"""Moderation tools."""
|
||||
|
||||
@@ -174,7 +173,7 @@ class Mod:
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.guildowner_or_permissions(administrator=True)
|
||||
async def modset(self, ctx: RedContext):
|
||||
async def modset(self, ctx: commands.Context):
|
||||
"""Manages server administration settings."""
|
||||
if ctx.invoked_subcommand is None:
|
||||
guild = ctx.guild
|
||||
@@ -200,7 +199,7 @@ class Mod:
|
||||
|
||||
@modset.command()
|
||||
@commands.guild_only()
|
||||
async def hierarchy(self, ctx: RedContext):
|
||||
async def hierarchy(self, ctx: commands.Context):
|
||||
"""Toggles role hierarchy check for mods / admins"""
|
||||
guild = ctx.guild
|
||||
toggled = await self.settings.guild(guild).respect_hierarchy()
|
||||
@@ -215,7 +214,7 @@ class Mod:
|
||||
|
||||
@modset.command()
|
||||
@commands.guild_only()
|
||||
async def banmentionspam(self, ctx: RedContext, max_mentions: int=False):
|
||||
async def banmentionspam(self, ctx: commands.Context, max_mentions: int=False):
|
||||
"""Enables auto ban for messages mentioning X different people
|
||||
|
||||
Accepted values: 5 or superior"""
|
||||
@@ -240,7 +239,7 @@ class Mod:
|
||||
|
||||
@modset.command()
|
||||
@commands.guild_only()
|
||||
async def deleterepeats(self, ctx: RedContext):
|
||||
async def deleterepeats(self, ctx: commands.Context):
|
||||
"""Enables auto deletion of repeated messages"""
|
||||
guild = ctx.guild
|
||||
cur_setting = await self.settings.guild(guild).delete_repeats()
|
||||
@@ -254,7 +253,7 @@ class Mod:
|
||||
|
||||
@modset.command()
|
||||
@commands.guild_only()
|
||||
async def deletedelay(self, ctx: RedContext, time: int=None):
|
||||
async def deletedelay(self, ctx: commands.Context, time: int=None):
|
||||
"""Sets the delay until the bot removes the command message.
|
||||
|
||||
Must be between -1 and 60.
|
||||
@@ -281,7 +280,7 @@ class Mod:
|
||||
|
||||
@modset.command()
|
||||
@commands.guild_only()
|
||||
async def reinvite(self, ctx: RedContext):
|
||||
async def reinvite(self, ctx: commands.Context):
|
||||
"""Toggles whether an invite will be sent when a user is unbanned via [p]unban.
|
||||
|
||||
If this is True, the bot will attempt to create and send a single-use invite
|
||||
@@ -298,7 +297,7 @@ class Mod:
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(kick_members=True)
|
||||
async def kick(self, ctx: RedContext, user: discord.Member, *, reason: str = None):
|
||||
async def kick(self, ctx: commands.Context, user: discord.Member, *, reason: str = None):
|
||||
"""Kicks user.
|
||||
|
||||
If a reason is specified, it will be the reason that shows up
|
||||
@@ -338,7 +337,7 @@ class Mod:
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(ban_members=True)
|
||||
async def ban(self, ctx: RedContext, user: discord.Member, days: str = None, *, reason: str = None):
|
||||
async def ban(self, ctx: commands.Context, user: discord.Member, days: str = None, *, reason: str = None):
|
||||
"""Bans user and deletes last X days worth of messages.
|
||||
|
||||
If days is not a number, it's treated as the first word of the reason.
|
||||
@@ -399,7 +398,7 @@ class Mod:
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(ban_members=True)
|
||||
async def hackban(self, ctx: RedContext, user_id: int, *, reason: str = None):
|
||||
async def hackban(self, ctx: commands.Context, user_id: int, *, reason: str = None):
|
||||
"""Preemptively bans user from the server
|
||||
|
||||
A user ID needs to be provided in order to ban
|
||||
@@ -452,7 +451,7 @@ class Mod:
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(ban_members=True)
|
||||
async def tempban(self, ctx: RedContext, user: discord.Member, days: int=1, *, reason: str=None):
|
||||
async def tempban(self, ctx: commands.Context, user: discord.Member, days: int=1, *, reason: str=None):
|
||||
"""Tempbans the user for the specified number of days"""
|
||||
guild = ctx.guild
|
||||
author = ctx.author
|
||||
@@ -500,7 +499,7 @@ class Mod:
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(ban_members=True)
|
||||
async def softban(self, ctx: RedContext, user: discord.Member, *, reason: str = None):
|
||||
async def softban(self, ctx: commands.Context, user: discord.Member, *, reason: str = None):
|
||||
"""Kicks the user, deleting 1 day worth of messages."""
|
||||
guild = ctx.guild
|
||||
channel = ctx.channel
|
||||
@@ -579,7 +578,7 @@ class Mod:
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(ban_members=True)
|
||||
@commands.bot_has_permissions(ban_members=True)
|
||||
async def unban(self, ctx: RedContext, user_id: int, *, reason: str = None):
|
||||
async def unban(self, ctx: commands.Context, user_id: int, *, reason: str = None):
|
||||
"""Unbans the target user.
|
||||
|
||||
Requires specifying the target user's ID. To find this, you may either:
|
||||
@@ -637,7 +636,7 @@ class Mod:
|
||||
.format(invite.url))
|
||||
|
||||
@staticmethod
|
||||
async def get_invite_for_reinvite(ctx: RedContext, max_age: int=86400):
|
||||
async def get_invite_for_reinvite(ctx: commands.Context, max_age: int=86400):
|
||||
"""Handles the reinvite logic for getting an invite
|
||||
to send the newly unbanned user
|
||||
:returns: :class:`Invite`"""
|
||||
@@ -672,7 +671,7 @@ class Mod:
|
||||
@commands.guild_only()
|
||||
@admin_or_voice_permissions(mute_members=True, deafen_members=True)
|
||||
@bot_has_voice_permissions(mute_members=True, deafen_members=True)
|
||||
async def voiceban(self, ctx: RedContext, user: discord.Member, *, reason: str=None):
|
||||
async def voiceban(self, ctx: commands.Context, user: discord.Member, *, reason: str=None):
|
||||
"""Bans the target user from speaking and listening in voice channels in the server"""
|
||||
user_voice_state = user.voice
|
||||
if user_voice_state is None:
|
||||
@@ -709,7 +708,7 @@ class Mod:
|
||||
@commands.guild_only()
|
||||
@admin_or_voice_permissions(mute_members=True, deafen_members=True)
|
||||
@bot_has_voice_permissions(mute_members=True, deafen_members=True)
|
||||
async def voiceunban(self, ctx: RedContext, user: discord.Member, *, reason: str=None):
|
||||
async def voiceunban(self, ctx: commands.Context, user: discord.Member, *, reason: str=None):
|
||||
"""Unbans the user from speaking/listening in the server's voice channels"""
|
||||
user_voice_state = user.voice
|
||||
if user_voice_state is None:
|
||||
@@ -743,7 +742,7 @@ class Mod:
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(manage_nicknames=True)
|
||||
async def rename(self, ctx: RedContext, user: discord.Member, *, nickname=""):
|
||||
async def rename(self, ctx: commands.Context, user: discord.Member, *, nickname=""):
|
||||
"""Changes user's nickname
|
||||
|
||||
Leaving the nickname empty will remove it."""
|
||||
@@ -763,7 +762,7 @@ class Mod:
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.mod_or_permissions(manage_channel=True)
|
||||
async def mute(self, ctx: RedContext):
|
||||
async def mute(self, ctx: commands.Context):
|
||||
"""Mutes user in the channel/server"""
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help()
|
||||
@@ -772,7 +771,7 @@ class Mod:
|
||||
@commands.guild_only()
|
||||
@mod_or_voice_permissions(mute_members=True)
|
||||
@bot_has_voice_permissions(mute_members=True)
|
||||
async def voice_mute(self, ctx: RedContext, user: discord.Member,
|
||||
async def voice_mute(self, ctx: commands.Context, user: discord.Member,
|
||||
*, reason: str = None):
|
||||
"""Mutes the user in a voice channel"""
|
||||
user_voice_state = user.voice
|
||||
@@ -811,7 +810,7 @@ class Mod:
|
||||
@checks.mod_or_permissions(administrator=True)
|
||||
@mute.command(name="channel")
|
||||
@commands.guild_only()
|
||||
async def channel_mute(self, ctx: RedContext, user: discord.Member, *, reason: str = None):
|
||||
async def channel_mute(self, ctx: commands.Context, user: discord.Member, *, reason: str = None):
|
||||
"""Mutes user in the current channel"""
|
||||
author = ctx.message.author
|
||||
channel = ctx.message.channel
|
||||
@@ -839,7 +838,7 @@ class Mod:
|
||||
@checks.mod_or_permissions(administrator=True)
|
||||
@mute.command(name="server", aliases=["guild"])
|
||||
@commands.guild_only()
|
||||
async def guild_mute(self, ctx: RedContext, user: discord.Member, *, reason: str = None):
|
||||
async def guild_mute(self, ctx: commands.Context, user: discord.Member, *, reason: str = None):
|
||||
"""Mutes user in the server"""
|
||||
author = ctx.message.author
|
||||
guild = ctx.guild
|
||||
@@ -902,7 +901,7 @@ class Mod:
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.mod_or_permissions(manage_channel=True)
|
||||
async def unmute(self, ctx: RedContext):
|
||||
async def unmute(self, ctx: commands.Context):
|
||||
"""Unmutes user in the channel/server
|
||||
|
||||
Defaults to channel"""
|
||||
@@ -913,7 +912,7 @@ class Mod:
|
||||
@commands.guild_only()
|
||||
@mod_or_voice_permissions(mute_members=True)
|
||||
@bot_has_voice_permissions(mute_members=True)
|
||||
async def voice_unmute(self, ctx: RedContext, user: discord.Member, *, reason: str = None):
|
||||
async def voice_unmute(self, ctx: commands.Context, user: discord.Member, *, reason: str = None):
|
||||
"""Unmutes the user in a voice channel"""
|
||||
user_voice_state = user.voice
|
||||
if user_voice_state:
|
||||
@@ -947,7 +946,7 @@ class Mod:
|
||||
@checks.mod_or_permissions(administrator=True)
|
||||
@unmute.command(name="channel")
|
||||
@commands.guild_only()
|
||||
async def channel_unmute(self, ctx: RedContext, user: discord.Member, *, reason: str=None):
|
||||
async def channel_unmute(self, ctx: commands.Context, user: discord.Member, *, reason: str=None):
|
||||
"""Unmutes user in the current channel"""
|
||||
channel = ctx.channel
|
||||
author = ctx.author
|
||||
@@ -970,7 +969,7 @@ class Mod:
|
||||
@checks.mod_or_permissions(administrator=True)
|
||||
@unmute.command(name="server", aliases=["guild"])
|
||||
@commands.guild_only()
|
||||
async def guild_unmute(self, ctx: RedContext, user: discord.Member, *, reason: str=None):
|
||||
async def guild_unmute(self, ctx: commands.Context, user: discord.Member, *, reason: str=None):
|
||||
"""Unmutes user in the server"""
|
||||
guild = ctx.guild
|
||||
author = ctx.author
|
||||
@@ -1038,14 +1037,14 @@ class Mod:
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(manage_channels=True)
|
||||
async def ignore(self, ctx: RedContext):
|
||||
async def ignore(self, ctx: commands.Context):
|
||||
"""Adds servers/channels to ignorelist"""
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help()
|
||||
await ctx.send(await self.count_ignored())
|
||||
|
||||
@ignore.command(name="channel")
|
||||
async def ignore_channel(self, ctx: RedContext, channel: discord.TextChannel=None):
|
||||
async def ignore_channel(self, ctx: commands.Context, channel: discord.TextChannel=None):
|
||||
"""Ignores channel
|
||||
|
||||
Defaults to current one"""
|
||||
@@ -1058,7 +1057,8 @@ class Mod:
|
||||
await ctx.send(_("Channel already in ignore list."))
|
||||
|
||||
@ignore.command(name="server", aliases=["guild"])
|
||||
async def ignore_guild(self, ctx: RedContext):
|
||||
@commands.has_permissions(manage_guild=True)
|
||||
async def ignore_guild(self, ctx: commands.Context):
|
||||
"""Ignores current server"""
|
||||
guild = ctx.guild
|
||||
if not await self.settings.guild(guild).ignored():
|
||||
@@ -1070,14 +1070,14 @@ class Mod:
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(manage_channels=True)
|
||||
async def unignore(self, ctx: RedContext):
|
||||
async def unignore(self, ctx: commands.Context):
|
||||
"""Removes servers/channels from ignorelist"""
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help()
|
||||
await ctx.send(await self.count_ignored())
|
||||
|
||||
@unignore.command(name="channel")
|
||||
async def unignore_channel(self, ctx: RedContext, channel: discord.TextChannel=None):
|
||||
async def unignore_channel(self, ctx: commands.Context, channel: discord.TextChannel=None):
|
||||
"""Removes channel from ignore list
|
||||
|
||||
Defaults to current one"""
|
||||
@@ -1091,7 +1091,8 @@ class Mod:
|
||||
await ctx.send(_("That channel is not in the ignore list."))
|
||||
|
||||
@unignore.command(name="server", aliases=["guild"])
|
||||
async def unignore_guild(self, ctx: RedContext):
|
||||
@commands.has_permissions(manage_guild=True)
|
||||
async def unignore_guild(self, ctx: commands.Context):
|
||||
"""Removes current guild from ignore list"""
|
||||
guild = ctx.message.guild
|
||||
if await self.settings.guild(guild).ignored():
|
||||
@@ -1131,11 +1132,8 @@ class Mod:
|
||||
chann_ignored and not perms.manage_channels)
|
||||
|
||||
@commands.command()
|
||||
async def names(self, ctx: RedContext, user: discord.Member):
|
||||
async def names(self, ctx: commands.Context, user: discord.Member):
|
||||
"""Show previous names/nicknames of a user"""
|
||||
async with self.settings.user(user).past_names() as name_list:
|
||||
while None in name_list: # clean out null entries from a bug
|
||||
name_list.remove(None)
|
||||
names = await self.settings.user(user).past_names()
|
||||
nicks = await self.settings.member(user).past_nicks()
|
||||
msg = ""
|
||||
@@ -1225,7 +1223,7 @@ class Mod:
|
||||
return True
|
||||
return False
|
||||
|
||||
async def on_command(self, ctx: RedContext):
|
||||
async def on_command(self, ctx: commands.Context):
|
||||
"""Currently used for:
|
||||
* delete delay"""
|
||||
guild = ctx.guild
|
||||
@@ -1359,15 +1357,13 @@ class Mod:
|
||||
if entry.target == target:
|
||||
return entry
|
||||
|
||||
async def on_member_update(self, before: discord.Member, after: discord.Member):
|
||||
async def on_member_update(self, before, after):
|
||||
if before.name != after.name:
|
||||
async with self.settings.user(before).past_names() as name_list:
|
||||
while None in name_list: # clean out null entries from a bug
|
||||
name_list.remove(None)
|
||||
if after.name in name_list:
|
||||
if after.nick in name_list:
|
||||
# Ensure order is maintained without duplicates occuring
|
||||
name_list.remove(after.name)
|
||||
name_list.append(after.name)
|
||||
name_list.remove(after.nick)
|
||||
name_list.append(after.nick)
|
||||
while len(name_list) > 20:
|
||||
name_list.pop(0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user