diff options
| -rw-r--r-- | bot/exts/help_channels/_cog.py | 2 | ||||
| -rw-r--r-- | bot/exts/info/information.py | 5 | ||||
| -rw-r--r-- | bot/exts/recruitment/talentpool/_review.py | 22 | ||||
| -rw-r--r-- | bot/resources/tags/dunder-methods.md | 28 | ||||
| -rw-r--r-- | config-default.yml | 2 | 
5 files changed, 42 insertions, 17 deletions
| diff --git a/bot/exts/help_channels/_cog.py b/bot/exts/help_channels/_cog.py index a9b847582..35658d117 100644 --- a/bot/exts/help_channels/_cog.py +++ b/bot/exts/help_channels/_cog.py @@ -594,7 +594,7 @@ class HelpChannels(commands.Cog):                  await bot_commands_channel.send(                      f"{message.author.mention} {constants.Emojis.cross_mark} "                      "To receive updates on help channels you're active in, enable your DMs.", -                    delete_after=RedirectOutput.delete_after +                    delete_after=RedirectOutput.delete_delay                  )                  return diff --git a/bot/exts/info/information.py b/bot/exts/info/information.py index 834fee1b4..1b1243118 100644 --- a/bot/exts/info/information.py +++ b/bot/exts/info/information.py @@ -241,8 +241,6 @@ class Information(Cog):              if is_set and (emoji := getattr(constants.Emojis, f"badge_{badge}", None)):                  badges.append(emoji) -        activity = await self.user_messages(user) -          if on_server:              joined = time_since(user.joined_at, max_units=3)              roles = ", ".join(role.mention for role in user.roles[1:]) @@ -272,8 +270,7 @@ class Information(Cog):          # Show more verbose output in moderation channels for infractions and nominations          if is_mod_channel(ctx.channel): -            fields.append(activity) - +            fields.append(await self.user_messages(user))              fields.append(await self.expanded_user_infraction_counts(user))              fields.append(await self.user_nomination_counts(user))          else: diff --git a/bot/exts/recruitment/talentpool/_review.py b/bot/exts/recruitment/talentpool/_review.py index b9ff61986..0cb786e4b 100644 --- a/bot/exts/recruitment/talentpool/_review.py +++ b/bot/exts/recruitment/talentpool/_review.py @@ -75,7 +75,7 @@ class Reviewer:      async def post_review(self, user_id: int, update_database: bool) -> None:          """Format the review of a user and post it to the nomination voting channel.""" -        review, seen_emoji = await self.make_review(user_id) +        review, reviewed_emoji = await self.make_review(user_id)          if not review:              return @@ -88,8 +88,8 @@ class Reviewer:          await pin_no_system_message(messages[0])          last_message = messages[-1] -        if seen_emoji: -            for reaction in (seen_emoji, "\N{THUMBS UP SIGN}", "\N{THUMBS DOWN SIGN}"): +        if reviewed_emoji: +            for reaction in (reviewed_emoji, "\N{THUMBS UP SIGN}", "\N{THUMBS DOWN SIGN}"):                  await last_message.add_reaction(reaction)          if update_database: @@ -97,7 +97,7 @@ class Reviewer:              await self.bot.api_client.patch(f"{self._pool.api_endpoint}/{nomination['id']}", json={"reviewed": True})      async def make_review(self, user_id: int) -> typing.Tuple[str, Optional[Emoji]]: -        """Format a generic review of a user and return it with the seen emoji.""" +        """Format a generic review of a user and return it with the reviewed emoji."""          log.trace(f"Formatting the review of {user_id}")          # Since `watched_users` is a defaultdict, we should take care @@ -127,15 +127,15 @@ class Reviewer:          review_body = await self._construct_review_body(member) -        seen_emoji = self._random_ducky(guild) +        reviewed_emoji = self._random_ducky(guild)          vote_request = (              "*Refer to their nomination and infraction histories for further details*.\n" -            f"*Please react {seen_emoji} if you've seen this post." -            " Then react :+1: for approval, or :-1: for disapproval*." +            f"*Please react {reviewed_emoji} once you have reviewed this user," +            " and react :+1: for approval, or :-1: for disapproval*."          )          review = "\n\n".join((opening, current_nominations, review_body, vote_request)) -        return review, seen_emoji +        return review, reviewed_emoji      async def archive_vote(self, message: PartialMessage, passed: bool) -> None:          """Archive this vote to #nomination-archive.""" @@ -163,7 +163,7 @@ class Reviewer:          user_id = int(MENTION_RE.search(content).group(1))          # Get reaction counts -        seen = await count_unique_users_reaction( +        reviewed = await count_unique_users_reaction(              messages[0],              lambda r: "ducky" in str(r) or str(r) == "\N{EYES}",              count_bots=False @@ -188,7 +188,7 @@ class Reviewer:          embed_content = (              f"{result} on {timestamp}\n" -            f"With {seen} {Emojis.ducky_dave} {upvotes} :+1: {downvotes} :-1:\n\n" +            f"With {reviewed} {Emojis.ducky_dave} {upvotes} :+1: {downvotes} :-1:\n\n"              f"{stripped_content}"          ) @@ -357,7 +357,7 @@ class Reviewer:      @staticmethod      def _random_ducky(guild: Guild) -> Union[Emoji, str]: -        """Picks a random ducky emoji to be used to mark the vote as seen. If no duckies found returns :eyes:.""" +        """Picks a random ducky emoji. If no duckies found returns :eyes:."""          duckies = [emoji for emoji in guild.emojis if emoji.name.startswith("ducky")]          if not duckies:              return ":eyes:" diff --git a/bot/resources/tags/dunder-methods.md b/bot/resources/tags/dunder-methods.md new file mode 100644 index 000000000..be2b97b7b --- /dev/null +++ b/bot/resources/tags/dunder-methods.md @@ -0,0 +1,28 @@ +**Dunder methods** + +Double-underscore methods, or "dunder" methods, are special methods defined in a class that are invoked implicitly. Like the name suggests, they are prefixed and suffixed with dunders. You've probably already seen some, such as the `__init__` dunder method, also known as the "constructor" of a class, which is implicitly invoked when you instantiate an instance of a class. + +When you create a new class, there will be default dunder methods inherited from the `object` class. However, we can override them by redefining these methods within the new class. For example, the default `__init__` method from `object` doesn't take any arguments, so we almost always override that to fit our needs. + +Other common dunder methods to override are `__str__` and `__repr__`. `__repr__` is the developer-friendly string representation of an object - usually the syntax to recreate it - and is implicitly called on arguments passed into the `repr` function. `__str__` is the user-friendly string representation of an object, and is called by the `str` function. Note here that, if not overriden, the default `__str__` invokes `__repr__` as a fallback. + +```py +class Foo: +    def __init__(self, value):  # constructor +        self.value = value +    def __str__(self): +        return f"This is a Foo object, with a value of {self.value}!"  # string representation +    def __repr__(self): +        return f"Foo({self.value!r})"  # way to recreate this object + + +bar = Foo(5) + +# print also implicitly calls __str__ +print(bar)  # Output: This is a Foo object, with a value of 5! + +# dev-friendly representation +print(repr(bar))  # Output: Foo(5) +``` + +Another example: did you know that when you use the `<left operand> + <right operand>` syntax, you're implicitly calling `<left operand>.__add__(<right operand>)`? The same applies to other operators, and you can look at the [`operator` built-in module documentation](https://docs.python.org/3/library/operator.html) for more information! diff --git a/config-default.yml b/config-default.yml index 863a4535e..f4fdc7606 100644 --- a/config-default.yml +++ b/config-default.yml @@ -398,7 +398,7 @@ anti_spam:          chars:              interval: 5 -            max: 3_000 +            max: 4_200          discord_emojis:              interval: 10 | 
