mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -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:
parent
1e60d1c265
commit
15ea5440a3
21
docs/framework_commands.rst
Normal file
21
docs/framework_commands.rst
Normal file
@ -0,0 +1,21 @@
|
||||
.. red commands module documentation
|
||||
|
||||
================
|
||||
Commands Package
|
||||
================
|
||||
|
||||
This package acts almost identically to ``discord.ext.commands``; i.e. they both have the same
|
||||
attributes. Some of these attributes, however, have been slightly modified, as outlined below.
|
||||
|
||||
.. autofunction:: redbot.core.commands.command
|
||||
|
||||
.. autofunction:: redbot.core.commands.group
|
||||
|
||||
.. autoclass:: redbot.core.commands.Command
|
||||
:members:
|
||||
|
||||
.. autoclass:: redbot.core.commands.Group
|
||||
:members:
|
||||
|
||||
.. autoclass:: redbot.core.commands.Context
|
||||
:members:
|
||||
@ -1,10 +0,0 @@
|
||||
.. red invocation context documentation
|
||||
|
||||
==========================
|
||||
Command Invocation Context
|
||||
==========================
|
||||
|
||||
.. automodule:: redbot.core.context
|
||||
|
||||
.. autoclass:: redbot.core.RedContext
|
||||
:members:
|
||||
@ -13,11 +13,12 @@ Basic Usage
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from discord.ext import commands
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
|
||||
_ = CogI18n("ExampleCog", __file__)
|
||||
_ = Translator("ExampleCog", __file__)
|
||||
|
||||
@cog_i18n(_)
|
||||
class ExampleCog:
|
||||
"""description"""
|
||||
|
||||
@ -39,16 +40,19 @@ In a command prompt in your cog's package (where yourcog.py is),
|
||||
create a directory called "locales".
|
||||
Then do one of the following:
|
||||
|
||||
Windows: :code:`python <your python install path>\Tools\i18n\pygettext.py -n -p locales`
|
||||
Windows: :code:`python <your python install path>\Tools\i18n\pygettext.py -D -n -p locales`
|
||||
|
||||
Mac: ?
|
||||
|
||||
Linux: :code:`pygettext3 -n -p locales`
|
||||
Linux: :code:`pygettext3 -D -n -p locales`
|
||||
|
||||
This will generate a messages.pot file with strings to be translated
|
||||
This will generate a messages.pot file with strings to be translated, including
|
||||
docstrings.
|
||||
|
||||
-------------
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. automodule:: redbot.core.i18n
|
||||
:members:
|
||||
:special-members: __call__
|
||||
|
||||
@ -37,12 +37,12 @@ Welcome to Red - Discord Bot's documentation!
|
||||
framework_bot
|
||||
framework_cogmanager
|
||||
framework_config
|
||||
framework_context
|
||||
framework_datamanager
|
||||
framework_downloader
|
||||
framework_events
|
||||
framework_i18n
|
||||
framework_modlog
|
||||
framework_commands
|
||||
framework_rpc
|
||||
framework_utils
|
||||
|
||||
|
||||
@ -3,17 +3,17 @@ from re import search
|
||||
from typing import Generator, Tuple, Iterable
|
||||
|
||||
import discord
|
||||
from redbot.core import Config
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core import Config, commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import box
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core.bot import Red
|
||||
from .alias_entry import AliasEntry
|
||||
|
||||
_ = CogI18n("Alias", __file__)
|
||||
_ = Translator("Alias", __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Alias:
|
||||
"""
|
||||
Alias
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
from typing import Tuple
|
||||
from discord.ext import commands
|
||||
|
||||
import discord
|
||||
from redbot.core import commands
|
||||
|
||||
|
||||
class AliasEntry:
|
||||
|
||||
@ -7,15 +7,19 @@ import lavalink
|
||||
import math
|
||||
import re
|
||||
import redbot.core
|
||||
from discord.ext import commands
|
||||
from redbot.core import Config, checks, bank
|
||||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
|
||||
_ = Translator("Audio", __file__)
|
||||
from .manager import shutdown_lavalink_server
|
||||
|
||||
__version__ = "0.0.5a"
|
||||
__author__ = ["aikaterna", "billy/bollo/ati"]
|
||||
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Audio:
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
import discord
|
||||
from redbot.core.utils.chat_formatting import box
|
||||
|
||||
from redbot.core import checks, bank
|
||||
from redbot.core.i18n import CogI18n
|
||||
from discord.ext import commands
|
||||
from redbot.core import checks, bank, commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
|
||||
from redbot.core.bot import Red # Only used for type hints
|
||||
|
||||
_ = CogI18n('Bank', __file__)
|
||||
_ = Translator('Bank', __file__)
|
||||
|
||||
|
||||
def check_global_setting_guildowner():
|
||||
@ -48,6 +47,7 @@ def check_global_setting_admin():
|
||||
return commands.check(pred)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Bank:
|
||||
"""Bank"""
|
||||
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import re
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core import checks, RedContext
|
||||
from redbot.core import checks, 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.mod import slow_deletion, mass_purge
|
||||
from redbot.cogs.mod.log import log
|
||||
|
||||
_ = CogI18n("Cleanup", __file__)
|
||||
_ = Translator("Cleanup", __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Cleanup:
|
||||
"""Commands for cleaning messages"""
|
||||
|
||||
@ -19,7 +19,7 @@ class Cleanup:
|
||||
self.bot = bot
|
||||
|
||||
@staticmethod
|
||||
async def check_100_plus(ctx: RedContext, number: int) -> bool:
|
||||
async def check_100_plus(ctx: commands.Context, number: int) -> bool:
|
||||
"""
|
||||
Called when trying to delete more than 100 messages at once
|
||||
|
||||
@ -39,7 +39,7 @@ class Cleanup:
|
||||
|
||||
@staticmethod
|
||||
async def get_messages_for_deletion(
|
||||
ctx: RedContext, channel: discord.TextChannel, number,
|
||||
ctx: commands.Context, channel: discord.TextChannel, number,
|
||||
check=lambda x: True, limit=100, before=None, after=None
|
||||
) -> list:
|
||||
"""
|
||||
@ -75,7 +75,7 @@ class Cleanup:
|
||||
|
||||
@commands.group()
|
||||
@checks.mod_or_permissions(manage_messages=True)
|
||||
async def cleanup(self, ctx: RedContext):
|
||||
async def cleanup(self, ctx: commands.Context):
|
||||
"""Deletes messages."""
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help()
|
||||
@ -83,7 +83,7 @@ class Cleanup:
|
||||
@cleanup.command()
|
||||
@commands.guild_only()
|
||||
@commands.bot_has_permissions(manage_messages=True)
|
||||
async def text(self, ctx: RedContext, text: str, number: int):
|
||||
async def text(self, ctx: commands.Context, text: str, number: int):
|
||||
"""Deletes last X messages matching the specified text.
|
||||
|
||||
Example:
|
||||
@ -124,7 +124,7 @@ class Cleanup:
|
||||
@cleanup.command()
|
||||
@commands.guild_only()
|
||||
@commands.bot_has_permissions(manage_messages=True)
|
||||
async def user(self, ctx: RedContext, user: str, number: int):
|
||||
async def user(self, ctx: commands.Context, user: str, number: int):
|
||||
"""Deletes last X messages from specified user.
|
||||
|
||||
Examples:
|
||||
@ -176,7 +176,7 @@ class Cleanup:
|
||||
@cleanup.command()
|
||||
@commands.guild_only()
|
||||
@commands.bot_has_permissions(manage_messages=True)
|
||||
async def after(self, ctx: RedContext, message_id: int):
|
||||
async def after(self, ctx: commands.Context, message_id: int):
|
||||
"""Deletes all messages after specified message.
|
||||
|
||||
To get a message id, enable developer mode in Discord's
|
||||
@ -215,7 +215,7 @@ class Cleanup:
|
||||
@cleanup.command()
|
||||
@commands.guild_only()
|
||||
@commands.bot_has_permissions(manage_messages=True)
|
||||
async def messages(self, ctx: RedContext, number: int):
|
||||
async def messages(self, ctx: commands.Context, number: int):
|
||||
"""Deletes last X messages.
|
||||
|
||||
Example:
|
||||
@ -248,7 +248,7 @@ class Cleanup:
|
||||
@cleanup.command(name='bot')
|
||||
@commands.guild_only()
|
||||
@commands.bot_has_permissions(manage_messages=True)
|
||||
async def cleanup_bot(self, ctx: RedContext, number: int):
|
||||
async def cleanup_bot(self, ctx: commands.Context, number: int):
|
||||
"""Cleans up command messages and messages from the bot."""
|
||||
|
||||
channel = ctx.message.channel
|
||||
@ -295,7 +295,7 @@ class Cleanup:
|
||||
await slow_deletion(to_delete)
|
||||
|
||||
@cleanup.command(name='self')
|
||||
async def cleanup_self(self, ctx: RedContext, number: int, match_pattern: str = None):
|
||||
async def cleanup_self(self, ctx: commands.Context, number: int, match_pattern: str = None):
|
||||
"""Cleans up messages owned by the bot.
|
||||
|
||||
By default, all messages are cleaned. If a third argument is specified,
|
||||
|
||||
@ -4,13 +4,12 @@ import random
|
||||
from datetime import datetime
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core import Config, checks
|
||||
from redbot.core import Config, checks, commands
|
||||
from redbot.core.utils.chat_formatting import box, pagify
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
|
||||
_ = CogI18n("CustomCommands", __file__)
|
||||
_ = Translator("CustomCommands", __file__)
|
||||
|
||||
|
||||
class CCError(Exception):
|
||||
@ -152,6 +151,7 @@ class CommandObj:
|
||||
command, value=None)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class CustomCommands:
|
||||
"""Custom commands
|
||||
Creates commands used to display text"""
|
||||
|
||||
@ -1,17 +1,16 @@
|
||||
from pathlib import Path
|
||||
import asyncio
|
||||
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core import checks, RedContext
|
||||
from redbot.core import checks, commands
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.cogs.dataconverter.core_specs import SpecResolver
|
||||
from redbot.core.utils.chat_formatting import box
|
||||
|
||||
_ = CogI18n('DataConverter', __file__)
|
||||
_ = Translator('DataConverter', __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class DataConverter:
|
||||
"""
|
||||
Cog for importing Red v2 Data
|
||||
@ -22,7 +21,7 @@ class DataConverter:
|
||||
|
||||
@checks.is_owner()
|
||||
@commands.command(name="convertdata")
|
||||
async def dataconversioncommand(self, ctx: RedContext, v2path: str):
|
||||
async def dataconversioncommand(self, ctx: commands.Context, v2path: str):
|
||||
"""
|
||||
Interactive prompt for importing data from Red v2
|
||||
|
||||
|
||||
@ -10,9 +10,9 @@ import sys
|
||||
from redbot.core import Config
|
||||
from redbot.core import checks
|
||||
from redbot.core.data_manager import cog_data_path
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import box, pagify
|
||||
from discord.ext import commands
|
||||
from redbot.core import commands
|
||||
|
||||
from redbot.core.bot import Red
|
||||
from .checks import install_agreement
|
||||
@ -22,9 +22,10 @@ from .installable import Installable
|
||||
from .log import log
|
||||
from .repo_manager import RepoManager, Repo
|
||||
|
||||
_ = CogI18n('Downloader', __file__)
|
||||
_ = Translator('Downloader', __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Downloader:
|
||||
def __init__(self, bot: Red):
|
||||
self.bot = bot
|
||||
|
||||
@ -7,14 +7,13 @@ from enum import Enum
|
||||
import discord
|
||||
|
||||
from redbot.cogs.bank import check_global_setting_guildowner, check_global_setting_admin
|
||||
from redbot.core import Config, bank
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core import Config, bank, commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import pagify, box
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core.bot import Red
|
||||
|
||||
_ = CogI18n("Economy", __file__)
|
||||
_ = Translator("Economy", __file__)
|
||||
|
||||
logger = logging.getLogger("red.economy")
|
||||
|
||||
@ -104,6 +103,7 @@ class SetParser:
|
||||
raise RuntimeError
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Economy:
|
||||
"""Economy
|
||||
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
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 pagify
|
||||
from redbot.core.utils.mod import is_mod_or_superior
|
||||
|
||||
_ = CogI18n("Filter", __file__)
|
||||
_ = Translator("Filter", __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Filter:
|
||||
"""Filter-related commands"""
|
||||
|
||||
@ -46,7 +46,7 @@ class Filter:
|
||||
@commands.group(name="filter")
|
||||
@commands.guild_only()
|
||||
@checks.mod_or_permissions(manage_messages=True)
|
||||
async def _filter(self, ctx: RedContext):
|
||||
async def _filter(self, ctx: commands.Context):
|
||||
"""Adds/removes words from filter
|
||||
|
||||
Use double quotes to add/remove sentences
|
||||
@ -129,7 +129,7 @@ class Filter:
|
||||
await ctx.send(_("Those words weren't in the filter."))
|
||||
|
||||
@_filter.command(name="names")
|
||||
async def filter_names(self, ctx: RedContext):
|
||||
async def filter_names(self, ctx: commands.Context):
|
||||
"""
|
||||
Toggles whether or not to check names and nicknames against the filter
|
||||
This is disabled by default
|
||||
@ -149,7 +149,7 @@ class Filter:
|
||||
)
|
||||
|
||||
@_filter.command(name="defaultname")
|
||||
async def filter_default_name(self, ctx: RedContext, name: str):
|
||||
async def filter_default_name(self, ctx: commands.Context, name: str):
|
||||
"""
|
||||
Sets the default name to use if filtering names is enabled
|
||||
Note that this has no effect if filtering names is disabled
|
||||
|
||||
@ -6,12 +6,12 @@ from urllib.parse import quote_plus
|
||||
|
||||
import aiohttp
|
||||
import discord
|
||||
from redbot.core.i18n import CogI18n
|
||||
from discord.ext import commands
|
||||
from redbot.core import commands
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
|
||||
from redbot.core.utils.chat_formatting import escape, italics, pagify
|
||||
|
||||
_ = CogI18n("General", __file__)
|
||||
_ = Translator("General", __file__)
|
||||
|
||||
|
||||
class RPS(Enum):
|
||||
@ -33,6 +33,7 @@ class RPSParser:
|
||||
raise
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class General:
|
||||
"""General commands."""
|
||||
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
from random import shuffle
|
||||
|
||||
import aiohttp
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core import checks, Config
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core import checks, Config, commands
|
||||
|
||||
_ = CogI18n("Image", __file__)
|
||||
_ = Translator("Image", __file__)
|
||||
|
||||
GIPHY_API_KEY = "dc6zaTOxFJmzC"
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Image:
|
||||
"""Image related commands."""
|
||||
default_global = {
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core import checks, modlog, RedContext
|
||||
from redbot.core import checks, 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
|
||||
|
||||
_ = CogI18n('ModLog', __file__)
|
||||
_ = Translator('ModLog', __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class ModLog:
|
||||
"""Log for mod actions"""
|
||||
|
||||
@ -17,14 +17,14 @@ class ModLog:
|
||||
|
||||
@commands.group()
|
||||
@checks.guildowner_or_permissions(administrator=True)
|
||||
async def modlogset(self, ctx: RedContext):
|
||||
async def modlogset(self, ctx: commands.Context):
|
||||
"""Settings for the mod log"""
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help()
|
||||
|
||||
@modlogset.command()
|
||||
@commands.guild_only()
|
||||
async def modlog(self, ctx: RedContext, channel: discord.TextChannel = None):
|
||||
async def modlog(self, ctx: commands.Context, channel: discord.TextChannel = None):
|
||||
"""Sets a channel as mod log
|
||||
|
||||
Leaving the channel parameter empty will deactivate it"""
|
||||
@ -53,7 +53,7 @@ class ModLog:
|
||||
|
||||
@modlogset.command(name='cases')
|
||||
@commands.guild_only()
|
||||
async def set_cases(self, ctx: RedContext, action: str = None):
|
||||
async def set_cases(self, ctx: commands.Context, action: str = None):
|
||||
"""Enables or disables case creation for each type of mod action"""
|
||||
guild = ctx.guild
|
||||
|
||||
@ -87,7 +87,7 @@ class ModLog:
|
||||
|
||||
@modlogset.command()
|
||||
@commands.guild_only()
|
||||
async def resetcases(self, ctx: RedContext):
|
||||
async def resetcases(self, ctx: commands.Context):
|
||||
"""Resets modlog's cases"""
|
||||
guild = ctx.guild
|
||||
await modlog.reset_cases(guild)
|
||||
@ -95,7 +95,7 @@ class ModLog:
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
async def case(self, ctx: RedContext, number: int):
|
||||
async def case(self, ctx: commands.Context, number: int):
|
||||
"""Shows the specified case"""
|
||||
try:
|
||||
case = await modlog.get_case(number, ctx.guild, self.bot)
|
||||
@ -107,7 +107,7 @@ class ModLog:
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
async def reason(self, ctx: RedContext, case: int, *, reason: str = ""):
|
||||
async def reason(self, ctx: commands.Context, case: int, *, reason: str = ""):
|
||||
"""Lets you specify a reason for mod-log's cases
|
||||
Please note that you can only edit cases you are
|
||||
the owner of unless you are a mod/admin or the server owner"""
|
||||
|
||||
@ -5,21 +5,21 @@ from datetime import timedelta
|
||||
from copy import copy
|
||||
import contextlib
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core import Config, checks, RedContext
|
||||
from redbot.core import Config, checks, commands
|
||||
from redbot.core.utils.chat_formatting import pagify, box
|
||||
from redbot.core.utils.antispam import AntiSpam
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.tunnel import Tunnel
|
||||
|
||||
|
||||
_ = CogI18n("Reports", __file__)
|
||||
_ = Translator("Reports", __file__)
|
||||
|
||||
log = logging.getLogger("red.reports")
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Reports:
|
||||
|
||||
default_guild_settings = {
|
||||
@ -66,7 +66,7 @@ class Reports:
|
||||
@checks.admin_or_permissions(manage_guild=True)
|
||||
@commands.guild_only()
|
||||
@commands.group(name="reportset")
|
||||
async def reportset(self, ctx: RedContext):
|
||||
async def reportset(self, ctx: commands.Context):
|
||||
"""
|
||||
settings for reports
|
||||
"""
|
||||
@ -74,14 +74,14 @@ class Reports:
|
||||
|
||||
@checks.admin_or_permissions(manage_guild=True)
|
||||
@reportset.command(name="output")
|
||||
async def setoutput(self, ctx: RedContext, channel: discord.TextChannel):
|
||||
async def setoutput(self, ctx: commands.Context, channel: discord.TextChannel):
|
||||
"""sets the output channel"""
|
||||
await self.config.guild(ctx.guild).output_channel.set(channel.id)
|
||||
await ctx.send(_("Report Channel Set."))
|
||||
|
||||
@checks.admin_or_permissions(manage_guild=True)
|
||||
@reportset.command(name="toggleactive")
|
||||
async def report_toggle(self, ctx: RedContext):
|
||||
async def report_toggle(self, ctx: commands.Context):
|
||||
"""Toggles whether the Reporting tool is enabled or not"""
|
||||
|
||||
active = await self.config.guild(ctx.guild).active()
|
||||
@ -136,7 +136,6 @@ class Reports:
|
||||
shared_guilds.append(guild)
|
||||
if len(shared_guilds) == 0:
|
||||
raise ValueError("No Qualifying Shared Guilds")
|
||||
return
|
||||
if len(shared_guilds) == 1:
|
||||
return shared_guilds[0]
|
||||
output = ""
|
||||
@ -216,7 +215,7 @@ class Reports:
|
||||
return ticket_number
|
||||
|
||||
@commands.group(name="report", invoke_without_command=True)
|
||||
async def report(self, ctx: RedContext, *, _report: str=""):
|
||||
async def report(self, ctx: commands.Context, *, _report: str=""):
|
||||
"""
|
||||
Follow the prompts to make a report
|
||||
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from redbot.core import Config, checks, RedContext
|
||||
from redbot.core import Config, checks, commands
|
||||
from redbot.core.utils.chat_formatting import pagify
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from .streamtypes import TwitchStream, HitboxStream, MixerStream, PicartoStream, TwitchCommunity, YoutubeStream
|
||||
from .errors import (OfflineStream, StreamNotFound, APIError, InvalidYoutubeCredentials,
|
||||
CommunityNotFound, OfflineCommunity, StreamsError, InvalidTwitchCredentials)
|
||||
@ -15,9 +14,10 @@ import re
|
||||
CHECK_DELAY = 60
|
||||
|
||||
|
||||
_ = CogI18n("Streams", __file__)
|
||||
_ = Translator("Streams", __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Streams:
|
||||
|
||||
global_defaults = {
|
||||
@ -64,7 +64,7 @@ class Streams:
|
||||
self.task = self.bot.loop.create_task(self._stream_alerts())
|
||||
|
||||
@commands.command()
|
||||
async def twitch(self, ctx, channel_name: str):
|
||||
async def twitch(self, ctx: commands.Context, channel_name: str):
|
||||
"""Checks if a Twitch channel is streaming"""
|
||||
token = await self.db.tokens.get_raw(TwitchStream.__name__, default=None)
|
||||
stream = TwitchStream(name=channel_name,
|
||||
@ -72,7 +72,7 @@ class Streams:
|
||||
await self.check_online(ctx, stream)
|
||||
|
||||
@commands.command()
|
||||
async def youtube(self, ctx, channel_id_or_name: str):
|
||||
async def youtube(self, ctx: commands.Context, channel_id_or_name: str):
|
||||
"""
|
||||
Checks if a Youtube channel is streaming
|
||||
"""
|
||||
@ -85,24 +85,24 @@ class Streams:
|
||||
await self.check_online(ctx, stream)
|
||||
|
||||
@commands.command()
|
||||
async def hitbox(self, ctx, channel_name: str):
|
||||
async def hitbox(self, ctx: commands.Context, channel_name: str):
|
||||
"""Checks if a Hitbox channel is streaming"""
|
||||
stream = HitboxStream(name=channel_name)
|
||||
await self.check_online(ctx, stream)
|
||||
|
||||
@commands.command()
|
||||
async def mixer(self, ctx, channel_name: str):
|
||||
async def mixer(self, ctx: commands.Context, channel_name: str):
|
||||
"""Checks if a Mixer channel is streaming"""
|
||||
stream = MixerStream(name=channel_name)
|
||||
await self.check_online(ctx, stream)
|
||||
|
||||
@commands.command()
|
||||
async def picarto(self, ctx, channel_name: str):
|
||||
async def picarto(self, ctx: commands.Context, channel_name: str):
|
||||
"""Checks if a Picarto channel is streaming"""
|
||||
stream = PicartoStream(name=channel_name)
|
||||
await self.check_online(ctx, stream)
|
||||
|
||||
async def check_online(self, ctx, stream):
|
||||
async def check_online(self, ctx: commands.Context, stream):
|
||||
try:
|
||||
embed = await stream.is_online()
|
||||
except OfflineStream:
|
||||
@ -124,49 +124,49 @@ class Streams:
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.mod()
|
||||
async def streamalert(self, ctx):
|
||||
async def streamalert(self, ctx: commands.Context):
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help()
|
||||
|
||||
@streamalert.group(name="twitch")
|
||||
async def _twitch(self, ctx):
|
||||
async def _twitch(self, ctx: commands.Context):
|
||||
"""Twitch stream alerts"""
|
||||
if ctx.invoked_subcommand is None or ctx.invoked_subcommand == self._twitch:
|
||||
await ctx.send_help()
|
||||
|
||||
@_twitch.command(name="channel")
|
||||
async def twitch_alert_channel(self, ctx: RedContext, channel_name: str):
|
||||
async def twitch_alert_channel(self, ctx: commands.Context, channel_name: str):
|
||||
"""Sets a Twitch stream alert notification in the channel"""
|
||||
await self.stream_alert(ctx, TwitchStream, channel_name.lower())
|
||||
|
||||
@_twitch.command(name="community")
|
||||
async def twitch_alert_community(self, ctx: RedContext, community: str):
|
||||
async def twitch_alert_community(self, ctx: commands.Context, community: str):
|
||||
"""Sets a Twitch stream alert notification in the channel
|
||||
for the specified community."""
|
||||
await self.community_alert(ctx, TwitchCommunity, community.lower())
|
||||
|
||||
@streamalert.command(name="youtube")
|
||||
async def youtube_alert(self, ctx: RedContext, channel_name_or_id: str):
|
||||
async def youtube_alert(self, ctx: commands.Context, channel_name_or_id: str):
|
||||
"""Sets a Youtube stream alert notification in the channel"""
|
||||
await self.stream_alert(ctx, YoutubeStream, channel_name_or_id)
|
||||
|
||||
@streamalert.command(name="hitbox")
|
||||
async def hitbox_alert(self, ctx, channel_name: str):
|
||||
async def hitbox_alert(self, ctx: commands.Context, channel_name: str):
|
||||
"""Sets a Hitbox stream alert notification in the channel"""
|
||||
await self.stream_alert(ctx, HitboxStream, channel_name)
|
||||
|
||||
@streamalert.command(name="mixer")
|
||||
async def mixer_alert(self, ctx, channel_name: str):
|
||||
async def mixer_alert(self, ctx: commands.Context, channel_name: str):
|
||||
"""Sets a Mixer stream alert notification in the channel"""
|
||||
await self.stream_alert(ctx, MixerStream, channel_name)
|
||||
|
||||
@streamalert.command(name="picarto")
|
||||
async def picarto_alert(self, ctx, channel_name: str):
|
||||
async def picarto_alert(self, ctx: commands.Context, channel_name: str):
|
||||
"""Sets a Picarto stream alert notification in the channel"""
|
||||
await self.stream_alert(ctx, PicartoStream, channel_name)
|
||||
|
||||
@streamalert.command(name="stop")
|
||||
async def streamalert_stop(self, ctx, _all: bool=False):
|
||||
async def streamalert_stop(self, ctx: commands.Context, _all: bool=False):
|
||||
"""Stops all stream notifications in the channel
|
||||
|
||||
Adding 'yes' will disable all notifications in the server"""
|
||||
@ -197,7 +197,7 @@ class Streams:
|
||||
await ctx.send(msg)
|
||||
|
||||
@streamalert.command(name="list")
|
||||
async def streamalert_list(self, ctx):
|
||||
async def streamalert_list(self, ctx: commands.Context):
|
||||
streams_list = defaultdict(list)
|
||||
guild_channels_ids = [c.id for c in ctx.guild.channels]
|
||||
msg = _("Active stream alerts:\n\n")
|
||||
@ -218,7 +218,7 @@ class Streams:
|
||||
for page in pagify(msg):
|
||||
await ctx.send(page)
|
||||
|
||||
async def stream_alert(self, ctx, _class, channel_name):
|
||||
async def stream_alert(self, ctx: commands.Context, _class, channel_name):
|
||||
stream = self.get_stream(_class, channel_name)
|
||||
if not stream:
|
||||
token = await self.db.tokens.get_raw(_class.__name__, default=None)
|
||||
@ -251,7 +251,7 @@ class Streams:
|
||||
|
||||
await self.add_or_remove(ctx, stream)
|
||||
|
||||
async def community_alert(self, ctx, _class, community_name):
|
||||
async def community_alert(self, ctx: commands.Context, _class, community_name):
|
||||
community = self.get_community(_class, community_name)
|
||||
if not community:
|
||||
token = await self.db.tokens.get_raw(_class.__name__, default=None)
|
||||
@ -278,13 +278,13 @@ class Streams:
|
||||
|
||||
@commands.group()
|
||||
@checks.mod()
|
||||
async def streamset(self, ctx):
|
||||
async def streamset(self, ctx: commands.Context):
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help()
|
||||
|
||||
@streamset.command()
|
||||
@checks.is_owner()
|
||||
async def twitchtoken(self, ctx, token: str):
|
||||
async def twitchtoken(self, ctx: commands.Context, token: str):
|
||||
"""Set the Client ID for twitch.
|
||||
|
||||
To do this, follow these steps:
|
||||
@ -302,7 +302,7 @@ class Streams:
|
||||
|
||||
@streamset.command()
|
||||
@checks.is_owner()
|
||||
async def youtubekey(self, ctx: RedContext, key: str):
|
||||
async def youtubekey(self, ctx: commands.Context, key: str):
|
||||
"""Sets the API key for Youtube.
|
||||
|
||||
To get one, do the following:
|
||||
@ -318,14 +318,14 @@ class Streams:
|
||||
|
||||
@streamset.group()
|
||||
@commands.guild_only()
|
||||
async def mention(self, ctx):
|
||||
async def mention(self, ctx: commands.Context):
|
||||
"""Sets mentions for stream alerts."""
|
||||
if ctx.invoked_subcommand is None or ctx.invoked_subcommand == self.mention:
|
||||
await ctx.send_help()
|
||||
|
||||
@mention.command(aliases=["everyone"])
|
||||
@commands.guild_only()
|
||||
async def all(self, ctx):
|
||||
async def all(self, ctx: commands.Context):
|
||||
"""Toggles everyone mention"""
|
||||
guild = ctx.guild
|
||||
current_setting = await self.db.guild(guild).mention_everyone()
|
||||
@ -340,7 +340,7 @@ class Streams:
|
||||
|
||||
@mention.command(aliases=["here"])
|
||||
@commands.guild_only()
|
||||
async def online(self, ctx):
|
||||
async def online(self, ctx: commands.Context):
|
||||
"""Toggles here mention"""
|
||||
guild = ctx.guild
|
||||
current_setting = await self.db.guild(guild).mention_here()
|
||||
@ -355,7 +355,7 @@ class Streams:
|
||||
|
||||
@mention.command()
|
||||
@commands.guild_only()
|
||||
async def role(self, ctx, *, role: discord.Role):
|
||||
async def role(self, ctx: commands.Context, *, role: discord.Role):
|
||||
"""Toggles role mention"""
|
||||
current_setting = await self.db.role(role).mention()
|
||||
if not role.mentionable:
|
||||
@ -373,7 +373,7 @@ class Streams:
|
||||
|
||||
@streamset.command()
|
||||
@commands.guild_only()
|
||||
async def autodelete(self, ctx, on_off: bool):
|
||||
async def autodelete(self, ctx: commands.Context, on_off: bool):
|
||||
"""Toggles automatic deletion of notifications for streams that go offline"""
|
||||
await self.db.guild(ctx.guild).autodelete.set(on_off)
|
||||
if on_off:
|
||||
@ -382,7 +382,7 @@ class Streams:
|
||||
else:
|
||||
await ctx.send("Notifications will never be deleted.")
|
||||
|
||||
async def add_or_remove(self, ctx, stream):
|
||||
async def add_or_remove(self, ctx: commands.Context, stream):
|
||||
if ctx.channel.id not in stream.channels:
|
||||
stream.channels.append(ctx.channel.id)
|
||||
if stream not in self.streams:
|
||||
@ -398,7 +398,7 @@ class Streams:
|
||||
|
||||
await self.save_streams()
|
||||
|
||||
async def add_or_remove_community(self, ctx, community):
|
||||
async def add_or_remove_community(self, ctx: commands.Context, community):
|
||||
if ctx.channel.id not in community.channels:
|
||||
community.channels.append(ctx.channel.id)
|
||||
if community not in self.communities:
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
from copy import copy
|
||||
from discord.ext import commands
|
||||
import asyncio
|
||||
import inspect
|
||||
import discord
|
||||
|
||||
from redbot.core import RedContext, Config, checks
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core import Config, checks, commands
|
||||
from redbot.core.i18n import Translator
|
||||
|
||||
_ = CogI18n("Warnings", __file__)
|
||||
_ = Translator("Warnings", __file__)
|
||||
|
||||
|
||||
async def warning_points_add_check(config: Config, ctx: RedContext, user: discord.Member, points: int):
|
||||
async def warning_points_add_check(config: Config, ctx: commands.Context, user: discord.Member, points: int):
|
||||
"""Handles any action that needs to be taken or not based on the points"""
|
||||
guild = ctx.guild
|
||||
guild_settings = config.guild(guild)
|
||||
@ -25,7 +24,7 @@ async def warning_points_add_check(config: Config, ctx: RedContext, user: discor
|
||||
await create_and_invoke_context(ctx, act["exceed_command"], user)
|
||||
|
||||
|
||||
async def warning_points_remove_check(config: Config, ctx: RedContext, user: discord.Member, points: int):
|
||||
async def warning_points_remove_check(config: Config, ctx: commands.Context, user: discord.Member, points: int):
|
||||
guild = ctx.guild
|
||||
guild_settings = config.guild(guild)
|
||||
act = {}
|
||||
@ -39,10 +38,10 @@ async def warning_points_remove_check(config: Config, ctx: RedContext, user: dis
|
||||
await create_and_invoke_context(ctx, act["drop_command"], user)
|
||||
|
||||
|
||||
async def create_and_invoke_context(realctx: RedContext, command_str: str, user: discord.Member):
|
||||
async def create_and_invoke_context(realctx: commands.Context, command_str: str, user: discord.Member):
|
||||
m = copy(realctx.message)
|
||||
m.content = command_str.format(user=user.mention, prefix=realctx.prefix)
|
||||
fctx = await realctx.bot.get_context(m, cls=RedContext)
|
||||
fctx = await realctx.bot.get_context(m, cls=commands.Context)
|
||||
try:
|
||||
await realctx.bot.invoke(fctx)
|
||||
except (commands.CheckFailure, commands.CommandOnCooldown):
|
||||
@ -69,7 +68,7 @@ def get_command_from_input(bot, userinput: str):
|
||||
return "{prefix}" + orig, None
|
||||
|
||||
|
||||
async def get_command_for_exceeded_points(ctx: RedContext):
|
||||
async def get_command_for_exceeded_points(ctx: commands.Context):
|
||||
"""Gets the command to be executed when the user is at or exceeding
|
||||
the points threshold for the action"""
|
||||
await ctx.send(
|
||||
@ -102,7 +101,7 @@ async def get_command_for_exceeded_points(ctx: RedContext):
|
||||
return command
|
||||
|
||||
|
||||
async def get_command_for_dropping_points(ctx: RedContext):
|
||||
async def get_command_for_dropping_points(ctx: commands.Context):
|
||||
"""
|
||||
Gets the command to be executed when the user drops below the points
|
||||
threshold
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
from collections import namedtuple
|
||||
|
||||
from discord.ext import commands
|
||||
import discord
|
||||
import asyncio
|
||||
|
||||
from redbot.cogs.warnings.helpers import warning_points_add_check, get_command_for_exceeded_points, \
|
||||
get_command_for_dropping_points, warning_points_remove_check
|
||||
from redbot.core import Config, modlog, checks
|
||||
from redbot.core import Config, modlog, checks, commands
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.context import RedContext
|
||||
from redbot.core.i18n import CogI18n
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.mod import is_admin_or_superior
|
||||
from redbot.core.utils.chat_formatting import warning, pagify
|
||||
|
||||
_ = CogI18n("Warnings", __file__)
|
||||
_ = Translator("Warnings", __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class Warnings:
|
||||
"""A warning system for Red"""
|
||||
|
||||
@ -51,14 +50,14 @@ class Warnings:
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.guildowner_or_permissions(administrator=True)
|
||||
async def warningset(self, ctx: RedContext):
|
||||
async def warningset(self, ctx: commands.Context):
|
||||
"""Warning settings"""
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help()
|
||||
|
||||
@warningset.command()
|
||||
@commands.guild_only()
|
||||
async def allowcustomreasons(self, ctx: RedContext, allowed: bool):
|
||||
async def allowcustomreasons(self, ctx: commands.Context, allowed: bool):
|
||||
"""Allow or disallow custom reasons for a warning"""
|
||||
guild = ctx.guild
|
||||
await self.config.guild(guild).allow_custom_reasons.set(allowed)
|
||||
@ -69,14 +68,14 @@ class Warnings:
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.guildowner_or_permissions(administrator=True)
|
||||
async def warnaction(self, ctx: RedContext):
|
||||
async def warnaction(self, ctx: commands.Context):
|
||||
"""Action management"""
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help()
|
||||
|
||||
@warnaction.command(name="add")
|
||||
@commands.guild_only()
|
||||
async def action_add(self, ctx: RedContext, name: str, points: int):
|
||||
async def action_add(self, ctx: commands.Context, name: str, points: int):
|
||||
"""Create an action to be taken at a specified point count
|
||||
Duplicate action names are not allowed"""
|
||||
guild = ctx.guild
|
||||
@ -125,7 +124,7 @@ class Warnings:
|
||||
|
||||
@warnaction.command(name="del")
|
||||
@commands.guild_only()
|
||||
async def action_del(self, ctx: RedContext, action_name: str):
|
||||
async def action_del(self, ctx: commands.Context, action_name: str):
|
||||
"""Delete the point count action with the specified name"""
|
||||
guild = ctx.guild
|
||||
guild_settings = self.config.guild(guild)
|
||||
@ -146,14 +145,14 @@ class Warnings:
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.guildowner_or_permissions(administrator=True)
|
||||
async def warnreason(self, ctx: RedContext):
|
||||
async def warnreason(self, ctx: commands.Context):
|
||||
"""Add reasons for warnings"""
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send_help()
|
||||
|
||||
@warnreason.command(name="add")
|
||||
@commands.guild_only()
|
||||
async def reason_add(self, ctx: RedContext, name: str, points: int, *, description: str):
|
||||
async def reason_add(self, ctx: commands.Context, name: str, points: int, *, description: str):
|
||||
"""Add a reason to be available for warnings"""
|
||||
guild = ctx.guild
|
||||
|
||||
@ -177,7 +176,7 @@ class Warnings:
|
||||
|
||||
@warnreason.command(name="del")
|
||||
@commands.guild_only()
|
||||
async def reason_del(self, ctx: RedContext, reason_name: str):
|
||||
async def reason_del(self, ctx: commands.Context, reason_name: str):
|
||||
"""Delete the reason with the specified name"""
|
||||
guild = ctx.guild
|
||||
guild_settings = self.config.guild(guild)
|
||||
@ -190,7 +189,7 @@ class Warnings:
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(ban_members=True)
|
||||
async def reasonlist(self, ctx: RedContext):
|
||||
async def reasonlist(self, ctx: commands.Context):
|
||||
"""List all configured reasons for warnings"""
|
||||
guild = ctx.guild
|
||||
guild_settings = self.config.guild(guild)
|
||||
@ -210,7 +209,7 @@ class Warnings:
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(ban_members=True)
|
||||
async def actionlist(self, ctx: RedContext):
|
||||
async def actionlist(self, ctx: commands.Context):
|
||||
"""List the actions to be taken at specific point values"""
|
||||
guild = ctx.guild
|
||||
guild_settings = self.config.guild(guild)
|
||||
@ -232,7 +231,7 @@ class Warnings:
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(ban_members=True)
|
||||
async def warn(self, ctx: RedContext, user: discord.Member, reason: str):
|
||||
async def warn(self, ctx: commands.Context, user: discord.Member, reason: str):
|
||||
"""Warn the user for the specified reason
|
||||
Reason must be a registered reason, or custom if custom reasons are allowed"""
|
||||
reason_type = {}
|
||||
@ -276,7 +275,7 @@ class Warnings:
|
||||
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
async def warnings(self, ctx: RedContext, userid: int=None):
|
||||
async def warnings(self, ctx: commands.Context, userid: int=None):
|
||||
"""Show warnings for the specified user.
|
||||
If userid is None, show warnings for the person running the command
|
||||
Note that showing warnings for users other than yourself requires
|
||||
@ -326,7 +325,7 @@ class Warnings:
|
||||
@commands.command()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(ban_members=True)
|
||||
async def unwarn(self, ctx: RedContext, user_id: int, warn_id: str):
|
||||
async def unwarn(self, ctx: commands.Context, user_id: int, warn_id: str):
|
||||
"""Removes the specified warning from the user specified"""
|
||||
guild = ctx.guild
|
||||
member = guild.get_member(user_id)
|
||||
@ -347,7 +346,7 @@ class Warnings:
|
||||
await ctx.tick()
|
||||
|
||||
@staticmethod
|
||||
async def custom_warning_reason(ctx: RedContext):
|
||||
async def custom_warning_reason(ctx: commands.Context):
|
||||
"""Handles getting description and points for custom reasons"""
|
||||
to_add = {
|
||||
"points": 0,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
from .config import Config
|
||||
from .context import RedContext
|
||||
|
||||
__all__ = ["Config", "RedContext", "__version__"]
|
||||
__all__ = ["Config", "__version__"]
|
||||
|
||||
|
||||
class VersionInfo:
|
||||
|
||||
@ -20,7 +20,7 @@ from .cog_manager import CogManager
|
||||
from . import (
|
||||
Config,
|
||||
i18n,
|
||||
RedContext,
|
||||
commands,
|
||||
rpc
|
||||
)
|
||||
from .help_formatter import Help, help as help_
|
||||
@ -193,7 +193,7 @@ class RedBase(BotBase, RpcMethodMixin):
|
||||
admin_role = await self.db.guild(member.guild).admin_role()
|
||||
return any(role.id in (mod_role, admin_role) for role in member.roles)
|
||||
|
||||
async def get_context(self, message, *, cls=RedContext):
|
||||
async def get_context(self, message, *, cls=commands.Context):
|
||||
return await super().get_context(message, cls=cls)
|
||||
|
||||
def list_packages(self):
|
||||
|
||||
@ -8,11 +8,10 @@ from typing import Tuple, Union, List
|
||||
import redbot.cogs
|
||||
import discord
|
||||
|
||||
from . import checks
|
||||
from . import checks, commands
|
||||
from .config import Config
|
||||
from .i18n import CogI18n
|
||||
from .i18n import Translator, cog_i18n
|
||||
from .data_manager import cog_data_path
|
||||
from discord.ext import commands
|
||||
|
||||
from .utils.chat_formatting import box, pagify
|
||||
|
||||
@ -303,10 +302,13 @@ class CogManager:
|
||||
invalidate_caches()
|
||||
|
||||
|
||||
_ = CogI18n("CogManagerUI", __file__)
|
||||
_ = Translator("CogManagerUI", __file__)
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class CogManagerUI:
|
||||
"""Commands to interface with Red's cog manager."""
|
||||
|
||||
async def visible_paths(self, ctx):
|
||||
install_path = await ctx.bot.cog_mgr.install_path()
|
||||
cog_paths = await ctx.bot.cog_mgr.paths()
|
||||
|
||||
4
redbot/core/commands/__init__.py
Normal file
4
redbot/core/commands/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
from discord.ext.commands import *
|
||||
from .commands import *
|
||||
from .context import *
|
||||
74
redbot/core/commands/commands.py
Normal file
74
redbot/core/commands/commands.py
Normal file
@ -0,0 +1,74 @@
|
||||
"""Module for command helpers and classes.
|
||||
|
||||
This module contains extended classes and functions which are intended to
|
||||
replace those from the `discord.ext.commands` module.
|
||||
"""
|
||||
import inspect
|
||||
|
||||
from discord.ext import commands
|
||||
|
||||
|
||||
__all__ = ["Command", "Group", "command", "group"]
|
||||
|
||||
|
||||
class Command(commands.Command):
|
||||
"""Command class for Red.
|
||||
|
||||
This should not be created directly, and instead via the decorator.
|
||||
|
||||
This class inherits from `discord.ext.commands.Command`.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._help_override = kwargs.pop('help_override', None)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.translator = kwargs.pop("i18n", None)
|
||||
|
||||
@property
|
||||
def help(self):
|
||||
"""Help string for this command.
|
||||
|
||||
If the :code:`help` kwarg was passed into the decorator, it will
|
||||
default to that. If not, it will attempt to translate the docstring
|
||||
of the command's callback function.
|
||||
"""
|
||||
if self._help_override is not None:
|
||||
return self._help_override
|
||||
if self.translator is None:
|
||||
translator = lambda s: s
|
||||
else:
|
||||
translator = self.translator
|
||||
return inspect.cleandoc(translator(self.callback.__doc__))
|
||||
|
||||
@help.setter
|
||||
def help(self, value):
|
||||
# We don't want our help property to be overwritten, namely by super()
|
||||
pass
|
||||
|
||||
|
||||
class Group(Command, commands.Group):
|
||||
"""Group command class for Red.
|
||||
|
||||
This class inherits from `discord.ext.commands.Group`, with `Command` mixed
|
||||
in.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
# decorators
|
||||
|
||||
def command(name=None, cls=Command, **attrs):
|
||||
"""A decorator which transforms an async function into a `Command`.
|
||||
|
||||
Same interface as `discord.ext.commands.command`.
|
||||
"""
|
||||
attrs["help_override"] = attrs.pop("help", None)
|
||||
return commands.command(name, cls, **attrs)
|
||||
|
||||
|
||||
def group(name=None, **attrs):
|
||||
"""A decorator which transforms an async function into a `Group`.
|
||||
|
||||
Same interface as `discord.ext.commands.group`.
|
||||
"""
|
||||
return command(name, cls=Group, **attrs)
|
||||
@ -1,26 +1,23 @@
|
||||
"""
|
||||
The purpose of this module is to allow for Red to further customise the command
|
||||
invocation context provided by discord.py.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from typing import Iterable, List
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core.utils.chat_formatting import box
|
||||
|
||||
__all__ = ["RedContext"]
|
||||
|
||||
TICK = "\N{WHITE HEAVY CHECK MARK}"
|
||||
|
||||
__all__ = ["Context"]
|
||||
|
||||
class RedContext(commands.Context):
|
||||
|
||||
class Context(commands.Context):
|
||||
"""Command invocation context for Red.
|
||||
|
||||
All context passed into commands will be of this type.
|
||||
|
||||
This class inherits from `commands.Context <discord.ext.commands.Context>`.
|
||||
This class inherits from `discord.ext.commands.Context`.
|
||||
"""
|
||||
|
||||
async def send_help(self) -> List[discord.Message]:
|
||||
@ -16,13 +16,12 @@ from distutils.version import StrictVersion
|
||||
import aiohttp
|
||||
import discord
|
||||
import pkg_resources
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core import __version__
|
||||
from redbot.core import checks
|
||||
from redbot.core import i18n
|
||||
from redbot.core import rpc
|
||||
from redbot.core.context import RedContext
|
||||
from redbot.core import commands
|
||||
from .utils import TYPE_CHECKING
|
||||
from .utils.chat_formatting import pagify, box, inline
|
||||
|
||||
@ -39,9 +38,10 @@ OWNER_DISCLAIMER = ("⚠ **Only** the person who is hosting Red should be "
|
||||
"system.** ⚠")
|
||||
|
||||
|
||||
_ = i18n.CogI18n("Core", __file__)
|
||||
_ = i18n.Translator("Core", __file__)
|
||||
|
||||
|
||||
@i18n.cog_i18n(_)
|
||||
class Core:
|
||||
"""Commands related to core functions"""
|
||||
def __init__(self, bot):
|
||||
@ -52,7 +52,7 @@ class Core:
|
||||
rpc.add_method('core', self.rpc_reload)
|
||||
|
||||
@commands.command()
|
||||
async def info(self, ctx: RedContext):
|
||||
async def info(self, ctx: commands.Context):
|
||||
"""Shows info about Red"""
|
||||
author_repo = "https://github.com/Twentysix26"
|
||||
org_repo = "https://github.com/Cog-Creators"
|
||||
@ -103,7 +103,7 @@ class Core:
|
||||
await ctx.send("I need the `Embed links` permission to send this")
|
||||
|
||||
@commands.command()
|
||||
async def uptime(self, ctx: RedContext):
|
||||
async def uptime(self, ctx: commands.Context):
|
||||
"""Shows Red's uptime"""
|
||||
since = ctx.bot.uptime.strftime("%Y-%m-%d %H:%M:%S")
|
||||
passed = self.get_bot_uptime()
|
||||
@ -134,7 +134,7 @@ class Core:
|
||||
return fmt.format(d=days, h=hours, m=minutes, s=seconds)
|
||||
|
||||
@commands.group()
|
||||
async def embedset(self, ctx: RedContext):
|
||||
async def embedset(self, ctx: commands.Context):
|
||||
"""
|
||||
Commands for toggling embeds on or off.
|
||||
|
||||
@ -157,7 +157,7 @@ class Core:
|
||||
|
||||
@embedset.command(name="global")
|
||||
@checks.is_owner()
|
||||
async def embedset_global(self, ctx: RedContext):
|
||||
async def embedset_global(self, ctx: commands.Context):
|
||||
"""
|
||||
Toggle the global embed setting.
|
||||
|
||||
@ -175,7 +175,7 @@ class Core:
|
||||
|
||||
@embedset.command(name="guild")
|
||||
@checks.guildowner_or_permissions(administrator=True)
|
||||
async def embedset_guild(self, ctx: RedContext, enabled: bool=None):
|
||||
async def embedset_guild(self, ctx: commands.Context, enabled: bool=None):
|
||||
"""
|
||||
Toggle the guild's embed setting.
|
||||
|
||||
@ -200,7 +200,7 @@ class Core:
|
||||
)
|
||||
|
||||
@embedset.command(name="user")
|
||||
async def embedset_user(self, ctx: RedContext, enabled: bool=None):
|
||||
async def embedset_user(self, ctx: commands.Context, enabled: bool=None):
|
||||
"""
|
||||
Toggle the user's embed setting.
|
||||
|
||||
@ -834,7 +834,7 @@ class Core:
|
||||
|
||||
@commands.command()
|
||||
@checks.is_owner()
|
||||
async def listlocales(self, ctx: RedContext):
|
||||
async def listlocales(self, ctx: commands.Context):
|
||||
"""
|
||||
Lists all available locales
|
||||
|
||||
|
||||
@ -7,9 +7,8 @@ from contextlib import redirect_stdout
|
||||
from copy import copy
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from . import checks
|
||||
from .i18n import CogI18n
|
||||
from . import checks, commands
|
||||
from .i18n import Translator
|
||||
from .utils.chat_formatting import box, pagify
|
||||
"""
|
||||
Notice:
|
||||
@ -19,7 +18,7 @@ Notice:
|
||||
https://github.com/Rapptz/RoboDanny/blob/master/cogs/repl.py
|
||||
"""
|
||||
|
||||
_ = CogI18n("Dev", __file__)
|
||||
_ = Translator("Dev", __file__)
|
||||
|
||||
|
||||
class Dev:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
"""The checks in this module run on every command."""
|
||||
from discord.ext import commands
|
||||
from . import commands
|
||||
|
||||
|
||||
def init_global_checks(bot):
|
||||
|
||||
@ -28,7 +28,6 @@ from collections import namedtuple
|
||||
from typing import List
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from discord.ext.commands import formatter
|
||||
import inspect
|
||||
import itertools
|
||||
@ -36,6 +35,8 @@ import re
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from . import commands
|
||||
|
||||
|
||||
EMPTY_STRING = u'\u200b'
|
||||
|
||||
@ -133,7 +134,12 @@ class Help(formatter.HelpFormatter):
|
||||
'fields': []
|
||||
}
|
||||
|
||||
description = self.command.description if not self.is_cog() else inspect.getdoc(self.command)
|
||||
if self.is_cog():
|
||||
translator = getattr(self.command, '__translator__', lambda s: s)
|
||||
description = inspect.cleandoc(translator(self.command.__doc__))
|
||||
else:
|
||||
description = self.command.description
|
||||
|
||||
if not description == '' and description is not None:
|
||||
description = '*{0}*'.format(description)
|
||||
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
__all__ = ['get_locale', 'set_locale', 'reload_locales', 'CogI18n']
|
||||
from . import commands
|
||||
|
||||
__all__ = ['get_locale', 'set_locale', 'reload_locales', 'cog_i18n',
|
||||
'Translator']
|
||||
|
||||
_current_locale = 'en_us'
|
||||
|
||||
@ -13,7 +16,7 @@ IN_MSGSTR = 4
|
||||
MSGID = 'msgid "'
|
||||
MSGSTR = 'msgstr "'
|
||||
|
||||
_i18n_cogs = {}
|
||||
_translators = []
|
||||
|
||||
|
||||
def get_locale():
|
||||
@ -27,8 +30,8 @@ def set_locale(locale):
|
||||
|
||||
|
||||
def reload_locales():
|
||||
for cog_name, i18n in _i18n_cogs.items():
|
||||
i18n.load_translations()
|
||||
for translator in _translators:
|
||||
translator.load_translations()
|
||||
|
||||
|
||||
def _parse(translation_file):
|
||||
@ -145,25 +148,36 @@ def get_locale_path(cog_folder: Path, extension: str) -> Path:
|
||||
return cog_folder / 'locales' / "{}.{}".format(get_locale(), extension)
|
||||
|
||||
|
||||
class CogI18n:
|
||||
class Translator:
|
||||
"""Function to get translated strings at runtime."""
|
||||
|
||||
def __init__(self, name, file_location):
|
||||
"""
|
||||
Initializes the internationalization object for a given cog.
|
||||
Initializes an internationalization object.
|
||||
|
||||
:param name: Your cog name.
|
||||
:param file_location:
|
||||
Parameters
|
||||
----------
|
||||
name : str
|
||||
Your cog name.
|
||||
file_location : `str` or `pathlib.Path`
|
||||
This should always be ``__file__`` otherwise your localizations
|
||||
will not load.
|
||||
|
||||
"""
|
||||
self.cog_folder = Path(file_location).resolve().parent
|
||||
self.cog_name = name
|
||||
self.translations = {}
|
||||
|
||||
_i18n_cogs.update({self.cog_name: self})
|
||||
_translators.append(self)
|
||||
|
||||
self.load_translations()
|
||||
|
||||
def __call__(self, untranslated: str):
|
||||
"""Translate the given string.
|
||||
|
||||
This will look for the string in the translator's :code:`.pot` file,
|
||||
with respect to the current locale.
|
||||
"""
|
||||
normalized_untranslated = _normalize(untranslated, True)
|
||||
try:
|
||||
return self.translations[normalized_untranslated]
|
||||
@ -172,7 +186,7 @@ class CogI18n:
|
||||
|
||||
def load_translations(self):
|
||||
"""
|
||||
Loads the current translations for this cog.
|
||||
Loads the current translations.
|
||||
"""
|
||||
self.translations = {}
|
||||
translation_file = None
|
||||
@ -201,3 +215,14 @@ class CogI18n:
|
||||
if translated:
|
||||
self.translations.update({untranslated: translated})
|
||||
|
||||
|
||||
def cog_i18n(translator: Translator):
|
||||
"""Get a class decorator to link the translator to this cog."""
|
||||
def decorator(cog_class: type):
|
||||
cog_class.__translator__ = translator
|
||||
for name, attr in cog_class.__dict__.items():
|
||||
if isinstance(attr, (commands.Group, commands.Command)):
|
||||
attr.translator = translator
|
||||
setattr(cog_class, name, attr)
|
||||
return cog_class
|
||||
return decorator
|
||||
|
||||
197
redbot/core/locales/debugging.po
Normal file
197
redbot/core/locales/debugging.po
Normal file
@ -0,0 +1,197 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR ORGANIZATION
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"POT-Creation-Date: 2017-12-06 11:27+1100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=cp1252\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
|
||||
|
||||
#: ../cog_manager.py:21
|
||||
#, docstring
|
||||
msgid ""
|
||||
"Directory manager for Red's cogs.\n"
|
||||
"\n"
|
||||
" This module allows you to load cogs from multiple directories and even from\n"
|
||||
" outside the bot directory. You may also set a directory for downloader to\n"
|
||||
" install new cogs to, the default being the :code:`cogs/` folder in the root\n"
|
||||
" bot directory.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:40
|
||||
#, docstring
|
||||
msgid ""
|
||||
"Get all currently valid path directories.\n"
|
||||
"\n"
|
||||
" Returns\n"
|
||||
" -------\n"
|
||||
" `tuple` of `pathlib.Path`\n"
|
||||
" All valid cog paths.\n"
|
||||
"\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:64
|
||||
#, docstring
|
||||
msgid ""
|
||||
"Get the install path for 3rd party cogs.\n"
|
||||
"\n"
|
||||
" Returns\n"
|
||||
" -------\n"
|
||||
" pathlib.Path\n"
|
||||
" The path to the directory where 3rd party cogs are stored.\n"
|
||||
"\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:273
|
||||
#, docstring
|
||||
msgid ""
|
||||
"Finds the names of all available modules to load.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:285
|
||||
#, docstring
|
||||
msgid ""
|
||||
"Re-evaluate modules in the py cache.\n"
|
||||
"\n"
|
||||
" This is an alias for an importlib internal and should be called\n"
|
||||
" any time that a new module has been installed to a cog directory.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:298
|
||||
#, docstring
|
||||
msgid ""
|
||||
"Commands to interface with Red's cog manager."
|
||||
msgstr ""
|
||||
"(TRANSLATED) Commands to interface with Red's cog manager."
|
||||
|
||||
#: ../cog_manager.py:302
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Lists current cog paths in order of priority."
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" (TRANSLATED) Lists current cog paths in order of priority."
|
||||
" "
|
||||
|
||||
#: ../cog_manager.py:321
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Add a path to the list of available cog paths."
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" (TRANSLATED) Add a path to the list of available cog paths."
|
||||
" "
|
||||
|
||||
#: ../cog_manager.py:340
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Removes a path from the available cog paths given the path_number"
|
||||
" from !paths"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" (TRANSLATED) Removes a path from the available cog paths given the path_number"
|
||||
" from !paths"
|
||||
" "
|
||||
|
||||
#: ../cog_manager.py:357
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Reorders paths internally to allow discovery of different cogs."
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" (TRANSLATED) Reorders paths internally to allow discovery of different cogs."
|
||||
" "
|
||||
|
||||
#: ../cog_manager.py:383
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Returns the current install path or sets it if one is provided."
|
||||
" The provided path must be absolute or relative to the bot's"
|
||||
" directory and it must already exist."
|
||||
"\n"
|
||||
" No installed cogs will be transferred in the process."
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" (TRANSLATED) Returns the current install path or sets it if one is provided."
|
||||
" The provided path must be absolute or relative to the bot's"
|
||||
" directory and it must already exist."
|
||||
"\n"
|
||||
" No installed cogs will be transferred in the process."
|
||||
" "
|
||||
|
||||
#: ../cog_manager.py:406
|
||||
#, docstring
|
||||
msgid ""
|
||||
"\n"
|
||||
" Lists all loaded and available cogs."
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" (TRANSLATED) Lists all loaded and available cogs."
|
||||
" "
|
||||
|
||||
#: ../cog_manager.py:309
|
||||
msgid ""
|
||||
"Install Path: {}\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:325
|
||||
msgid "That path is does not exist or does not point to a valid directory."
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:334
|
||||
msgid "Path successfully added."
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:347
|
||||
msgid "That is an invalid path number."
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:351
|
||||
msgid "Path successfully removed."
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:367
|
||||
msgid "Invalid 'from' index."
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:373
|
||||
msgid "Invalid 'to' index."
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:377
|
||||
msgid "Paths reordered."
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:395
|
||||
msgid "That path does not exist."
|
||||
msgstr ""
|
||||
|
||||
#: ../cog_manager.py:399
|
||||
msgid "The bot will install new cogs to the `{}` directory."
|
||||
msgstr ""
|
||||
|
||||
@ -7,10 +7,10 @@ Ported to Red V3 by Palm__ (https://github.com/palmtree5)
|
||||
import asyncio
|
||||
import discord
|
||||
|
||||
from redbot.core import RedContext
|
||||
from redbot.core import commands
|
||||
|
||||
|
||||
async def menu(ctx: RedContext, pages: list,
|
||||
async def menu(ctx: commands.Context, pages: list,
|
||||
controls: dict,
|
||||
message: discord.Message=None, page: int=0,
|
||||
timeout: float=30.0):
|
||||
@ -28,7 +28,7 @@ async def menu(ctx: RedContext, pages: list,
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ctx: RedContext
|
||||
ctx: commands.Context
|
||||
The command context
|
||||
pages: `list` of `str` or `discord.Embed`
|
||||
The pages of the menu.
|
||||
@ -92,7 +92,7 @@ async def menu(ctx: RedContext, pages: list,
|
||||
timeout, react.emoji)
|
||||
|
||||
|
||||
async def next_page(ctx: RedContext, pages: list,
|
||||
async def next_page(ctx: commands.Context, pages: list,
|
||||
controls: dict, message: discord.Message, page: int,
|
||||
timeout: float, emoji: str):
|
||||
perms = message.channel.permissions_for(ctx.guild.me)
|
||||
@ -109,7 +109,7 @@ async def next_page(ctx: RedContext, pages: list,
|
||||
page=page, timeout=timeout)
|
||||
|
||||
|
||||
async def prev_page(ctx: RedContext, pages: list,
|
||||
async def prev_page(ctx: commands.Context, pages: list,
|
||||
controls: dict, message: discord.Message, page: int,
|
||||
timeout: float, emoji: str):
|
||||
perms = message.channel.permissions_for(ctx.guild.me)
|
||||
@ -126,7 +126,7 @@ async def prev_page(ctx: RedContext, pages: list,
|
||||
page=next_page, timeout=timeout)
|
||||
|
||||
|
||||
async def close_menu(ctx: RedContext, pages: list,
|
||||
async def close_menu(ctx: commands.Context, pages: list,
|
||||
controls: dict, message: discord.Message, page: int,
|
||||
timeout: float, emoji: str):
|
||||
if message:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user