From 2682d58d20145aa0d462f732cc361d29d85e65ab Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 5 Sep 2021 01:21:34 +0800 Subject: [PATCH 001/225] oops --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e7438ca373..4dc7d411a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,5 +34,5 @@ repository = 'https://github.com/kyb3r/modmail' homepage = 'https://github.com/kyb3r/modmail' keywords = ['discord', 'modmail'] -[tool.pylint.format]react_to_contact_message +[tool.pylint.format] max-line-length = "110" From e311828d32cd13ab0ce6a33d3362cd52ea49b69d Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 6 Sep 2021 01:10:18 +0800 Subject: [PATCH 002/225] Improved UI for group conversations, LOG_DISCORD, snippet fix --- CHANGELOG.md | 14 ++++++++++++++ README.md | 2 +- bot.py | 11 ++++++++++- cogs/modmail.py | 11 +++++++++++ core/thread.py | 37 +++++++++++++++++++++++++++++++++++-- pyproject.toml | 2 +- 6 files changed, 72 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af6e0cc407..85fc813322 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html); however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. +# v3.10.3 + +### Improved + +- Thread genesis message now shows other recipients. + +### Fixed + +- `?snippet add` now properly blocks command names. + +### Internal + +- Set `LOG_DISCORD` environment variable to the logger level and log discord events. + # v3.10.2 This is a hotfix for react to contact. diff --git a/README.md b/README.md index f4b8e8d2ff..9730cd1339 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@
- +
diff --git a/bot.py b/bot.py index 7d4248173c..86ef132b40 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "3.10.2" +__version__ = "3.10.3" import asyncio @@ -1694,6 +1694,15 @@ def main(): ) sys.exit(0) + if os.environ.get("LOG_DISCORD"): + logger.debug(f"Discord logging enabled: {os.environ['LOG_DISCORD'].upper()}") + d_logger = logging.getLogger("discord") + + d_logger.setLevel(os.environ["LOG_DISCORD"].upper()) + handler = logging.FileHandler(filename="discord.log", encoding="utf-8", mode="w") + handler.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s")) + d_logger.addHandler(handler) + bot = ModmailBot() bot.run() diff --git a/cogs/modmail.py b/cogs/modmail.py index bb3860bfde..4a974b26cc 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -212,6 +212,7 @@ async def snippet_add(self, ctx, name: str.lower, *, value: commands.clean_conte color=self.bot.error_color, description=f"A command with the same name already exists: `{name}`.", ) + return await ctx.send(embed=embed) elif name in self.bot.snippets: embed = discord.Embed( title="Error", @@ -813,6 +814,16 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role, ctx.command.reset_cooldown(ctx) return + if not users: + em = discord.Embed( + title="Error", + description="No valid users to remove.", + color=self.bot.error_color, + ) + await ctx.send(embed=em) + ctx.command.reset_cooldown(ctx) + return + if not silent: description = self.bot.formatter.format( self.bot.config["private_removed_from_group_response"], moderator=ctx.author diff --git a/core/thread.py b/core/thread.py index 54509cdc36..fc48f88f5b 100644 --- a/core/thread.py +++ b/core/thread.py @@ -51,7 +51,7 @@ def __init__( self._recipient = recipient self._other_recipients = other_recipients or [] self._channel = channel - self.genesis_message = None + self._genesis_message = None self._ready_event = asyncio.Event() self.wait_tasks = [] self.close_task = None @@ -140,6 +140,15 @@ async def from_channel(cls, manager: "ThreadManager", channel: discord.TextChann return thread + async def get_genesis_message(self) -> discord.Message: + if self._genesis_message is None: + async for m in self.channel.history(limit=5, oldest_first=True): + if m.author == self.bot.user: + if m.embeds and m.embeds[0].fields and m.embeds[0].fields[0].name == "Roles": + self._genesis_message = m + + return self._genesis_message + async def setup(self, *, creator=None, category=None, initial_message=None): """Create the thread channel and other io related initialisation tasks""" self.bot.dispatch("thread_initiate", self, creator, category, initial_message) @@ -195,7 +204,7 @@ async def send_genesis_message(): try: msg = await channel.send(mention, embed=info_embed) self.bot.loop.create_task(msg.pin()) - self.genesis_message = msg + self._genesis_message = msg except Exception: logger.error("Failed unexpectedly:", exc_info=True) @@ -1131,6 +1140,26 @@ async def set_title(self, title: str) -> None: await self.channel.edit(topic=f"Title: {title}\nUser ID: {user_id}\nOther Recipients: {ids}") + async def _update_users_genesis(self): + genesis_message = await self.get_genesis_message() + embed = genesis_message.embeds[0] + value = " ".join(x.mention for x in self._other_recipients) + index = None + for n, field in enumerate(embed.fields): + if field.name == "Other Recipients": + index = n + break + + if index is None and value: + embed.add_field(name="Other Recipients", value=value, inline=False) + else: + if value: + embed.set_field_at(index, value=value) + else: + embed.remove_field(index) + + await genesis_message.edit(embed=embed) + async def add_users(self, users: typing.List[typing.Union[discord.Member, discord.User]]) -> None: title = match_title(self.channel.topic) user_id = match_user_id(self.channel.topic) @@ -1139,6 +1168,8 @@ async def add_users(self, users: typing.List[typing.Union[discord.Member, discor ids = ",".join(str(i.id) for i in self._other_recipients) await self.channel.edit(topic=f"Title: {title}\nUser ID: {user_id}\nOther Recipients: {ids}") + await self._update_users_genesis() + async def remove_users(self, users: typing.List[typing.Union[discord.Member, discord.User]]) -> None: title = match_title(self.channel.topic) user_id = match_user_id(self.channel.topic) @@ -1148,6 +1179,8 @@ async def remove_users(self, users: typing.List[typing.Union[discord.Member, dis ids = ",".join(str(i.id) for i in self._other_recipients) await self.channel.edit(topic=f"Title: {title}\nUser ID: {user_id}\nOther Recipients: {ids}") + await self._update_users_genesis() + class ThreadManager: """Class that handles storing, finding and creating Modmail threads.""" diff --git a/pyproject.toml b/pyproject.toml index 4dc7d411a5..341e506413 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '3.10.2' +version = '3.10.3' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 6431ab04980eae662151e7d7d4ed3ea02d08c280 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 6 Sep 2021 01:20:22 +0800 Subject: [PATCH 003/225] Fix typo in config_help --- core/config_help.json | 2 +- core/thread.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/config_help.json b/core/config_help.json index ee91e3d37d..1bfd65a92b 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -426,7 +426,7 @@ "default": "\"You have opened a Modmail thread.\"", "description": "This is the message embed description sent to recipients when self-contacted.", "examples": [ - "`{prefix}config set thread_creation_contact_title You contacted yourself.`" + "`{prefix}config set thread_creation_self_contact_response You contacted yourself.`" ], "notes": [ "`thread_creation_contact_response` is used when contacted by another user.", diff --git a/core/thread.py b/core/thread.py index fc48f88f5b..e17a581630 100644 --- a/core/thread.py +++ b/core/thread.py @@ -805,7 +805,8 @@ async def note( async def reply( self, message: discord.Message, anonymous: bool = False, plain: bool = False - ) -> typing.Tuple[discord.Message, discord.Message]: + ) -> typing.Tuple[typing.List[discord.Message], discord.Message]: + """Returns List[user_dm_msg] and thread_channel_msg""" if not message.content and not message.attachments: raise MissingRequiredArgument(SimpleNamespace(name="msg")) if not any(g.get_member(self.id) for g in self.bot.guilds): From fc156f9601798246b2dca04764f0c861069d1ec2 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 6 Sep 2021 01:22:20 +0800 Subject: [PATCH 004/225] Fix syntax --- core/thread.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/thread.py b/core/thread.py index e17a581630..6bc7adc6cb 100644 --- a/core/thread.py +++ b/core/thread.py @@ -806,7 +806,7 @@ async def note( async def reply( self, message: discord.Message, anonymous: bool = False, plain: bool = False ) -> typing.Tuple[typing.List[discord.Message], discord.Message]: - """Returns List[user_dm_msg] and thread_channel_msg""" + """Returns List[user_dm_msg] and thread_channel_msg""" if not message.content and not message.attachments: raise MissingRequiredArgument(SimpleNamespace(name="msg")) if not any(g.get_member(self.id) for g in self.bot.guilds): From 68827f7ad13f6842dfe19f4715d1f63c479c1cf7 Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Tue, 7 Sep 2021 09:01:53 +0800 Subject: [PATCH 005/225] Fix `?contact` command bug where the channel is created inside random category when `silent` or `silently` is passed in. Resolve #3091 --- cogs/modmail.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index 4a974b26cc..937ef61ca5 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1362,9 +1362,16 @@ async def contact( """ silent = False if isinstance(category, str): - if "silent" in category or "silently" in category: + category = category.split() + + # just check the last element in the list + if category[-1].lower() in ("silent", "silently"): silent = True - category = category.strip("silently").strip("silent").strip() + # remove the last element as we no longer need it + category.pop() + + category = " ".join(category) + if category: try: category = await SimilarCategoryConverter().convert( ctx, category From 7922a97939c1d78da4a57bf8ed793527572c36b1 Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Tue, 7 Sep 2021 13:09:44 +1000 Subject: [PATCH 006/225] Allow top role's hoisted check to be configurable. --- cogs/modmail.py | 4 ++-- core/config.py | 2 ++ core/thread.py | 6 +++--- core/utils.py | 6 ++++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index 4a974b26cc..fdbc27429b 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -918,7 +918,7 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, tag = self.bot.config["mod_tag"] if tag is None: - tag = str(get_top_hoisted_role(ctx.author)) + tag = str(get_top_role(ctx.author, self.bot.config["use_hoisted_top_role"])) name = self.bot.config["anon_username"] if name is None: name = tag @@ -1003,7 +1003,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro tag = self.bot.config["mod_tag"] if tag is None: - tag = str(get_top_hoisted_role(ctx.author)) + tag = str(get_top_role(ctx.author, self.bot.config["use_hoisted_top_role"])) name = self.bot.config["anon_username"] if name is None: name = tag diff --git a/core/config.py b/core/config.py index d8593a02ef..e9de7d516d 100644 --- a/core/config.py +++ b/core/config.py @@ -123,6 +123,7 @@ class ConfigManager: "confirm_thread_creation_deny": "\N{NO ENTRY SIGN}", # regex "use_regex_autotrigger": False, + "use_hoisted_top_role": True, } private_keys = { @@ -209,6 +210,7 @@ class ConfigManager: "thread_show_roles", "thread_show_account_age", "thread_show_join_age", + "use_hoisted_top_role", } enums = { diff --git a/core/thread.py b/core/thread.py index 6bc7adc6cb..e20a7d1110 100644 --- a/core/thread.py +++ b/core/thread.py @@ -21,7 +21,7 @@ match_user_id, match_other_recipients, truncate, - get_top_hoisted_role, + get_top_role, create_thread_channel, get_joint_id, ) @@ -938,7 +938,7 @@ async def send( # Anonymously sending to the user. tag = self.bot.config["mod_tag"] if tag is None: - tag = str(get_top_hoisted_role(author)) + tag = str(get_top_role(author, self.bot.config["use_hoisted_top_role"])) name = self.bot.config["anon_username"] if name is None: name = tag @@ -1055,7 +1055,7 @@ async def send( elif not anonymous: mod_tag = self.bot.config["mod_tag"] if mod_tag is None: - mod_tag = str(get_top_hoisted_role(message.author)) + mod_tag = str(get_top_role(message.author, self.bot.config["use_hoisted_top_role"])) embed.set_footer(text=mod_tag) # Normal messages else: embed.set_footer(text=self.bot.config["anon_tag"]) diff --git a/core/utils.py b/core/utils.py index 0fa74e457a..44df043938 100644 --- a/core/utils.py +++ b/core/utils.py @@ -30,7 +30,7 @@ "trigger_typing", "escape_code_block", "tryint", - "get_top_hoisted_role", + "get_top_role", "get_joint_id", ] @@ -369,9 +369,11 @@ def tryint(x): return x -def get_top_hoisted_role(member: discord.Member): +def get_top_role(member: discord.Member, hoisted=True): roles = sorted(member.roles, key=lambda r: r.position, reverse=True) for role in roles: + if not hoisted: + return role if role.hoist: return role From 655e063e7ba200fcce770b4d8d3d103f236d7e1d Mon Sep 17 00:00:00 2001 From: scragly <29337040+scragly@users.noreply.github.com> Date: Tue, 7 Sep 2021 18:55:32 +1000 Subject: [PATCH 007/225] Add use_hoisted_top_role config help details. --- core/config_help.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/config_help.json b/core/config_help.json index 1bfd65a92b..d7bbcf5da8 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -1121,5 +1121,16 @@ "notes": [ "This configuration can only to be set through `.env` file or environment (config) variables." ] + }, + "use_hoisted_top_role": { + "default": "Yes", + "description": "Controls if only hoisted roles are evaluated when finding top role.", + "examples": [ + ], + "notes": [ + "Top role is displayed in embeds when replying or adding/removing users to a thread in the case mod_tag and anon_username are not set.", + "If this configuration is enabled, only roles that are hoisted (displayed seperately in member list) will be used. If a user has no hoisted roles, it will return 'None'.", + "If you would like to display the top role of a user regardless of if it's hoisted or not, disable `use_hoisted_top_role`." + ] } } From c5b311ba6c545627304c43c432628f5ccb14d299 Mon Sep 17 00:00:00 2001 From: Andy <49132750+matrix2113@users.noreply.github.com> Date: Wed, 8 Sep 2021 20:23:16 -0400 Subject: [PATCH 008/225] Fix typo --- core/config_help.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/config_help.json b/core/config_help.json index ee91e3d37d..88d0e2e47e 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -227,7 +227,7 @@ "default": "Yes", "description": "This is the channel where update notifications are sent to.", "examples": [ - "`{prefix}config set update_notifications no" + "`{prefix}config set update_notifications no`" ], "notes": [ "This has no effect unless `disable_autoupdates` is set to no.", From c65a5b785473786e96949c5237e688ca5c46b6a9 Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Tue, 21 Sep 2021 21:26:48 +0530 Subject: [PATCH 009/225] Fetch thread closers if needed. --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 7d4248173c..a04661cc5f 100644 --- a/bot.py +++ b/bot.py @@ -582,7 +582,7 @@ async def on_ready(self): continue await thread.close( - closer=self.get_user(items["closer_id"]), + closer=self.get_user(items["closer_id"]) or await self.fetch_user(items["closer_id"]), after=after, silent=items["silent"], delete_channel=items["delete_channel"], From e87669c214ece58558e2cf9566e632e21f826634 Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Tue, 21 Sep 2021 21:27:08 +0530 Subject: [PATCH 010/225] Add the get_or_fetch_user method. --- bot.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bot.py b/bot.py index a04661cc5f..8cafda33b0 100644 --- a/bot.py +++ b/bot.py @@ -656,6 +656,15 @@ async def convert_emoji(self, name: str) -> str: raise return name + async def get_or_fetch_user(self, id: int) -> discord.User: + """ + Retrieve a User based on their ID. + + This tries getting the user from the cache and falls back to making + an API call if they're not found in the cache. + """ + return self.get_user(id) or await self.fetch_user(id) + async def retrieve_emoji(self) -> typing.Tuple[str, str]: sent_emoji = self.config["sent_emoji"] From 0e4c3749e4ccd4aa05837f9531b506d052fec781 Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Tue, 21 Sep 2021 21:34:41 +0530 Subject: [PATCH 011/225] Use the method where possible to tidy up code. --- bot.py | 2 +- cogs/modmail.py | 19 ++++++++----------- core/thread.py | 8 ++++---- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/bot.py b/bot.py index 8cafda33b0..f19725a954 100644 --- a/bot.py +++ b/bot.py @@ -582,7 +582,7 @@ async def on_ready(self): continue await thread.close( - closer=self.get_user(items["closer_id"]) or await self.fetch_user(items["closer_id"]), + closer=await self.get_or_fetch_user(items["closer_id"]), after=after, silent=items["silent"], delete_channel=items["delete_channel"], diff --git a/cogs/modmail.py b/cogs/modmail.py index bb3860bfde..814113f617 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1042,7 +1042,7 @@ async def logs(self, ctx, *, user: User = None): thread = ctx.thread if not thread: raise commands.MissingRequiredArgument(SimpleNamespace(name="member")) - user = thread.recipient or await self.bot.fetch_user(thread.id) + user = thread.recipient or await self.bot.get_or_fetch_user(thread.id) default_avatar = "https://cdn.discordapp.com/embed/avatars/0.png" icon_url = getattr(user, "avatar_url", default_avatar) @@ -1492,15 +1492,12 @@ async def blocked(self, ctx): logger.debug("No longer blocked, user %s.", id_) continue - user = self.bot.get_user(int(id_)) - if user: - users.append((user.mention, reason)) + try: + user = await self.bot.get_or_fetch_user(int(id_)) + except discord.NotFound: + users.append((id_, reason)) else: - try: - user = await self.bot.fetch_user(id_) - users.append((user.mention, reason)) - except discord.NotFound: - users.append((id_, reason)) + users.append((user.mention, reason)) blocked_roles = list(self.bot.blocked_roles.items()) for id_, reason in blocked_roles: @@ -1840,7 +1837,7 @@ async def repair(self, ctx): user_id = match_user_id(message.embeds[0].footer.text) other_recipients = match_other_recipients(ctx.channel.topic) for n, uid in enumerate(other_recipients): - other_recipients[n] = self.bot.get_user(uid) or await self.bot.fetch_user(uid) + other_recipients[n] = await self.bot.get_or_fetch_user(uid) if user_id != -1: recipient = self.bot.get_user(user_id) @@ -1893,7 +1890,7 @@ async def repair(self, ctx): other_recipients = match_other_recipients(ctx.channel.topic) for n, uid in enumerate(other_recipients): - other_recipients[n] = self.bot.get_user(uid) or await self.bot.fetch_user(uid) + other_recipients[n] = await self.bot.get_or_fetch_user(uid) if recipient is None: self.bot.threads.cache[user.id] = thread = Thread( diff --git a/core/thread.py b/core/thread.py index 54509cdc36..c4fa7bbf07 100644 --- a/core/thread.py +++ b/core/thread.py @@ -126,12 +126,12 @@ async def from_channel(cls, manager: "ThreadManager", channel: discord.TextChann if recipient_id in manager.cache: thread = manager.cache[recipient_id] else: - recipient = manager.bot.get_user(recipient_id) or await manager.bot.fetch_user(recipient_id) + recipient = await manager.bot.get_or_fetch_user(recipient_id) other_recipients = [] for uid in match_other_recipients(channel.topic): try: - other_recipient = manager.bot.get_user(uid) or await manager.bot.fetch_user(uid) + other_recipient = await manager.bot.get_or_fetch_user(uid) except discord.NotFound: continue other_recipients.append(other_recipient) @@ -1243,14 +1243,14 @@ async def _find_from_channel(self, channel): return self.cache[user_id] try: - recipient = self.bot.get_user(user_id) or await self.bot.fetch_user(user_id) + recipient = await self.bot.get_or_fetch_user(user_id) except discord.NotFound: recipient = None other_recipients = [] for uid in match_other_recipients(channel.topic): try: - other_recipient = self.bot.get_user(uid) or await self.bot.fetch_user(uid) + other_recipient = await self.bot.get_or_fetch_user(uid) except discord.NotFound: continue other_recipients.append(other_recipient) From 9d0014284b8d31df96aa983a74e2a1ed1ec0f79a Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Sun, 3 Oct 2021 03:16:09 +0800 Subject: [PATCH 012/225] Rename `category` to `fallback` due to shadowing names. --- core/utils.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/utils.py b/core/utils.py index 0fa74e457a..aaaf7e463d 100644 --- a/core/utils.py +++ b/core/utils.py @@ -393,19 +393,20 @@ async def create_thread_channel(bot, recipient, category, overwrites, *, name=No errors_raised.append((e.text, (category, name))) if "Maximum number of channels in category reached" in e.text: + fallback = None fallback_id = bot.config["fallback_category_id"] if fallback_id: fallback = discord.utils.get(category.guild.categories, id=int(fallback_id)) - if fallback and len(fallback.channels) < 49: - category = fallback + if fallback and len(fallback.channels) >= 49: + fallback = None - if not category: - category = await category.clone(name="Fallback Modmail") + if not fallback: + fallback = await category.clone(name="Fallback Modmail") bot.config.set("fallback_category_id", str(category.id)) await bot.config.update() return await create_thread_channel( - bot, recipient, category, overwrites, errors_raised=errors_raised + bot, recipient, fallback, overwrites, errors_raised=errors_raised ) if "Contains words not allowed" in e.text: From 8b69b67f22430b2adf719d5c6f0fa0ba1d605943 Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:55:59 +0800 Subject: [PATCH 013/225] Forgot to update the reference in `.config.set()`. --- core/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/utils.py b/core/utils.py index aaaf7e463d..2c58fe69d6 100644 --- a/core/utils.py +++ b/core/utils.py @@ -402,7 +402,7 @@ async def create_thread_channel(bot, recipient, category, overwrites, *, name=No if not fallback: fallback = await category.clone(name="Fallback Modmail") - bot.config.set("fallback_category_id", str(category.id)) + bot.config.set("fallback_category_id", str(fallback.id)) await bot.config.update() return await create_thread_channel( From b388f0eeca0ccf1200684cb278a0747fa6ada239 Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Wed, 6 Oct 2021 01:57:01 +0800 Subject: [PATCH 014/225] Change default value for `errors_raised` parameter to `None`. --- core/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/utils.py b/core/utils.py index 2c58fe69d6..1fa1a95e61 100644 --- a/core/utils.py +++ b/core/utils.py @@ -376,8 +376,10 @@ def get_top_hoisted_role(member: discord.Member): return role -async def create_thread_channel(bot, recipient, category, overwrites, *, name=None, errors_raised=[]): +async def create_thread_channel(bot, recipient, category, overwrites, *, name=None, errors_raised=None): name = name or bot.format_channel_name(recipient) + errors_raised = errors_raised or [] + try: channel = await bot.modmail_guild.create_text_channel( name=name, From 3f393e03a550c1137ac66e3170cdf9145669b28c Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Sun, 10 Oct 2021 00:47:01 +0800 Subject: [PATCH 015/225] New regex to properly match/parse channel topics. --- cogs/modmail.py | 2 +- core/thread.py | 52 +++++++++++++++++++++++------------- core/utils.py | 71 ++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 91 insertions(+), 34 deletions(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index 4a974b26cc..e3c19d8182 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1848,7 +1848,7 @@ async def repair(self, ctx): and message.embeds[0].color.value == self.bot.main_color and message.embeds[0].footer.text ): - user_id = match_user_id(message.embeds[0].footer.text) + user_id = match_user_id(message.embeds[0].footer.text, any_string=True) other_recipients = match_other_recipients(ctx.channel.topic) for n, uid in enumerate(other_recipients): other_recipients[n] = self.bot.get_user(uid) or await self.bot.fetch_user(uid) diff --git a/core/thread.py b/core/thread.py index 6bc7adc6cb..5bb5ad577b 100644 --- a/core/thread.py +++ b/core/thread.py @@ -17,9 +17,9 @@ from core.utils import ( is_image_url, days, + parse_channel_topic, match_title, match_user_id, - match_other_recipients, truncate, get_top_hoisted_role, create_thread_channel, @@ -119,9 +119,8 @@ def cancelled(self, flag: bool): @classmethod async def from_channel(cls, manager: "ThreadManager", channel: discord.TextChannel) -> "Thread": - recipient_id = match_user_id( - channel.topic - ) # there is a chance it grabs from another recipient's main thread + # there is a chance it grabs from another recipient's main thread + _, recipient_id, other_ids = parse_channel_topic(channel.topic) if recipient_id in manager.cache: thread = manager.cache[recipient_id] @@ -129,7 +128,7 @@ async def from_channel(cls, manager: "ThreadManager", channel: discord.TextChann recipient = manager.bot.get_user(recipient_id) or await manager.bot.fetch_user(recipient_id) other_recipients = [] - for uid in match_other_recipients(channel.topic): + for uid in other_ids: try: other_recipient = manager.bot.get_user(uid) or await manager.bot.fetch_user(uid) except discord.NotFound: @@ -1162,23 +1161,31 @@ async def _update_users_genesis(self): await genesis_message.edit(embed=embed) async def add_users(self, users: typing.List[typing.Union[discord.Member, discord.User]]) -> None: - title = match_title(self.channel.topic) - user_id = match_user_id(self.channel.topic) + title, user_id, _ = parse_channel_topic(self.channel.topic) + if title is not None: + title = f"Title: {title}\n" + else: + title = "" + self._other_recipients += users ids = ",".join(str(i.id) for i in self._other_recipients) - await self.channel.edit(topic=f"Title: {title}\nUser ID: {user_id}\nOther Recipients: {ids}") + await self.channel.edit(topic=f"{title}User ID: {user_id}\nOther Recipients: {ids}") await self._update_users_genesis() async def remove_users(self, users: typing.List[typing.Union[discord.Member, discord.User]]) -> None: - title = match_title(self.channel.topic) - user_id = match_user_id(self.channel.topic) + title, user_id, _ = parse_channel_topic(self.channel.topic) + if title is not None: + title = f"Title: {title}\n" + else: + title = "" + for u in users: self._other_recipients.remove(u) ids = ",".join(str(i.id) for i in self._other_recipients) - await self.channel.edit(topic=f"Title: {title}\nUser ID: {user_id}\nOther Recipients: {ids}") + await self.channel.edit(topic=f"{title}User ID: {user_id}\nOther Recipients: {ids}") await self._update_users_genesis() @@ -1240,16 +1247,24 @@ async def find( await thread.close(closer=self.bot.user, silent=True, delete_channel=False) thread = None else: + + def check(topic): + _, user_id, other_ids = parse_channel_topic(topic) + return recipient_id == user_id or recipient_id in other_ids + channel = discord.utils.find( - lambda x: str(recipient_id) in x.topic if x.topic else False, + lambda x: (check(x.topic)) if x.topic else False, self.bot.modmail_guild.text_channels, ) if channel: thread = await Thread.from_channel(self, channel) if thread.recipient: - # only save if data is valid - self.cache[recipient_id] = thread + # only save if data is valid. + # also the recipient_id here could belong to other recipient, + # it would be wrong if we set it as the dict key, + # so we use the thread id instead + self.cache[thread.id] = thread thread.ready = True if thread and recipient_id not in [x.id for x in thread.recipients]: @@ -1265,10 +1280,11 @@ async def _find_from_channel(self, channel): searching channel history for genesis embed and extracts user_id from that. """ - user_id = -1 - if channel.topic: - user_id = match_user_id(channel.topic) + if not channel.topic: + return None + + _, user_id, other_ids = parse_channel_topic(channel.topic) if user_id == -1: return None @@ -1282,7 +1298,7 @@ async def _find_from_channel(self, channel): recipient = None other_recipients = [] - for uid in match_other_recipients(channel.topic): + for uid in other_ids: try: other_recipient = self.bot.get_user(uid) or await self.bot.fetch_user(uid) except discord.NotFound: diff --git a/core/utils.py b/core/utils.py index 0fa74e457a..c87635b861 100644 --- a/core/utils.py +++ b/core/utils.py @@ -20,9 +20,11 @@ "human_join", "days", "cleanup_code", + "parse_channel_topic", "match_title", "match_user_id", "match_other_recipients", + "create_thread_channel", "create_not_found_embed", "parse_alias", "normalize_alias", @@ -218,9 +220,45 @@ def cleanup_code(content: str) -> str: return content.strip("` \n") -TOPIC_OTHER_RECIPIENTS_REGEX = re.compile(r"Other Recipients:\s*((?:\d{17,21},*)+)", flags=re.IGNORECASE) -TOPIC_TITLE_REGEX = re.compile(r"\bTitle: (.*)\n(?:User ID: )\b", flags=re.IGNORECASE | re.DOTALL) -TOPIC_UID_REGEX = re.compile(r"\bUser ID:\s*(\d{17,21})\b", flags=re.IGNORECASE) +TOPIC_REGEX = re.compile( + r"\b(Title: (?P.*)\n)?" + r"\bUser ID:\s*(?P<user_id>\d{17,21})\b" + r"(\nOther Recipients:\s*(?P<other_ids>(\d{17,21},?)+))?", + flags=re.IGNORECASE | re.DOTALL, +) +UID_REGEX = re.compile(r"\bUser ID:\s*(\d{17,21})\b", flags=re.IGNORECASE) + + +def parse_channel_topic(text: str) -> typing.Tuple[typing.Optional[str], int, typing.List[int]]: + """ + A helper to parse channel topics and respectivefully returns all the required values + at once. + + Parameters + ---------- + text : str + The text of channel topic. + + Returns + ------- + Tuple[Optional[str], int, List[int]] + A tuple of title, user ID, and other recipients IDs. + """ + title, user_id, other_ids = None, -1, [] + match = TOPIC_REGEX.search(text) + if match is not None: + groupdict = match.groupdict() + title = groupdict["title"] + + # user ID string is the required one in regex, so if match is found + # the value of this won't be None + user_id = int(groupdict["user_id"]) + + oth_ids = groupdict["other_ids"] + if oth_ids: + other_ids = list(map(int, oth_ids.split(","))) + + return title, user_id, other_ids def match_title(text: str) -> str: @@ -237,12 +275,10 @@ def match_title(text: str) -> str: Optional[str] The title if found. """ - match = TOPIC_TITLE_REGEX.search(text) - if match is not None: - return match.group(1) + return parse_channel_topic(text)[0] -def match_user_id(text: str) -> int: +def match_user_id(text: str, any_string: bool = False) -> int: """ Matches a user ID in the format of "User ID: 12345". @@ -250,16 +286,24 @@ def match_user_id(text: str) -> int: ---------- text : str The text of the user ID. + any_string: bool + Whether to search any string that matches the UID_REGEX, e.g. not from channel topic. + Defaults to False. Returns ------- int The user ID if found. Otherwise, -1. """ - match = TOPIC_UID_REGEX.search(text) - if match is not None: - return int(match.group(1)) - return -1 + user_id = -1 + if any_string: + match = UID_REGEX.search(text) + if match is not None: + user_id = int(match.group(1)) + else: + user_id = parse_channel_topic(text)[1] + + return user_id def match_other_recipients(text: str) -> typing.List[int]: @@ -276,10 +320,7 @@ def match_other_recipients(text: str) -> typing.List[int]: List[int] The list of other recipients IDs. """ - match = TOPIC_OTHER_RECIPIENTS_REGEX.search(text) - if match is not None: - return list(map(int, match.group(1).split(","))) - return [] + return parse_channel_topic(text)[2] def create_not_found_embed(word, possibilities, name, n=2, cutoff=0.6) -> discord.Embed: From 219ef56e512273561497998b0f61c2959a789e38 Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Mon, 11 Oct 2021 07:09:39 +0800 Subject: [PATCH 016/225] Only add title and other recipients strings in channel topic if any. --- core/thread.py | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/core/thread.py b/core/thread.py index 5bb5ad577b..2a2a243ba1 100644 --- a/core/thread.py +++ b/core/thread.py @@ -1135,10 +1135,16 @@ def get_notifications(self) -> str: return " ".join(set(mentions)) async def set_title(self, title: str) -> None: + topic = f"Title: {title}\n" + user_id = match_user_id(self.channel.topic) - ids = ",".join(i.id for i in self._other_recipients) + topic += f"User ID: {user_id}" + + if self._other_recipients: + ids = ",".join(str(i.id) for i in self._other_recipients) + topic += f"\nOther Recipients: {ids}" - await self.channel.edit(topic=f"Title: {title}\nUser ID: {user_id}\nOther Recipients: {ids}") + await self.channel.edit(topic=topic) async def _update_users_genesis(self): genesis_message = await self.get_genesis_message() @@ -1161,32 +1167,37 @@ async def _update_users_genesis(self): await genesis_message.edit(embed=embed) async def add_users(self, users: typing.List[typing.Union[discord.Member, discord.User]]) -> None: + topic = "" title, user_id, _ = parse_channel_topic(self.channel.topic) if title is not None: - title = f"Title: {title}\n" - else: - title = "" + topic += f"Title: {title}\n" - self._other_recipients += users + topic += f"User ID: {user_id}" + self._other_recipients += users ids = ",".join(str(i.id) for i in self._other_recipients) - await self.channel.edit(topic=f"{title}User ID: {user_id}\nOther Recipients: {ids}") + topic += f"\nOther Recipients: {ids}" + + await self.channel.edit(topic=topic) await self._update_users_genesis() async def remove_users(self, users: typing.List[typing.Union[discord.Member, discord.User]]) -> None: + topic = "" title, user_id, _ = parse_channel_topic(self.channel.topic) if title is not None: - title = f"Title: {title}\n" - else: - title = "" + topic += f"Title: {title}\n" + + topic += f"User ID: {user_id}" for u in users: self._other_recipients.remove(u) - ids = ",".join(str(i.id) for i in self._other_recipients) - await self.channel.edit(topic=f"{title}User ID: {user_id}\nOther Recipients: {ids}") + if self._other_recipients: + ids = ",".join(str(i.id) for i in self._other_recipients) + topic += f"\nOther Recipients: {ids}" + await self.channel.edit(topic=topic) await self._update_users_genesis() From 7be70c0150ad94881335623ff58eb20025a9dfed Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Tue, 2 Nov 2021 07:56:59 +0800 Subject: [PATCH 017/225] Fix regex to offer a bit more flexibility. Suggested by @Taaku18 --- core/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/utils.py b/core/utils.py index c87635b861..9f99333cca 100644 --- a/core/utils.py +++ b/core/utils.py @@ -221,9 +221,9 @@ def cleanup_code(content: str) -> str: TOPIC_REGEX = re.compile( - r"\b(Title: (?P<title>.*)\n)?" + r"(?:\bTitle:\s*(?P<title>.*)\n)?" r"\bUser ID:\s*(?P<user_id>\d{17,21})\b" - r"(\nOther Recipients:\s*(?P<other_ids>(\d{17,21},?)+))?", + r"(?:\nOther Recipients:\s*(?P<other_ids>\d{17,21}(?:(?:\s*,\s*)\d{17,21})*)\b)?", flags=re.IGNORECASE | re.DOTALL, ) UID_REGEX = re.compile(r"\bUser ID:\s*(\d{17,21})\b", flags=re.IGNORECASE) From 08b27ce731d5ac4f80a0557e836ba6d75cf9e983 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Fri, 19 Nov 2021 16:53:57 +0800 Subject: [PATCH 018/225] Fix typos #3116 --- bot.py | 1 + core/thread.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 86ef132b40..b47a694042 100644 --- a/bot.py +++ b/bot.py @@ -1694,6 +1694,7 @@ def main(): ) sys.exit(0) + # Set up discord.py internal logging if os.environ.get("LOG_DISCORD"): logger.debug(f"Discord logging enabled: {os.environ['LOG_DISCORD'].upper()}") d_logger = logging.getLogger("discord") diff --git a/core/thread.py b/core/thread.py index 6bc7adc6cb..3b4a1ef224 100644 --- a/core/thread.py +++ b/core/thread.py @@ -321,7 +321,7 @@ def _format_info_embed(self, user, log_url, log_count, color): created = str((time - user.created_at).days) user_info = [] if self.bot.config["thread_show_account_age"]: - user_info.append(f"was created {days(created)}") + user_info.append(f" was created {days(created)}") embed = discord.Embed(color=color, description=user.mention, timestamp=time) From b15a77b502a6ec13637fc2ec4da1b3cf6eedd96b Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Fri, 19 Nov 2021 17:08:38 +0800 Subject: [PATCH 019/225] Update changelog for PR-based changes --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85fc813322..8f5fd59670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html); however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. +# v3.11.0 + +### Added + +- `use_hoisted_top_role` config to use change how default mod tags work, see `v3.10.0#Added` for details. ([PR #3093](https://github.com/kyb3r/modmail/pull/3093)) + +### Fixed + +- Several minor typos. ([PR #3095](https://github.com/kyb3r/modmail/pull/3095), [PR #3116](https://github.com/kyb3r/modmail/pull/3116)) +- Certain cases where fallback categories were not working as intended. ([PR #3109](https://github.com/kyb3r/modmail/pull/3109)) +- `?contact` would create in a random category in silent mode. ([GH #3091](https://github.com/kyb3r/modmail/issues/3091), [PR #3092](https://github.com/kyb3r/modmail/pull/3092)) +- Certain cases where `?close` would fail if closer isn't in cache. ([GH #3104](https://github.com/kyb3r/modmail/issues/3104), [PR #3105](https://github.com/kyb3r/modmail/pull/3105)) + +### Internal + +- Improve regex parsing of channel topics. ([PR #3111](https://github.com/kyb3r/modmail/pull/3111)) + # v3.10.3 ### Improved From 25ebb56605c576a0203875b62198f29f77be1d93 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sat, 20 Nov 2021 02:42:37 +0800 Subject: [PATCH 020/225] Update version --- README.md | 2 +- bot.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9730cd1339..75a3652454 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ <br> <a href="#"> - <img src="https://img.shields.io/badge/Latest%20Version-v3.10.3-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> + <img src="https://img.shields.io/badge/Latest%20Version-v3.11.0-dev1-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> </a> <br> diff --git a/bot.py b/bot.py index a0de88f8f7..432e6fdd11 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "3.10.3" +__version__ = "3.11.0-dev1" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 341e506413..797650d754 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '3.10.3' +version = '3.11.0-dev1' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From f46d077ca7330d0c11ce537fcf17a8ce6e2d4d2a Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 00:55:09 +0800 Subject: [PATCH 021/225] [BREAKING] Update discord.py to v2-master --- CHANGELOG.md | 6 + Pipfile | 2 +- Pipfile.lock | 733 ++++++++++++++++++++++++++-------------------- README.md | 6 +- bot.py | 96 +++--- cogs/modmail.py | 50 ++-- cogs/plugins.py | 2 +- cogs/utility.py | 29 +- core/changelog.py | 4 +- core/clients.py | 16 +- core/paginator.py | 16 +- core/thread.py | 34 +-- core/time.py | 10 +- core/utils.py | 6 +- requirements.txt | 18 +- 15 files changed, 570 insertions(+), 458 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f5fd59670..fe9ec8e3e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ however, insignificant breaking changes do not guarantee a major version bump, s # v3.11.0 +### Breaking + +- Upgraded to discord.py v2.0 master ([internal changes](https://gist.github.com/apple502j/f75b4f24652f04de85c7084ffd73ec58)). +- Python 3.8 or higher is required. + ### Added - `use_hoisted_top_role` config to use change how default mod tags work, see `v3.10.0#Added` for details. ([PR #3093](https://github.com/kyb3r/modmail/pull/3093)) @@ -22,6 +27,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Internal - Improve regex parsing of channel topics. ([PR #3111](https://github.com/kyb3r/modmail/pull/3111)) +- Add warning if deploying on a developmental version. # v3.10.3 diff --git a/Pipfile b/Pipfile index 4ed01f5b70..51569d26e5 100644 --- a/Pipfile +++ b/Pipfile @@ -11,7 +11,7 @@ pylint = "~=2.9.3" [packages] aiohttp = "==3.7.4.post0" colorama = "~=0.4.4" # Doesn't officially support Python 3.9 yet, v0.4.5 will support 3.9 -"discord.py" = "==1.7.3" +"discord.py" = {ref = "45d498c1b76deaf3b394d17ccf56112fa691d160", git = "https://github.com/Rapptz/discord.py.git"} emoji = "~=1.2.0" isodate = "~=0.6.0" motor = "~=2.4.0" diff --git a/Pipfile.lock b/Pipfile.lock index a9f820119e..e1a77d86b5 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "0e726213f83b90d7c4e90a04cea6636dbdc5be2ad82049c96820535e5cc3d1ad" + "sha256": "aaa53487befe4f19feda64131fbc5bde140c1ec1a59ff2656d2ad1da2c50b390" }, "pipfile-spec": 6, "requires": { @@ -91,21 +91,21 @@ "index": "pypi", "version": "==0.4.4" }, + "discord-py": { + "git": "https://github.com/Rapptz/discord.py.git", + "ref": "45d498c1b76deaf3b394d17ccf56112fa691d160" + }, "discord.py": { - "hashes": [ - "sha256:462cd0fe307aef8b29cbfa8dd613e548ae4b2cb581d46da9ac0d46fb6ea19408", - "sha256:c6f64db136de0e18e090f6752ea68bdd4ab0a61b82dfe7acecefa22d6477bb0c" - ], - "index": "pypi", - "version": "==1.7.3" + "git": "https://github.com/Rapptz/discord.py.git", + "ref": "45d498c1b76deaf3b394d17ccf56112fa691d160" }, "dnspython": { "hashes": [ - "sha256:36c5e8e38d4369a08b6780b7f27d790a292b2b08eea01607865bf0936c558e01", - "sha256:f69c21288a962f4da86e56c4905b49d11aba7938d3d740e80d9e366ee4f1632d" + "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216", + "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.16.0" + "version": "==2.1.0" }, "emoji": { "hashes": [ @@ -117,11 +117,11 @@ }, "idna": { "hashes": [ - "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a", - "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3" + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], "markers": "python_version >= '3.5'", - "version": "==3.2" + "version": "==3.3" }, "isodate": { "hashes": [ @@ -141,46 +141,81 @@ }, "multidict": { "hashes": [ - "sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a", - "sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93", - "sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632", - "sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656", - "sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79", - "sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7", - "sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d", - "sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5", - "sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224", - "sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26", - "sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea", - "sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348", - "sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6", - "sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76", - "sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1", - "sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f", - "sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952", - "sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a", - "sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37", - "sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9", - "sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359", - "sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8", - "sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da", - "sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3", - "sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d", - "sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf", - "sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841", - "sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d", - "sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93", - "sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f", - "sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647", - "sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635", - "sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456", - "sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda", - "sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5", - "sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281", - "sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80" + "sha256:06560fbdcf22c9387100979e65b26fba0816c162b888cb65b845d3def7a54c9b", + "sha256:067150fad08e6f2dd91a650c7a49ba65085303fcc3decbd64a57dc13a2733031", + "sha256:0a2cbcfbea6dc776782a444db819c8b78afe4db597211298dd8b2222f73e9cd0", + "sha256:0dd1c93edb444b33ba2274b66f63def8a327d607c6c790772f448a53b6ea59ce", + "sha256:0fed465af2e0eb6357ba95795d003ac0bdb546305cc2366b1fc8f0ad67cc3fda", + "sha256:116347c63ba049c1ea56e157fa8aa6edaf5e92925c9b64f3da7769bdfa012858", + "sha256:1b4ac3ba7a97b35a5ccf34f41b5a8642a01d1e55454b699e5e8e7a99b5a3acf5", + "sha256:1c7976cd1c157fa7ba5456ae5d31ccdf1479680dc9b8d8aa28afabc370df42b8", + "sha256:246145bff76cc4b19310f0ad28bd0769b940c2a49fc601b86bfd150cbd72bb22", + "sha256:25cbd39a9029b409167aa0a20d8a17f502d43f2efebfe9e3ac019fe6796c59ac", + "sha256:28e6d883acd8674887d7edc896b91751dc2d8e87fbdca8359591a13872799e4e", + "sha256:2d1d55cdf706ddc62822d394d1df53573d32a7a07d4f099470d3cb9323b721b6", + "sha256:2e77282fd1d677c313ffcaddfec236bf23f273c4fba7cdf198108f5940ae10f5", + "sha256:32fdba7333eb2351fee2596b756d730d62b5827d5e1ab2f84e6cbb287cc67fe0", + "sha256:35591729668a303a02b06e8dba0eb8140c4a1bfd4c4b3209a436a02a5ac1de11", + "sha256:380b868f55f63d048a25931a1632818f90e4be71d2081c2338fcf656d299949a", + "sha256:3822c5894c72e3b35aae9909bef66ec83e44522faf767c0ad39e0e2de11d3b55", + "sha256:38ba256ee9b310da6a1a0f013ef4e422fca30a685bcbec86a969bd520504e341", + "sha256:3bc3b1621b979621cee9f7b09f024ec76ec03cc365e638126a056317470bde1b", + "sha256:3d2d7d1fff8e09d99354c04c3fd5b560fb04639fd45926b34e27cfdec678a704", + "sha256:517d75522b7b18a3385726b54a081afd425d4f41144a5399e5abd97ccafdf36b", + "sha256:5f79c19c6420962eb17c7e48878a03053b7ccd7b69f389d5831c0a4a7f1ac0a1", + "sha256:5f841c4f14331fd1e36cbf3336ed7be2cb2a8f110ce40ea253e5573387db7621", + "sha256:637c1896497ff19e1ee27c1c2c2ddaa9f2d134bbb5e0c52254361ea20486418d", + "sha256:6ee908c070020d682e9b42c8f621e8bb10c767d04416e2ebe44e37d0f44d9ad5", + "sha256:77f0fb7200cc7dedda7a60912f2059086e29ff67cefbc58d2506638c1a9132d7", + "sha256:7878b61c867fb2df7a95e44b316f88d5a3742390c99dfba6c557a21b30180cac", + "sha256:78c106b2b506b4d895ddc801ff509f941119394b89c9115580014127414e6c2d", + "sha256:8b911d74acdc1fe2941e59b4f1a278a330e9c34c6c8ca1ee21264c51ec9b67ef", + "sha256:93de39267c4c676c9ebb2057e98a8138bade0d806aad4d864322eee0803140a0", + "sha256:9416cf11bcd73c861267e88aea71e9fcc35302b3943e45e1dbb4317f91a4b34f", + "sha256:94b117e27efd8e08b4046c57461d5a114d26b40824995a2eb58372b94f9fca02", + "sha256:9815765f9dcda04921ba467957be543423e5ec6a1136135d84f2ae092c50d87b", + "sha256:98ec9aea6223adf46999f22e2c0ab6cf33f5914be604a404f658386a8f1fba37", + "sha256:a37e9a68349f6abe24130846e2f1d2e38f7ddab30b81b754e5a1fde32f782b23", + "sha256:a43616aec0f0d53c411582c451f5d3e1123a68cc7b3475d6f7d97a626f8ff90d", + "sha256:a4771d0d0ac9d9fe9e24e33bed482a13dfc1256d008d101485fe460359476065", + "sha256:a5635bcf1b75f0f6ef3c8a1ad07b500104a971e38d3683167b9454cb6465ac86", + "sha256:a9acb76d5f3dd9421874923da2ed1e76041cb51b9337fd7f507edde1d86535d6", + "sha256:ac42181292099d91217a82e3fa3ce0e0ddf3a74fd891b7c2b347a7f5aa0edded", + "sha256:b227345e4186809d31f22087d0265655114af7cda442ecaf72246275865bebe4", + "sha256:b61f85101ef08cbbc37846ac0e43f027f7844f3fade9b7f6dd087178caedeee7", + "sha256:b70913cbf2e14275013be98a06ef4b412329fe7b4f83d64eb70dce8269ed1e1a", + "sha256:b9aad49466b8d828b96b9e3630006234879c8d3e2b0a9d99219b3121bc5cdb17", + "sha256:baf1856fab8212bf35230c019cde7c641887e3fc08cadd39d32a421a30151ea3", + "sha256:bd6c9c50bf2ad3f0448edaa1a3b55b2e6866ef8feca5d8dbec10ec7c94371d21", + "sha256:c1ff762e2ee126e6f1258650ac641e2b8e1f3d927a925aafcfde943b77a36d24", + "sha256:c30ac9f562106cd9e8071c23949a067b10211917fdcb75b4718cf5775356a940", + "sha256:c9631c642e08b9fff1c6255487e62971d8b8e821808ddd013d8ac058087591ac", + "sha256:cdd68778f96216596218b4e8882944d24a634d984ee1a5a049b300377878fa7c", + "sha256:ce8cacda0b679ebc25624d5de66c705bc53dcc7c6f02a7fb0f3ca5e227d80422", + "sha256:cfde464ca4af42a629648c0b0d79b8f295cf5b695412451716531d6916461628", + "sha256:d3def943bfd5f1c47d51fd324df1e806d8da1f8e105cc7f1c76a1daf0f7e17b0", + "sha256:d9b668c065968c5979fe6b6fa6760bb6ab9aeb94b75b73c0a9c1acf6393ac3bf", + "sha256:da7d57ea65744d249427793c042094c4016789eb2562576fb831870f9c878d9e", + "sha256:dc3a866cf6c13d59a01878cd806f219340f3e82eed514485e094321f24900677", + "sha256:df23c83398715b26ab09574217ca21e14694917a0c857e356fd39e1c64f8283f", + "sha256:dfc924a7e946dd3c6360e50e8f750d51e3ef5395c95dc054bc9eab0f70df4f9c", + "sha256:e4a67f1080123de76e4e97a18d10350df6a7182e243312426d508712e99988d4", + "sha256:e5283c0a00f48e8cafcecadebfa0ed1dac8b39e295c7248c44c665c16dc1138b", + "sha256:e58a9b5cc96e014ddf93c2227cbdeca94b56a7eb77300205d6e4001805391747", + "sha256:e6453f3cbeb78440747096f239d282cc57a2997a16b5197c9bc839099e1633d0", + "sha256:e6c4fa1ec16e01e292315ba76eb1d012c025b99d22896bd14a66628b245e3e01", + "sha256:e7d81ce5744757d2f05fc41896e3b2ae0458464b14b5a2c1e87a6a9d69aefaa8", + "sha256:ea21d4d5104b4f840b91d9dc8cbc832aba9612121eaba503e54eaab1ad140eb9", + "sha256:ecc99bce8ee42dcad15848c7885197d26841cb24fa2ee6e89d23b8993c871c64", + "sha256:f0bb0973f42ffcb5e3537548e0767079420aefd94ba990b61cf7bb8d47f4916d", + "sha256:f19001e790013ed580abfde2a4465388950728861b52f0da73e8e8a9418533c0", + "sha256:f76440e480c3b2ca7f843ff8a48dc82446b86ed4930552d736c0bac507498a52", + "sha256:f9bef5cff994ca3026fcc90680e326d1a19df9841c5e3d224076407cc21471a1", + "sha256:fc66d4016f6e50ed36fb39cd287a3878ffcebfa90008535c62e0e90a7ab713ae", + "sha256:fd77c8f3cba815aa69cb97ee2b2ef385c7c12ada9c734b0f3b32e26bb88bbf1d" ], "markers": "python_version >= '3.6'", - "version": "==5.1.0" + "version": "==5.2.0" }, "natural": { "hashes": [ @@ -202,107 +237,116 @@ "srv" ], "hashes": [ - "sha256:02dc0b0f48ed3cd06c13b7e31b066bf91e00dac5f8147b0a0a45f9009bfab857", - "sha256:053b4ebf91c7395d1fcd2ce6a9edff0024575b7b2de6781554a4114448a8adc9", - "sha256:070a4ef689c9438a999ec3830e69b208ff0d12251846e064d947f97d819d1d05", - "sha256:072ba7cb65c8aa4d5c5659bf6722ee85781c9d7816dc00679b8b6f3dff1ddafc", - "sha256:0b6055e0ef451ff73c93d0348d122a0750dddf323b9361de5835dac2f6cf7fc1", - "sha256:11f9e0cfc84ade088a38df2708d0b958bb76360181df1b2e1e1a41beaa57952b", - "sha256:18290649759f9db660972442aa606f845c368db9b08c4c73770f6da14113569b", - "sha256:186104a94d39b8412f8e3de385acd990a628346a4402d4f3a288a82b8660bd22", - "sha256:1970cfe2aec1bf74b40cf30c130ad10cd968941694630386db33e1d044c22a2e", - "sha256:19d4bd0fc29aa405bb1781456c9cfff9fceabb68543741eb17234952dbc2bbb0", - "sha256:1bab889ae7640eba739f67fcbf8eff252dddc60d4495e6ddd3a87cd9a95fdb52", - "sha256:1bc6fe7279ff40c6818db002bf5284aa03ec181ea1b1ceaeee33c289d412afa7", - "sha256:208debdcf76ed39ebf24f38509f50dc1c100e31e8653817fedb8e1f867850a13", - "sha256:2399a85b54f68008e483b2871f4a458b4c980469c7fe921595ede073e4844f1e", - "sha256:246ec420e4c8744fceb4e259f906211b9c198e1f345e6158dcd7cbad3737e11e", - "sha256:24f8aeec4d6b894a6128844e50ff423dd02462ee83addf503c598ee3a80ddf3d", - "sha256:255a35bf29185f44b412e31a927d9dcedda7c2c380127ecc4fbf2f61b72fa978", - "sha256:2dbfbbded947a83a3dffc2bd1ec4750c17e40904692186e2c55a3ad314ca0222", - "sha256:2e92aa32300a0b5e4175caec7769f482b292769807024a86d674b3f19b8e3755", - "sha256:316c1b8723afa9870567cd6dff35d440b2afeda53aa13da6c5ab85f98ed6f5ca", - "sha256:333bfad77aa9cd11711febfb75eed0bb537a1d022e1c252714dad38993590240", - "sha256:39dafa2eaf577d1969f289dc9a44501859a1897eb45bd589e93ce843fc610800", - "sha256:3ce83f17f641a62a4dfb0ba1b8a3c1ced7c842f511b5450d90c030c7828e3693", - "sha256:46d5ec90276f71af3a29917b30f2aec2315a2759b5f8d45b3b63a07ca8a070a3", - "sha256:48d5bc80ab0af6b60c4163c5617f5cd23f2f880d7600940870ea5055816af024", - "sha256:4ba0def4abef058c0e5101e05e3d5266e6fffb9795bbf8be0fe912a7361a0209", - "sha256:5af390fa9faf56c93252dab09ea57cd020c9123aa921b63a0ed51832fdb492e7", - "sha256:5e574664f1468872cd40f74e4811e22b1aa4de9399d6bcfdf1ee6ea94c017fcf", - "sha256:625befa3bc9b40746a749115cc6a15bf20b9bd7597ca55d646205b479a2c99c7", - "sha256:6261bee7c5abadeac7497f8f1c43e521da78dd13b0a2439f526a7b0fc3788824", - "sha256:657ad80de8ec9ed656f28844efc801a0802961e8c6a85038d97ff6f555ef4919", - "sha256:6b89dc51206e4971c5568c797991eaaef5dc2a6118d67165858ad11752dba055", - "sha256:6e66780f14c2efaf989cd3ac613b03ee6a8e3a0ba7b96c0bb14adca71a427e55", - "sha256:6fb3f85870ae26896bb44e67db94045f2ebf00c5d41e6b66cdcbb5afd644fc18", - "sha256:701e08457183da70ed96b35a6b43e6ba1df0b47c837b063cde39a1fbe1aeda81", - "sha256:70761fd3c576b027eec882b43ee0a8e5b22ff9c20cdf4d0400e104bc29e53e34", - "sha256:73b400fdc22de84bae0dbf1a22613928a41612ec0a3d6ed47caf7ad4d3d0f2ff", - "sha256:7412a36798966624dc4c57d64aa43c2d1100b348abd98daaac8e99e57d87e1d7", - "sha256:78ecb8d42f50d393af912bfb1fb1dcc9aabe9967973efb49ee577e8f1cea494c", - "sha256:7c6a9948916a7bbcc6d3a9f6fb75db1acb5546078023bfb3db6efabcd5a67527", - "sha256:7c72d08acdf573455b2b9d2b75b8237654841d63a48bc2327dc102c6ee89b75a", - "sha256:7d98ce3c42921bb91566121b658e0d9d59a9082a9bd6f473190607ff25ab637f", - "sha256:845a8b83798b2fb11b09928413cb32692866bfbc28830a433d9fa4c8c3720dd0", - "sha256:94d38eba4d1b5eb3e6bfece0651b855a35c44f32fd91f512ab4ba41b8c0d3e66", - "sha256:9a13661681d17e43009bb3e85e837aa1ec5feeea1e3654682a01b8821940f8b3", - "sha256:a0e5dff6701fa615f165306e642709e1c1550d5b237c5a7a6ea299886828bd50", - "sha256:a2239556ff7241584ce57be1facf25081669bb457a9e5cbe68cce4aae6567aa1", - "sha256:a325600c83e61e3c9cebc0c2b1c8c4140fa887f789085075e8f44c8ff2547eb9", - "sha256:a3566acfbcde46911c52810374ecc0354fdb841284a3efef6ff7105bc007e9a8", - "sha256:a634a4730ce0b0934ed75e45beba730968e12b4dafbb22f69b3b2f616d9e644e", - "sha256:a6d055f01b83b1a4df8bb0c61983d3bdffa913764488910af3620e5c2450bf83", - "sha256:a752ecd1a26000a6d67be7c9a2e93801994a8b3f866ac95b672fbc00225ca91a", - "sha256:a9ba2a63777027b06b116e1ea8248e66fd1bedc2c644f93124b81a91ddbf6d88", - "sha256:aaa038eafb7186a4abbb311fcf20724be9363645882bbce540bef4797e812a7a", - "sha256:af586e85144023686fb0af09c8cdf672484ea182f352e7ceead3d832de381e1b", - "sha256:b0a0cf39f589e52d801fdef418305562bc030cdf8929217463c8433c65fd5c2f", - "sha256:b1c4874331ab960429caca81acb9d2932170d66d6d6f87e65dc4507a85aca152", - "sha256:b3b5b3cbc3fdf4fcfa292529df2a85b5d9c7053913a739d3069af1e12e12219f", - "sha256:b542d56ed1b8d5cf3bb36326f814bd2fbe8812dfd2582b80a15689ea433c0e35", - "sha256:b6ea08758b6673610b3c5bdf47189286cf9c58b1077558706a2f6f8744922527", - "sha256:b754240daafecd9d5fce426b0fbaaed03f4ebb130745c8a4ae9231fffb8d75e5", - "sha256:b772bab31cbd9cb911e41e1a611ebc9497f9a32a7348e2747c38210f75c00f41", - "sha256:b88d1742159bc93a078733f9789f563cef26f5e370eba810476a71aa98e5fbc2", - "sha256:b8bf42d3b32f586f4c9e37541769993783a534ad35531ce8a4379f6fa664fba9", - "sha256:bc9ac81e73573516070d24ce15da91281922811f385645df32bd3c8a45ab4684", - "sha256:c188db6cf9e14dbbb42f5254292be96f05374a35e7dfa087cc2140f0ff4f10f6", - "sha256:c55782a55f4a013a78ac5b6ee4b8731a192dea7ab09f1b6b3044c96d5128edd4", - "sha256:c5cab230e7cabdae9ff23c12271231283efefb944c1b79bed79a91beb65ba547", - "sha256:cbf8672edeb7b7128c4a939274801f0e32bbf5159987815e3d1eace625264a46", - "sha256:cc2894fe91f31a513860238ede69fe47fada21f9e7ddfe73f7f9fef93a971e41", - "sha256:cda9e628b1315beec8341e8c04aac9a0b910650b05e0751e42e399d5694aeacb", - "sha256:ceae3ab9e11a27aaab42878f1d203600dfd24f0e43678b47298219a0f10c0d30", - "sha256:ced944dcdd561476deef7cb7bfd4987c69fffbfeff6d02ca4d5d4fd592d559b7", - "sha256:d04ca462cb99077e6c059e97c072957caf2918e6e4191e3161c01c439e0193de", - "sha256:d1131562ddc2ea8a446f66c2648d7dabec2b3816fc818528eb978a75a6d23b2e", - "sha256:d1740776b70367277323fafb76bcf09753a5cc9824f5d705bac22a34ff3668ea", - "sha256:d6e11ffd43184d529d6752d6dcb62b994f903038a17ea2168ef1910c96324d26", - "sha256:d73e10772152605f6648ba4410318594f1043bbfe36d2fadee7c4b8912eff7c5", - "sha256:da8288bc4a7807c6715416deed1c57d94d5e03e93537889e002bf985be503f1a", - "sha256:db93608a246da44d728842b8fa9e45aa9782db76955f634a707739a8d53ff544", - "sha256:dcd3d0009fbb6e454d729f8b22d0063bd9171c31a55e0f0271119bd4f2700023", - "sha256:dd1f49f949a658c4e8f81ed73f9aad25fcc7d4f62f767f591e749e30038c4e1d", - "sha256:dd6ff2192f34bd622883c745a56f492b1c9ccd44e14953e8051c33024a2947d5", - "sha256:e018a4921657c2d3f89c720b7b90b9182e277178a04a7e9542cc79d7d787ca51", - "sha256:e2b7670c0c8c6b501464150dd49dd0d6be6cb7f049e064124911cec5514fa19e", - "sha256:e7a33322e08021c37e89cae8ff06327503e8a1719e97c69f32c31cbf6c30d72c", - "sha256:e8a82e35d52ad6f867e88096a1a2b9bdc7ec4d5e65c7b4976a248bf2d1a32a93", - "sha256:e9faf8d4712d5ea301d74abfcf6dafe4b7f4af7936e91f283b0ad7bf69ed3e3a", - "sha256:ec5ca7c0007ce268048bbe0ffc6846ed1616cf3d8628b136e81d5e64ff3f52a2", - "sha256:eee42a1cc06565f6b21caa1f504ec15e07de7ebfd520ab57f8cb3308bc118e22", - "sha256:f2acf9bbcd514e901f82c4ca6926bbd2ae61716728f110b4343eb0a69612d018", - "sha256:f55c1ddcc1f6050b07d468ce594f55dbf6107b459e16f735d26818d7be1e9538", - "sha256:f6977a520bd96e097c8a37a8cbb9faa1ea99d21bf84190195056e25f688af73d", - "sha256:f94c7d22fb36b184734dded7345a04ec5f95130421c775b8b0c65044ef073f34", - "sha256:fa8957e9a1b202cb45e6b839c241cd986c897be1e722b81d2f32e9c6aeee80b0", - "sha256:fd3854148005c808c485c754a184c71116372263709958b42aefbef2e5dd373a", - "sha256:fe5872ce6f9627deac8314bdffd3862624227c3de4c17ef0cc78bbf0402999eb", - "sha256:ffbae429ba9e42d0582d3ac63fdb410338892468a2107d8ff68228ec9a39a0ed" + "sha256:02e0c088f189ca69fac094cb5f851b43bbbd7cec42114495777d4d8f297f7f8a", + "sha256:138248c542051eb462f88b50b0267bd5286d6661064bab06faa0ef6ac30cdb4b", + "sha256:13a7c6d055af58a1e9c505e736da8b6a2e95ccc8cec10b008143f7a536e5de8a", + "sha256:13d74bf3435c1e58d8fafccc0d5e87f246ae2c6e9cbef4b35e32a1c3759e354f", + "sha256:15dae01341571d0af51526b7a21648ca575e9375e16ba045c9860848dfa8952f", + "sha256:17238115e6d37f5423b046cb829f1ca02c4ea7edb163f5b8b88e0c975dc3fec9", + "sha256:180b405e17b90a877ea5dbc5efe7f4c171af4c89323148e100c0f12cedb86f12", + "sha256:1821ce4e5a293313947fd017bbd2d2535aa6309680fa29b33d0442d15da296ec", + "sha256:1a7b138a04fdd17849930dc8bf664002e17db38448850bfb96d200c9c5a8b3a1", + "sha256:1c4e51a3b69789b6f468a8e881a13f2d1e8f5e99e41f80fd44845e6ec0f701e1", + "sha256:1d55982e5335925c55e2b87467043866ce72bd30ea7e7e3eeed6ec3d95a806d4", + "sha256:1fa6f08ddb6975371777f97592d35c771e713ee2250e55618148a5e57e260aff", + "sha256:2174d3279b8e2b6d7613b338f684cd78ff7adf1e7ec5b7b7bde5609a129c9898", + "sha256:2462a68f6675da548e333fa299d8e9807e00f95a4d198cfe9194d7be69f40c9b", + "sha256:25fd76deabe9ea37c8360c362b32f702cc095a208dd1c5328189938ca7685847", + "sha256:287c2a0063267c1458c4ddf528b44063ce7f376a6436eea5bccd7f625bbc3b5e", + "sha256:2d3abe548a280b49269c7907d5b71199882510c484d680a5ea7860f30c4a695f", + "sha256:2fa101bb23619120673899694a65b094364269e597f551a87c4bdae3a474d726", + "sha256:2fda3b3fb5c0d159195ab834b322a23808f1b059bcc7e475765abeddee6a2529", + "sha256:303531649fa45f96b694054c1aa02f79bda32ef57affe42c5c339336717eed74", + "sha256:36806ee53a85c3ba73939652f2ced2961e6a77cfbae385cd83f2e24cd97964b7", + "sha256:37a63da5ee623acdf98e6d511171c8a5827a6106b0712c18af4441ef4f11e6be", + "sha256:3a2fcbd04273a509fa85285d9eccf17ab65ce440bd4f5e5a58c978e563cd9e9a", + "sha256:3b40e36d3036bfe69ba63ec8e746a390721f75467085a0384b528e1dda532c69", + "sha256:4168b6c425d783e81723fc3dc382d374a228ff29530436a472a36d9f27593e73", + "sha256:444c00ebc20f2f9dc62e34f7dc9453dc2f5f5a72419c8dccad6e26d546c35712", + "sha256:45d6b47d70ed44e3c40bef618ed61866c48176e7e5dff80d06d8b1a6192e8584", + "sha256:460bdaa3f65ddb5b7474ae08589a1763b5da1a78b8348351b9ba1c63b459d67d", + "sha256:47ed77f62c8417a86f9ad158b803f3459a636386cb9d3d4e9e7d6a82d051f907", + "sha256:48722e91981bb22a16b0431ea01da3e1cc5b96805634d3b8d3c2a5315c1ce7f1", + "sha256:49b0d92724d3fce1174fd30b0b428595072d5c6b14d6203e46a9ea347ae7b439", + "sha256:4a2d73a9281faefb273a5448f6d25f44ebd311ada9eb79b6801ae890508fe231", + "sha256:4f4bc64fe9cbd70d46f519f1e88c9e4677f7af18ab9cd4942abce2bcfa7549c3", + "sha256:5067c04d3b19c820faac6342854d887ade58e8d38c3db79b68c2a102bbb100e7", + "sha256:51437c77030bed72d57d8a61e22758e3c389b13fea7787c808030002bb05ca39", + "sha256:515e4708d6567901ffc06476a38abe2c9093733f52638235d9f149579c1d3de0", + "sha256:5183b698d6542219e4135de583b57bc6286bd37df7f645b688278eb919bfa785", + "sha256:56feb80ea1f5334ccab9bd16a5161571ab70392e51fcc752fb8a1dc67125f663", + "sha256:573e2387d0686976642142c50740dfc4d3494cc627e2a7d22782b99f70879055", + "sha256:58a67b3800476232f9989e533d0244060309451b436d46670a53e6d189f1a7e7", + "sha256:5e3833c001a04aa06a28c6fd9628256862a654c09b0f81c07734b5629bc014ab", + "sha256:5f5fe59328838fa28958cc06ecf94be585726b97d637012f168bc3c7abe4fd81", + "sha256:6235bf2157aa46e53568ed79b70603aa8874baa202d5d1de82fa0eb917696e73", + "sha256:63be03f7ae1e15e72a234637ec7941ef229c7ab252c9ff6af48bba1e5418961c", + "sha256:65f159c445761cab04b665fc448b3fc008aebc98e54fdcbfd1aff195ef1b1408", + "sha256:67e0b2ad3692f6d0335ae231a40de55ec395b6c2e971ad6f55b162244d1ec542", + "sha256:68409171ab2aa7ccd6e8e839233e4b8ddeec246383c9a3698614e814739356f9", + "sha256:6a96c04ce39d66df60d9ce89f4c254c4967bc7d9e2e2c52adc58f47be826ee96", + "sha256:6ead0126fb4424c6c6a4fdc603d699a9db7c03cdb8eac374c352a75fec8a820a", + "sha256:6eb6789f26c398c383225e1313c8e75a7d290d323b8eaf65f3f3ddd0eb8a5a3c", + "sha256:6f07888e3b73c0dfa46f12d098760494f5f23fd66923a6615edfe486e6a7649c", + "sha256:6f0f0a10f128ea0898e607d351ebfabf70941494fc94e87f12c76e2894d8e6c4", + "sha256:704879b6a54c45ad76cea7c6789c1ae7185050acea7afd15b58318fa1932ed45", + "sha256:7117bfd8827cfe550f65a3c399dcd6e02226197a91c6d11a3540c3e8efc686d6", + "sha256:712de1876608fd5d76abc3fc8ec55077278dd5044073fbe9492631c9a2c58351", + "sha256:75c7ef67b4b8ec070e7a4740764f6c03ec9246b59d95e2ae45c029d41cb9efa1", + "sha256:77dddf596fb065de29fb39992fbc81301f7fd0003be649b7fa7448c77ca53bed", + "sha256:7abc87e45b572eb6d17a50422e69a9e5d6f13e691e821fe2312df512500faa50", + "sha256:7d8cdd2f070c71366e64990653522cce84b08dc26ab0d1fa19aa8d14ee0cf9ba", + "sha256:81ce5f871f5d8e82615c8bd0b34b68a9650204c8b1a04ce7890d58c98eb66e39", + "sha256:837cdef094f39c6f4a2967abc646a412999c2540fbf5d3cce1dd3b671f4b876c", + "sha256:849e641cfed05c75d772f9e9018f42c5fbd00655d43d52da1b9c56346fd3e4cc", + "sha256:87114b995506e7584cf3daf891e419b5f6e7e383e7df6267494da3a76312aa22", + "sha256:87db421c9eb915b8d9a9a13c5b2ee338350e36ee83e26ff0adfc48abc5db3ac3", + "sha256:8851544168703fb519e95556e3b463fca4beeef7ed3f731d81a68c8268515d9d", + "sha256:891f541c7ed29b95799da0cd249ae1db1842777b564e8205a197b038c5df6135", + "sha256:8f87f53c9cd89010ae45490ec2c963ff18b31f5f290dc08b04151709589fe8d9", + "sha256:9641be893ccce7d192a0094efd0a0d9f1783a1ebf314b4128f8a27bfadb8a77c", + "sha256:979e34db4f3dc5710c18db437aaf282f691092b352e708cb2afd4df287698c76", + "sha256:9b62d84478f471fdb0dcea3876acff38f146bd23cbdbed15074fb4622064ec2e", + "sha256:a472ca3d43d33e596ff5836c6cc71c3e61be33f44fe1cfdab4a1100f4af60333", + "sha256:a5dbeeea6a375fbd79448b48a54c46fc9351611a03ef8398d2a40b684ce46194", + "sha256:a7430f3987d232e782304c109be1d0e6fff46ca6405cb2479e4d8d08cd29541e", + "sha256:a81e52dbf95f236a0c89a5abcd2b6e1331da0c0312f471c73fae76c79d2acf6b", + "sha256:aa434534cc91f51a85e3099dc257ee8034b3d2be77f2ca58fb335a686e3a681f", + "sha256:ab27d6d7d41a66d9e54269a290d27cd5c74f08e9add0054a754b4821026c4f42", + "sha256:adb37bf22d25a51b84d989a2a5c770d4514ac590201eea1cb50ce8c9c5257f1d", + "sha256:afb16330ab6efbbf995375ad94e970fa2f89bb46bd10d854b7047620fdb0d67d", + "sha256:b1b06038c9940a49c73db0aeb0f6809b308e198da1326171768cf68d843af521", + "sha256:b1e6d1cf4bd6552b5f519432cce1530c09e6b0aab98d44803b991f7e880bd332", + "sha256:bf2d9d62178bb5c05e77d40becf89c309b1966fbcfb5c306238f81bf1ec2d6a2", + "sha256:bfd073fea04061019a103a288847846b5ef40dfa2f73b940ed61e399ca95314f", + "sha256:c04e84ccf590933a266180286d8b6a5fc844078a5d934432628301bd8b5f9ca7", + "sha256:c0947d7be30335cb4c3d5d0983d8ebc8294ae52503cf1d596c926f7e7183900b", + "sha256:c2a17752f97a942bdb4ff4a0516a67c5ade1658ebe1ab2edacdec0b42e39fa75", + "sha256:c4653830375ab019b86d218c749ad38908b74182b2863d09936aa8d7f990d30e", + "sha256:c660fd1e4a4b52f79f7d134a3d31d452948477b7f46ff5061074a534c5805ba6", + "sha256:cb48ff6cc6109190e1ccf8ea1fc71cc244c9185813ce7d1c415dce991cfb8709", + "sha256:cef2675004d85d85a4ccc24730b73a99931547368d18ceeed1259a2d9fcddbc1", + "sha256:d1b98539b0de822b6f717498e59ae3e5ae2e7f564370ab513e6d0c060753e447", + "sha256:d6c6989c10008ac70c2bb2ad2b940fcfe883712746c89f7e3308c14c213a70d7", + "sha256:db3efec9dcecd96555d752215797816da40315d61878f90ca39c8e269791bf17", + "sha256:dc4749c230a71b34db50ac2481d9008bb17b67c92671c443c3b40e192fbea78e", + "sha256:dcf906c1f7a33e4222e4bff18da1554d69323bc4dd95fe867a6fa80709ee5f93", + "sha256:e2bccadbe313b11704160aaba5eec95d2da1aa663f02f41d2d1520d02bbbdcd5", + "sha256:e30cce3cc86d6082c8596b3fbee0d4f54bc4d337a4fa1bf536920e2e319e24f0", + "sha256:e5d6428b8b422ba5205140e8be11722fa7292a0bedaa8bc80fb34c92eb19ba45", + "sha256:e841695b5dbea38909ab2dbf17e91e9a823412d8d88d1ef77f1b94a7bc551c0f", + "sha256:eb65ec0255a0fccc47c87d44e505ef5180bfd71690bd5f84161b1f23949fb209", + "sha256:ed20ec5a01c43254f6047c5d8124b70d28e39f128c8ad960b437644fe94e1827", + "sha256:ed751a20840a31242e7bea566fcf93ba75bc11b33afe2777bbf46069c1af5094", + "sha256:ef8b927813c27c3bdfc82c55682d7767403bcdadfd9f9c0fc49f4be4553a877b", + "sha256:f43cacda46fc188f998e6d308afe1c61ff41dcb300949f4cbf731e9a0a5eb2d3", + "sha256:f44bea60fd2178d7153deef9621c4b526a93939da30010bba24d3408a98b0f79", + "sha256:fcc021530b7c71069132fe4846d95a3cdd74d143adc2f7e398d5fabf610f111c", + "sha256:fe16517b275031d61261a4e3941c411fb7c46a9cd012f02381b56e7907cc9e06", + "sha256:fe3ae4294d593da54862f0140fdcc89d1aeeb94258ca97f094119ed7f0e5882d" ], "index": "pypi", - "version": "==3.12.0" + "version": "==3.12.1" }, "python-dateutil": { "hashes": [ @@ -330,70 +374,111 @@ }, "typing-extensions": { "hashes": [ - "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497", - "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342", - "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84" + "sha256:2cdf80e4e04866a9b3689a51869016d36db0814d84b8d8a568d22781d45d27ed", + "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9" ], - "version": "==3.10.0.0" + "markers": "python_version >= '3.6'", + "version": "==4.0.0" }, "uvloop": { "hashes": [ - "sha256:0de811931e90ae2da9e19ce70ffad73047ab0c1dba7c6e74f9ae1a3aabeb89bd", - "sha256:1ff05116ede1ebdd81802df339e5b1d4cab1dfbd99295bf27e90b4cec64d70e9", - "sha256:2d8ffe44ae709f839c54bacf14ed283f41bee90430c3b398e521e10f8d117b3a", - "sha256:5cda65fc60a645470b8525ce014516b120b7057b576fa876cdfdd5e60ab1efbb", - "sha256:63a3288abbc9c8ee979d7e34c34e780b2fbab3e7e53d00b6c80271119f277399", - "sha256:7522df4e45e4f25b50adbbbeb5bb9847495c438a628177099d2721f2751ff825", - "sha256:7f4b8a905df909a407c5791fb582f6c03b0d3b491ecdc1cdceaefbc9bf9e08f6", - "sha256:905f0adb0c09c9f44222ee02f6b96fd88b493478fffb7a345287f9444e926030", - "sha256:ae2b325c0f6d748027f7463077e457006b4fdb35a8788f01754aadba825285ee", - "sha256:e71fb9038bfcd7646ca126c5ef19b17e48d4af9e838b2bcfda7a9f55a6552a32" + "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450", + "sha256:089b4834fd299d82d83a25e3335372f12117a7d38525217c2258e9b9f4578897", + "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861", + "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c", + "sha256:3a19828c4f15687675ea912cc28bbcb48e9bb907c801873bd1519b96b04fb805", + "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d", + "sha256:647e481940379eebd314c00440314c81ea547aa636056f554d491e40503c8464", + "sha256:6ccd57ae8db17d677e9e06192e9c9ec4bd2066b77790f9aa7dede2cc4008ee8f", + "sha256:772206116b9b57cd625c8a88f2413df2fcfd0b496eb188b82a43bed7af2c2ec9", + "sha256:8e0d26fa5875d43ddbb0d9d79a447d2ace4180d9e3239788208527c4784f7cab", + "sha256:98d117332cc9e5ea8dfdc2b28b0a23f60370d02e1395f88f40d1effd2cb86c4f", + "sha256:b572256409f194521a9895aef274cea88731d14732343da3ecdb175228881638", + "sha256:bd53f7f5db562f37cd64a3af5012df8cac2c464c97e732ed556800129505bd64", + "sha256:bd8f42ea1ea8f4e84d265769089964ddda95eb2bb38b5cbe26712b0616c3edee", + "sha256:e814ac2c6f9daf4c36eb8e85266859f42174a4ff0d71b99405ed559257750382", + "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228" ], "markers": "sys_platform != 'win32'", - "version": "==0.15.3" + "version": "==0.16.0" }, "yarl": { "hashes": [ - "sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e", - "sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434", - "sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366", - "sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3", - "sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec", - "sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959", - "sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e", - "sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c", - "sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6", - "sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a", - "sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6", - "sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424", - "sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e", - "sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f", - "sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50", - "sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2", - "sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc", - "sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4", - "sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970", - "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10", - "sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0", - "sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406", - "sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896", - "sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643", - "sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721", - "sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478", - "sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724", - "sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e", - "sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8", - "sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96", - "sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25", - "sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76", - "sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2", - "sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2", - "sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c", - "sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a", - "sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71" + "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac", + "sha256:0cba38120db72123db7c58322fa69e3c0efa933040ffb586c3a87c063ec7cae8", + "sha256:167ab7f64e409e9bdd99333fe8c67b5574a1f0495dcfd905bc7454e766729b9e", + "sha256:1be4bbb3d27a4e9aa5f3df2ab61e3701ce8fcbd3e9846dbce7c033a7e8136746", + "sha256:1ca56f002eaf7998b5fcf73b2421790da9d2586331805f38acd9997743114e98", + "sha256:1d3d5ad8ea96bd6d643d80c7b8d5977b4e2fb1bab6c9da7322616fd26203d125", + "sha256:1eb6480ef366d75b54c68164094a6a560c247370a68c02dddb11f20c4c6d3c9d", + "sha256:1edc172dcca3f11b38a9d5c7505c83c1913c0addc99cd28e993efeaafdfaa18d", + "sha256:211fcd65c58bf250fb994b53bc45a442ddc9f441f6fec53e65de8cba48ded986", + "sha256:29e0656d5497733dcddc21797da5a2ab990c0cb9719f1f969e58a4abac66234d", + "sha256:368bcf400247318382cc150aaa632582d0780b28ee6053cd80268c7e72796dec", + "sha256:39d5493c5ecd75c8093fa7700a2fb5c94fe28c839c8e40144b7ab7ccba6938c8", + "sha256:3abddf0b8e41445426d29f955b24aeecc83fa1072be1be4e0d194134a7d9baee", + "sha256:3bf8cfe8856708ede6a73907bf0501f2dc4e104085e070a41f5d88e7faf237f3", + "sha256:3ec1d9a0d7780416e657f1e405ba35ec1ba453a4f1511eb8b9fbab81cb8b3ce1", + "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd", + "sha256:52690eb521d690ab041c3919666bea13ab9fbff80d615ec16fa81a297131276b", + "sha256:534b047277a9a19d858cde163aba93f3e1677d5acd92f7d10ace419d478540de", + "sha256:580c1f15500e137a8c37053e4cbf6058944d4c114701fa59944607505c2fe3a0", + "sha256:59218fef177296451b23214c91ea3aba7858b4ae3306dde120224cfe0f7a6ee8", + "sha256:5ba63585a89c9885f18331a55d25fe81dc2d82b71311ff8bd378fc8004202ff6", + "sha256:5bb7d54b8f61ba6eee541fba4b83d22b8a046b4ef4d8eb7f15a7e35db2e1e245", + "sha256:6152224d0a1eb254f97df3997d79dadd8bb2c1a02ef283dbb34b97d4f8492d23", + "sha256:67e94028817defe5e705079b10a8438b8cb56e7115fa01640e9c0bb3edf67332", + "sha256:695ba021a9e04418507fa930d5f0704edbce47076bdcfeeaba1c83683e5649d1", + "sha256:6a1a9fe17621af43e9b9fcea8bd088ba682c8192d744b386ee3c47b56eaabb2c", + "sha256:6ab0c3274d0a846840bf6c27d2c60ba771a12e4d7586bf550eefc2df0b56b3b4", + "sha256:6feca8b6bfb9eef6ee057628e71e1734caf520a907b6ec0d62839e8293e945c0", + "sha256:737e401cd0c493f7e3dd4db72aca11cfe069531c9761b8ea474926936b3c57c8", + "sha256:788713c2896f426a4e166b11f4ec538b5736294ebf7d5f654ae445fd44270832", + "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58", + "sha256:8300401dc88cad23f5b4e4c1226f44a5aa696436a4026e456fe0e5d2f7f486e6", + "sha256:87f6e082bce21464857ba58b569370e7b547d239ca22248be68ea5d6b51464a1", + "sha256:89ccbf58e6a0ab89d487c92a490cb5660d06c3a47ca08872859672f9c511fc52", + "sha256:8b0915ee85150963a9504c10de4e4729ae700af11df0dc5550e6587ed7891e92", + "sha256:8cce6f9fa3df25f55521fbb5c7e4a736683148bcc0c75b21863789e5185f9185", + "sha256:95a1873b6c0dd1c437fb3bb4a4aaa699a48c218ac7ca1e74b0bee0ab16c7d60d", + "sha256:9b4c77d92d56a4c5027572752aa35082e40c561eec776048330d2907aead891d", + "sha256:9bfcd43c65fbb339dc7086b5315750efa42a34eefad0256ba114cd8ad3896f4b", + "sha256:9c1f083e7e71b2dd01f7cd7434a5f88c15213194df38bc29b388ccdf1492b739", + "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05", + "sha256:a467a431a0817a292121c13cbe637348b546e6ef47ca14a790aa2fa8cc93df63", + "sha256:aa32aaa97d8b2ed4e54dc65d241a0da1c627454950f7d7b1f95b13985afd6c5d", + "sha256:ac10bbac36cd89eac19f4e51c032ba6b412b3892b685076f4acd2de18ca990aa", + "sha256:ac35ccde589ab6a1870a484ed136d49a26bcd06b6a1c6397b1967ca13ceb3913", + "sha256:bab827163113177aee910adb1f48ff7af31ee0289f434f7e22d10baf624a6dfe", + "sha256:baf81561f2972fb895e7844882898bda1eef4b07b5b385bcd308d2098f1a767b", + "sha256:bf19725fec28452474d9887a128e98dd67eee7b7d52e932e6949c532d820dc3b", + "sha256:c01a89a44bb672c38f42b49cdb0ad667b116d731b3f4c896f72302ff77d71656", + "sha256:c0910c6b6c31359d2f6184828888c983d54d09d581a4a23547a35f1d0b9484b1", + "sha256:c10ea1e80a697cf7d80d1ed414b5cb8f1eec07d618f54637067ae3c0334133c4", + "sha256:c1164a2eac148d85bbdd23e07dfcc930f2e633220f3eb3c3e2a25f6148c2819e", + "sha256:c145ab54702334c42237a6c6c4cc08703b6aa9b94e2f227ceb3d477d20c36c63", + "sha256:c17965ff3706beedafd458c452bf15bac693ecd146a60a06a214614dc097a271", + "sha256:c19324a1c5399b602f3b6e7db9478e5b1adf5cf58901996fc973fe4fccd73eed", + "sha256:c2a1ac41a6aa980db03d098a5531f13985edcb451bcd9d00670b03129922cd0d", + "sha256:c6ddcd80d79c96eb19c354d9dca95291589c5954099836b7c8d29278a7ec0bda", + "sha256:c9c6d927e098c2d360695f2e9d38870b2e92e0919be07dbe339aefa32a090265", + "sha256:cc8b7a7254c0fc3187d43d6cb54b5032d2365efd1df0cd1749c0c4df5f0ad45f", + "sha256:cff3ba513db55cc6a35076f32c4cdc27032bd075c9faef31fec749e64b45d26c", + "sha256:d260d4dc495c05d6600264a197d9d6f7fc9347f21d2594926202fd08cf89a8ba", + "sha256:d6f3d62e16c10e88d2168ba2d065aa374e3c538998ed04996cd373ff2036d64c", + "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b", + "sha256:dfe4b95b7e00c6635a72e2d00b478e8a28bfb122dc76349a06e20792eb53a523", + "sha256:e39378894ee6ae9f555ae2de332d513a5763276a9265f8e7cbaeb1b1ee74623a", + "sha256:ede3b46cdb719c794427dcce9d8beb4abe8b9aa1e97526cc20de9bd6583ad1ef", + "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95", + "sha256:f44477ae29025d8ea87ec308539f95963ffdc31a82f42ca9deecf2d505242e72", + "sha256:f64394bd7ceef1237cc604b5a89bf748c95982a84bcd3c4bbeb40f685c810794", + "sha256:fc4dd8b01a8112809e6b636b00f487846956402834a7fd59d46d4f4267181c41", + "sha256:fce78593346c014d0d986b7ebc80d782b7f5e19843ca798ed62f8e3ba8728576", + "sha256:fd547ec596d90c8676e369dd8a581a21227fe9b4ad37d0dc7feb4ccf544c2d59" ], "markers": "python_version >= '3.6'", - "version": "==1.6.3" + "version": "==1.7.2" } }, "develop": { @@ -406,19 +491,19 @@ }, "astroid": { "hashes": [ - "sha256:7b963d1c590d490f60d2973e57437115978d3a2529843f160b5003b721e1e925", - "sha256:83e494b02d75d07d4e347b27c066fd791c0c74fc96c613d1ea3de0c82c48168f" + "sha256:3975a0bd5373bdce166e60c851cfcbaf21ee96de80ec518c1f4cb3e94c3fb334", + "sha256:ab7f36e8a78b8e54a62028ba6beef7561db4cdb6f2a5009ecc44a6f42b5697ef" ], "markers": "python_version ~= '3.6'", - "version": "==2.6.5" + "version": "==2.6.6" }, "bandit": { "hashes": [ - "sha256:216be4d044209fa06cf2a3e51b319769a51be8318140659719aa7a115c35ed07", - "sha256:8a4c7415254d75df8ff3c3b15cfe9042ecee628a1e40b44c15a98890fbfc2608" + "sha256:a81b00b5436e6880fa8ad6799bc830e02032047713cbb143a12939ac67eb756c", + "sha256:f5acd838e59c038a159b5c621cf0f8270b279e884eadd7b782d7491c02add0d4" ], "index": "pypi", - "version": "==1.7.0" + "version": "==1.7.1" }, "black": { "hashes": [ @@ -430,11 +515,11 @@ }, "click": { "hashes": [ - "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a", - "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6" + "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3", + "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b" ], "markers": "python_version >= '3.6'", - "version": "==8.0.1" + "version": "==8.0.3" }, "colorama": { "hashes": [ @@ -446,27 +531,27 @@ }, "gitdb": { "hashes": [ - "sha256:6c4cc71933456991da20917998acbe6cf4fb41eeaab7d6d67fbc05ecd4c865b0", - "sha256:96bf5c08b157a666fec41129e6d327235284cca4c81e92109260f353ba138005" + "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd", + "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa" ], - "markers": "python_version >= '3.4'", - "version": "==4.0.7" + "markers": "python_version >= '3.6'", + "version": "==4.0.9" }, "gitpython": { "hashes": [ - "sha256:b838a895977b45ab6f0cc926a9045c8d1c44e2b653c1fcc39fe91f42c6e8f05b", - "sha256:fce760879cd2aebd2991b3542876dc5c4a909b30c9d69dfc488e504a8db37ee8" + "sha256:dc0a7f2f697657acc8d7f89033e8b1ea94dd90356b2983bca89dc8d2ab3cc647", + "sha256:df83fdf5e684fef7c6ee2c02fc68a5ceb7e7e759d08b694088d0cacb4eba59e5" ], - "markers": "python_version >= '3.6'", - "version": "==3.1.18" + "markers": "python_version >= '3.7'", + "version": "==3.1.24" }, "isort": { "hashes": [ - "sha256:eed17b53c3e7912425579853d078a0832820f023191561fcee9d7cae424e0813", - "sha256:f65ce5bd4cbc6abdfbe29afc2f0245538ab358c14590912df638033f157d555e" + "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7", + "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951" ], "markers": "python_version < '4.0' and python_full_version >= '3.6.1'", - "version": "==5.9.2" + "version": "==5.10.1" }, "lazy-object-proxy": { "hashes": [ @@ -519,124 +604,128 @@ }, "pbr": { "hashes": [ - "sha256:42df03e7797b796625b1029c0400279c7c34fd7df24a7d7818a1abb5b38710dd", - "sha256:c68c661ac5cc81058ac94247278eeda6d2e6aecb3e227b0387c30d277e7ef8d4" + "sha256:176e8560eaf61e127817ef93d8a844803abb27a4d4637f0ff3bb783129be2e0a", + "sha256:672d8ebee84921862110f23fcec2acea191ef58543d34dfe9ef3d9f13c31cddf" ], "markers": "python_version >= '2.6'", - "version": "==5.6.0" + "version": "==5.8.0" }, "pylint": { "hashes": [ - "sha256:1f333dc72ef7f5ea166b3230936ebcfb1f3b722e76c980cb9fe6b9f95e8d3172", - "sha256:748f81e5776d6273a6619506e08f1b48ff9bcb8198366a56821cf11aac14fc87" + "sha256:2e1a0eb2e8ab41d6b5dbada87f066492bb1557b12b76c47c2ee8aa8a11186594", + "sha256:8b838c8983ee1904b2de66cce9d0b96649a91901350e956d78f289c3bc87b48e" ], "index": "pypi", - "version": "==2.9.5" + "version": "==2.9.6" }, "pyyaml": { "hashes": [ - "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf", - "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696", - "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393", - "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77", - "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922", - "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5", - "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8", - "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10", - "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc", - "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018", - "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e", - "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253", - "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347", - "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183", - "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541", - "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb", - "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185", - "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc", - "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db", - "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa", - "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46", - "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122", - "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b", - "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63", - "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", - "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc", - "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247", - "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6", - "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0" + "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", + "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", + "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", + "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", + "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", + "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", + "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", + "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", + "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", + "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", + "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", + "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", + "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", + "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", + "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", + "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", + "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", + "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", + "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", + "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", + "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", + "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", + "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", + "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", + "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", + "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", + "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", + "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", + "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", + "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", + "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", + "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", + "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==5.4.1" + "markers": "python_version >= '3.6'", + "version": "==6.0" }, "regex": { "hashes": [ - "sha256:0eb2c6e0fcec5e0f1d3bcc1133556563222a2ffd2211945d7b1480c1b1a42a6f", - "sha256:15dddb19823f5147e7517bb12635b3c82e6f2a3a6b696cc3e321522e8b9308ad", - "sha256:173bc44ff95bc1e96398c38f3629d86fa72e539c79900283afa895694229fe6a", - "sha256:1c78780bf46d620ff4fff40728f98b8afd8b8e35c3efd638c7df67be2d5cddbf", - "sha256:2366fe0479ca0e9afa534174faa2beae87847d208d457d200183f28c74eaea59", - "sha256:2bceeb491b38225b1fee4517107b8491ba54fba77cf22a12e996d96a3c55613d", - "sha256:2ddeabc7652024803666ea09f32dd1ed40a0579b6fbb2a213eba590683025895", - "sha256:2fe5e71e11a54e3355fa272137d521a40aace5d937d08b494bed4529964c19c4", - "sha256:319eb2a8d0888fa6f1d9177705f341bc9455a2c8aca130016e52c7fe8d6c37a3", - "sha256:3f5716923d3d0bfb27048242a6e0f14eecdb2e2a7fac47eda1d055288595f222", - "sha256:422dec1e7cbb2efbbe50e3f1de36b82906def93ed48da12d1714cabcd993d7f0", - "sha256:4c9c3155fe74269f61e27617529b7f09552fbb12e44b1189cebbdb24294e6e1c", - "sha256:4f64fc59fd5b10557f6cd0937e1597af022ad9b27d454e182485f1db3008f417", - "sha256:564a4c8a29435d1f2256ba247a0315325ea63335508ad8ed938a4f14c4116a5d", - "sha256:59506c6e8bd9306cd8a41511e32d16d5d1194110b8cfe5a11d102d8b63cf945d", - "sha256:598c0a79b4b851b922f504f9f39a863d83ebdfff787261a5ed061c21e67dd761", - "sha256:59c00bb8dd8775473cbfb967925ad2c3ecc8886b3b2d0c90a8e2707e06c743f0", - "sha256:6110bab7eab6566492618540c70edd4d2a18f40ca1d51d704f1d81c52d245026", - "sha256:6afe6a627888c9a6cfbb603d1d017ce204cebd589d66e0703309b8048c3b0854", - "sha256:791aa1b300e5b6e5d597c37c346fb4d66422178566bbb426dd87eaae475053fb", - "sha256:8394e266005f2d8c6f0bc6780001f7afa3ef81a7a2111fa35058ded6fce79e4d", - "sha256:875c355360d0f8d3d827e462b29ea7682bf52327d500a4f837e934e9e4656068", - "sha256:89e5528803566af4df368df2d6f503c84fbfb8249e6631c7b025fe23e6bd0cde", - "sha256:99d8ab206a5270c1002bfcf25c51bf329ca951e5a169f3b43214fdda1f0b5f0d", - "sha256:9a854b916806c7e3b40e6616ac9e85d3cdb7649d9e6590653deb5b341a736cec", - "sha256:b85ac458354165405c8a84725de7bbd07b00d9f72c31a60ffbf96bb38d3e25fa", - "sha256:bc84fb254a875a9f66616ed4538542fb7965db6356f3df571d783f7c8d256edd", - "sha256:c92831dac113a6e0ab28bc98f33781383fe294df1a2c3dfd1e850114da35fd5b", - "sha256:cbe23b323988a04c3e5b0c387fe3f8f363bf06c0680daf775875d979e376bd26", - "sha256:ccb3d2190476d00414aab36cca453e4596e8f70a206e2aa8db3d495a109153d2", - "sha256:d8bbce0c96462dbceaa7ac4a7dfbbee92745b801b24bce10a98d2f2b1ea9432f", - "sha256:db2b7df831c3187a37f3bb80ec095f249fa276dbe09abd3d35297fc250385694", - "sha256:e586f448df2bbc37dfadccdb7ccd125c62b4348cb90c10840d695592aa1b29e0", - "sha256:e5983c19d0beb6af88cb4d47afb92d96751fb3fa1784d8785b1cdf14c6519407", - "sha256:e6a1e5ca97d411a461041d057348e578dc344ecd2add3555aedba3b408c9f874", - "sha256:eaf58b9e30e0e546cdc3ac06cf9165a1ca5b3de8221e9df679416ca667972035", - "sha256:ed693137a9187052fc46eedfafdcb74e09917166362af4cc4fddc3b31560e93d", - "sha256:edd1a68f79b89b0c57339bce297ad5d5ffcc6ae7e1afdb10f1947706ed066c9c", - "sha256:f080248b3e029d052bf74a897b9d74cfb7643537fbde97fe8225a6467fb559b5", - "sha256:f9392a4555f3e4cb45310a65b403d86b589adc773898c25a39184b1ba4db8985", - "sha256:f98dc35ab9a749276f1a4a38ab3e0e2ba1662ce710f6530f5b0a6656f1c32b58" - ], - "version": "==2021.7.6" - }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.16.0" + "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f", + "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc", + "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4", + "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4", + "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8", + "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f", + "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a", + "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef", + "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f", + "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc", + "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50", + "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d", + "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d", + "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733", + "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36", + "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345", + "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0", + "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12", + "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646", + "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667", + "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244", + "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29", + "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec", + "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf", + "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4", + "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449", + "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a", + "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d", + "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb", + "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e", + "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83", + "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e", + "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a", + "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94", + "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc", + "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e", + "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965", + "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0", + "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36", + "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec", + "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23", + "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7", + "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe", + "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6", + "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b", + "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb", + "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b", + "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30", + "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e" + ], + "version": "==2021.11.10" }, "smmap": { "hashes": [ - "sha256:7e65386bd122d45405ddf795637b7f7d2b532e7e401d46bbe3fb49b9986d5182", - "sha256:a9a7479e4c572e2e775c404dcd3080c8dc49f39918c2cf74913d30c4c478e3c2" + "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94", + "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936" ], - "markers": "python_version >= '3.5'", - "version": "==4.0.0" + "markers": "python_version >= '3.6'", + "version": "==5.0.0" }, "stevedore": { "hashes": [ - "sha256:3a5bbd0652bf552748871eaa73a4a8dc2899786bc497a2aa1fcb4dcdb0debeee", - "sha256:50d7b78fbaf0d04cd62411188fa7eedcb03eb7f4c4b37005615ceebe582aa82a" + "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c", + "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335" ], "markers": "python_version >= '3.6'", - "version": "==3.3.0" + "version": "==3.5.0" }, "toml": { "hashes": [ @@ -646,6 +735,14 @@ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, + "typing-extensions": { + "hashes": [ + "sha256:2cdf80e4e04866a9b3689a51869016d36db0814d84b8d8a568d22781d45d27ed", + "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9" + ], + "markers": "python_version >= '3.6'", + "version": "==4.0.0" + }, "wrapt": { "hashes": [ "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" diff --git a/README.md b/README.md index 75a3652454..81cc75929c 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,11 @@ </a> <a href="https://patreon.com/kyber"> - <img src="https://img.shields.io/badge/patreon-donate-orange.svg?style=for-the-badge&logo=Patreon" alt="Python 3.7"> + <img src="https://img.shields.io/badge/patreon-donate-orange.svg?style=for-the-badge&logo=Patreon" alt="Python 3.8"> </a> <a href="https://www.python.org/downloads/"> - <img src="https://img.shields.io/badge/Made%20With-Python%203.7-blue.svg?style=for-the-badge&logo=Python" alt="Made with Python 3.7"> + <img src="https://img.shields.io/badge/Made%20With-Python%203.8-blue.svg?style=for-the-badge&logo=Python" alt="Made with Python 3.8"> </a> <a href="https://github.com/ambv/black"> @@ -108,7 +108,7 @@ If you don't want to go through the trouble of setting up your very own Modmail ### Locally -Local hosting of Modmail is also possible. First, you will need [`Python 3.7`](https://www.python.org/downloads/release/python-376/). +Local hosting of Modmail is also possible. First, you will need [`Python 3.8`](https://www.python.org/downloads/release/python-376/). Follow the [**installation guide**](https://github.com/kyb3r/modmail/wiki/Installation) and disregard deploying the Heroku bot application. If you run into any problems, join our [Modmail Discord Server](https://discord.gg/etJNHCQ) for help and support. diff --git a/bot.py b/bot.py index 432e6fdd11..a0d4043b55 100644 --- a/bot.py +++ b/bot.py @@ -22,8 +22,6 @@ from emoji import UNICODE_EMOJI from pkg_resources import parse_version -from core.utils import tryint - try: # noinspection PyUnresolvedReferences @@ -48,7 +46,7 @@ ) from core.thread import ThreadManager from core.time import human_timedelta -from core.utils import normalize_alias, truncate +from core.utils import normalize_alias, truncate, tryint logger = getLogger(__name__) @@ -69,12 +67,10 @@ def __init__(self): super().__init__(command_prefix=None, intents=intents) # implemented in `get_prefix` self._session = None self._api = None - self.metadata_loop = None - self.autoupdate_loop = None self.formatter = SafeFormatter() self.loaded_cogs = ["cogs.modmail", "cogs.plugins", "cogs.utility"] self._connected = asyncio.Event() - self.start_time = datetime.utcnow() + self.start_time = discord.utils.utcnow() self._started = False self.config = ConfigManager(self) @@ -90,7 +86,7 @@ def __init__(self): @property def uptime(self) -> str: - now = datetime.utcnow() + now = discord.utils.utcnow() delta = now - self.start_time hours, remainder = divmod(int(delta.total_seconds()), 3600) minutes, seconds = divmod(remainder, 60) @@ -241,11 +237,7 @@ def stop_loop_on_completion(f): loop.stop() def _cancel_tasks(): - if sys.version_info < (3, 8): - task_retriever = asyncio.Task.all_tasks - else: - task_retriever = asyncio.all_tasks - + task_retriever = asyncio.all_tasks tasks = {t for t in task_retriever(loop=loop) if not t.done()} if not tasks: @@ -557,6 +549,13 @@ async def on_ready(self): logger.info("Receiving guild ID: %s", self.modmail_guild.id) logger.line() + if "dev" in __version__: + logger.warning( + "You are running a developmental version. This should not be used in production. (v%s)", + __version__, + ) + logger.line() + await self.threads.populate_cache() # closures @@ -565,7 +564,7 @@ async def on_ready(self): logger.line() for recipient_id, items in tuple(closures.items()): - after = (datetime.fromisoformat(items["time"]) - datetime.utcnow()).total_seconds() + after = (datetime.fromisoformat(items["time"]) - discord.utils.utcnow()).total_seconds() if after <= 0: logger.debug("Closing thread for recipient %s.", recipient_id) after = 0 @@ -598,13 +597,13 @@ async def on_ready(self): { "open": False, "title": None, - "closed_at": str(datetime.utcnow()), + "closed_at": str(discord.utils.utcnow()), "close_message": "Channel has been deleted, no closer found.", "closer": { "id": str(self.user.id), "name": self.user.name, "discriminator": self.user.discriminator, - "avatar_url": str(self.user.avatar_url), + "avatar_url": self.user.display_avatar.url, "mod": True, }, }, @@ -614,25 +613,6 @@ async def on_ready(self): else: logger.debug("Failed to close thread with channel %s, skipping.", log["channel_id"]) - if self.config.get("data_collection"): - self.metadata_loop = tasks.Loop( - self.post_metadata, - seconds=0, - minutes=0, - hours=1, - count=None, - reconnect=True, - loop=None, - ) - self.metadata_loop.before_loop(self.before_post_metadata) - self.metadata_loop.start() - - self.autoupdate_loop = tasks.Loop( - self.autoupdate, seconds=0, minutes=0, hours=1, count=None, reconnect=True, loop=None - ) - self.autoupdate_loop.before_loop(self.before_autoupdate) - self.autoupdate_loop.start() - other_guilds = [guild for guild in self.guilds if guild not in {self.guild, self.modmail_guild}] if any(other_guilds): logger.warning( @@ -690,7 +670,7 @@ async def retrieve_emoji(self) -> typing.Tuple[str, str]: def check_account_age(self, author: discord.Member) -> bool: account_age = self.config.get("account_age") - now = datetime.utcnow() + now = discord.utils.utcnow() try: min_account_age = author.created_at + account_age @@ -712,7 +692,7 @@ def check_account_age(self, author: discord.Member) -> bool: def check_guild_age(self, author: discord.Member) -> bool: guild_age = self.config.get("guild_age") - now = datetime.utcnow() + now = discord.utils.utcnow() if not hasattr(author, "joined_at"): logger.warning("Not in guild, cannot verify guild_age, %s.", author.name) @@ -742,7 +722,7 @@ def check_manual_blocked_roles(self, author: discord.Member) -> bool: if str(r.id) in self.blocked_roles: blocked_reason = self.blocked_roles.get(str(r.id)) or "" - now = datetime.utcnow() + now = discord.utils.utcnow() # etc "blah blah blah... until 2019-10-14T21:12:45.559948." end_time = re.search(r"until ([^`]+?)\.$", blocked_reason) @@ -772,7 +752,7 @@ def check_manual_blocked(self, author: discord.Member) -> bool: return True blocked_reason = self.blocked_users.get(str(author.id)) or "" - now = datetime.utcnow() + now = discord.utils.utcnow() if blocked_reason.startswith("System Message:"): # Met the limits already, otherwise it would've been caught by the previous checks @@ -861,7 +841,7 @@ async def is_blocked( async def get_thread_cooldown(self, author: discord.Member): thread_cooldown = self.config.get("thread_cooldown") - now = datetime.utcnow() + now = discord.utils.utcnow() if thread_cooldown == isodate.Duration(): return @@ -932,7 +912,7 @@ async def process_dm_modmail(self, message: discord.Message) -> None: color=self.error_color, description=self.config["disabled_new_thread_response"], ) - embed.set_footer(text=self.config["disabled_new_thread_footer"], icon_url=self.guild.icon_url) + embed.set_footer(text=self.config["disabled_new_thread_footer"], icon_url=self.guild.icon.url) logger.info("A new thread was blocked from %s due to disabled Modmail.", message.author) await self.add_reaction(message, blocked_emoji) return await message.channel.send(embed=embed) @@ -947,7 +927,7 @@ async def process_dm_modmail(self, message: discord.Message) -> None: ) embed.set_footer( text=self.config["disabled_current_thread_footer"], - icon_url=self.guild.icon_url, + icon_url=self.guild.icon.url, ) logger.info("A message was blocked from %s due to disabled Modmail.", message.author) await self.add_reaction(message, blocked_emoji) @@ -982,7 +962,7 @@ async def get_contexts(self, message, *, cls=commands.Context): ctx = cls(prefix=self.prefix, view=view, bot=self, message=message) thread = await self.threads.find(channel=ctx.channel) - if self._skip_check(message.author.id, self.user.id): + if message.author.id == self.user.id: # type: ignore return [ctx] prefixes = await self.get_prefix() @@ -1139,7 +1119,7 @@ async def on_message(self, message): color=self.main_color, ) if self.config["show_timestamp"]: - em.timestamp = datetime.utcnow() + em.timestamp = discord.utils.utcnow() if not self.config["silent_alert_on_mention"]: content = self.config["mention"] @@ -1329,7 +1309,7 @@ async def handle_react_to_contact(self, payload): ) embed.set_footer( text=self.config["disabled_new_thread_footer"], - icon_url=self.guild.icon_url, + icon_url=self.guild.icon.url, ) logger.info( "A new thread using react to contact was blocked from %s due to disabled Modmail.", @@ -1431,7 +1411,13 @@ async def on_message_delete(self, message): return message = message[0] embed = message.embeds[0] - embed.set_footer(text=f"{embed.footer.text} (deleted)", icon_url=embed.footer.icon_url) + + if embed.footer.icon: + icon_url = embed.footer.icon.url + else: + icon_url = discord.Embed.Empty + + embed.set_footer(text=f"{embed.footer.text} (deleted)", icon_url=icon_url) await message.edit(embed=embed) return @@ -1521,21 +1507,23 @@ async def on_command_error(self, context, exception): else: logger.error("Unexpected exception:", exc_info=exception) + @tasks.loop(hours=1) async def post_metadata(self): info = await self.application_info() + delta = discord.utils.utcnow() - self.start_time data = { "bot_id": self.user.id, "bot_name": str(self.user), - "avatar_url": str(self.user.avatar_url), + "avatar_url": self.user.display_avatar.url, "guild_id": self.guild_id, "guild_name": self.guild.name, "member_count": len(self.guild.members), - "uptime": (datetime.utcnow() - self.start_time).total_seconds(), + "uptime": delta.total_seconds(), "latency": f"{self.ws.latency * 1000:.4f}", "version": str(self.version), "selfhosted": True, - "last_updated": str(datetime.utcnow()), + "last_updated": str(discord.utils.utcnow()), } if info.team is not None: @@ -1552,13 +1540,16 @@ async def post_metadata(self): async with self.session.post("https://api.modmail.dev/metadata", json=data): logger.debug("Uploading metadata to Modmail server.") + @post_metadata.before_loop async def before_post_metadata(self): await self.wait_for_connected() + if not self.config.get("data_collection") or not self.guild: + self.post_metadata.cancel() + logger.debug("Starting metadata loop.") logger.line("debug") - if not self.guild: - self.metadata_loop.cancel() + @tasks.loop(hours=1) async def autoupdate(self): changelog = await Changelog.from_url(self) latest = changelog.latest_version @@ -1637,6 +1628,7 @@ async def autoupdate(self): await channel.send(embed=embed) return await self.close() + @autoupdate.before_loop async def before_autoupdate(self): await self.wait_for_connected() logger.debug("Starting autoupdate loop") @@ -1696,9 +1688,9 @@ def main(): pass # check discord version - if discord.__version__ != "1.7.3": + if discord.__version__ != "2.0.0a": logger.error( - "Dependencies are not updated, run pipenv install. discord.py version expected 1.7.3, received %s", + "Dependencies are not updated, run pipenv install. discord.py version expected 2.0.0a, received %s", discord.__version__, ) sys.exit(0) diff --git a/cogs/modmail.py b/cogs/modmail.py index 6da8ce0772..60c18594ac 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -158,7 +158,7 @@ async def snippet(self, ctx, *, name: str.lower = None): color=self.bot.error_color, description="You dont have any snippets at the moment." ) embed.set_footer(text=f'Check "{self.bot.prefix}help snippet add" to add a snippet.') - embed.set_author(name="Snippets", icon_url=ctx.guild.icon_url) + embed.set_author(name="Snippets", icon_url=ctx.guild.icon.url) return await ctx.send(embed=embed) embeds = [] @@ -166,7 +166,7 @@ async def snippet(self, ctx, *, name: str.lower = None): for i, names in enumerate(zip_longest(*(iter(sorted(self.bot.snippets)),) * 15)): description = format_description(i, names) embed = discord.Embed(color=self.bot.main_color, description=description) - embed.set_author(name="Snippets", icon_url=ctx.guild.icon_url) + embed.set_author(name="Snippets", icon_url=ctx.guild.icon.url) embeds.append(embed) session = EmbedPaginatorSession(ctx, *embeds) @@ -396,7 +396,7 @@ async def close(self, ctx, *, after: UserFriendlyTime = None): thread = ctx.thread - now = datetime.utcnow() + now = discord.utils.utcnow() close_after = (after.dt - now).total_seconds() if after else 0 message = after.arg if after else None @@ -643,7 +643,7 @@ def format_log_embeds(self, logs, avatar_url): embed = discord.Embed(color=self.bot.main_color, timestamp=created_at) embed.set_author(name=f"{title} - {username}", icon_url=avatar_url, url=log_url) embed.url = log_url - embed.add_field(name="Created", value=duration(created_at, now=datetime.utcnow())) + embed.add_field(name="Created", value=duration(created_at, now=discord.utils.utcnow())) closer = entry.get("closer") if closer is None: closer_msg = "Unknown" @@ -745,8 +745,8 @@ async def adduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, str color=self.bot.main_color, ) if self.bot.config["show_timestamp"]: - em.timestamp = datetime.utcnow() - em.set_footer(text=str(ctx.author), icon_url=ctx.author.avatar_url) + em.timestamp = discord.utils.utcnow() + em.set_footer(text=str(ctx.author), icon_url=ctx.author.display_avatar.url) for u in users: await u.send(embed=em) @@ -761,8 +761,8 @@ async def adduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, str color=self.bot.main_color, ) if self.bot.config["show_timestamp"]: - em.timestamp = datetime.utcnow() - em.set_footer(text=f"{users[0]}", icon_url=users[0].avatar_url) + em.timestamp = discord.utils.utcnow() + em.set_footer(text=f"{users[0]}", icon_url=users[0].display_avatar.url) for i in ctx.thread.recipients: if i not in users: @@ -834,8 +834,8 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role, color=self.bot.main_color, ) if self.bot.config["show_timestamp"]: - em.timestamp = datetime.utcnow() - em.set_footer(text=str(ctx.author), icon_url=ctx.author.avatar_url) + em.timestamp = discord.utils.utcnow() + em.set_footer(text=str(ctx.author), icon_url=ctx.author.display_avatar.url) for u in users: await u.send(embed=em) @@ -850,8 +850,8 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role, color=self.bot.main_color, ) if self.bot.config["show_timestamp"]: - em.timestamp = datetime.utcnow() - em.set_footer(text=f"{users[0]}", icon_url=users[0].avatar_url) + em.timestamp = discord.utils.utcnow() + em.set_footer(text=f"{users[0]}", icon_url=users[0].display_avatar.url) for i in ctx.thread.recipients: if i not in users: @@ -914,7 +914,7 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, color=self.bot.main_color, ) if self.bot.config["show_timestamp"]: - em.timestamp = datetime.utcnow() + em.timestamp = discord.utils.utcnow() tag = self.bot.config["mod_tag"] if tag is None: @@ -924,7 +924,7 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: - avatar_url = self.bot.guild.icon_url + avatar_url = self.bot.guild.icon.url em.set_footer(text=name, icon_url=avatar_url) for u in users: @@ -940,8 +940,8 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, color=self.bot.main_color, ) if self.bot.config["show_timestamp"]: - em.timestamp = datetime.utcnow() - em.set_footer(text=f"{users[0]}", icon_url=users[0].avatar_url) + em.timestamp = discord.utils.utcnow() + em.set_footer(text=f"{users[0]}", icon_url=users[0].display_avatar.url) for i in ctx.thread.recipients: if i not in users: @@ -999,7 +999,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro color=self.bot.main_color, ) if self.bot.config["show_timestamp"]: - em.timestamp = datetime.utcnow() + em.timestamp = discord.utils.utcnow() tag = self.bot.config["mod_tag"] if tag is None: @@ -1009,7 +1009,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: - avatar_url = self.bot.guild.icon_url + avatar_url = self.bot.guild.icon.url em.set_footer(text=name, icon_url=avatar_url) for u in users: @@ -1025,8 +1025,8 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro color=self.bot.main_color, ) if self.bot.config["show_timestamp"]: - em.timestamp = datetime.utcnow() - em.set_footer(text=f"{users[0]}", icon_url=users[0].avatar_url) + em.timestamp = discord.utils.utcnow() + em.set_footer(text=f"{users[0]}", icon_url=users[0].display_avatar.url) for i in ctx.thread.recipients: if i not in users: @@ -1086,7 +1086,7 @@ async def logs_closed_by(self, ctx, *, user: User = None): user = user if user is not None else ctx.author entries = await self.bot.api.search_closed_by(user.id) - embeds = self.format_log_embeds(entries, avatar_url=self.bot.guild.icon_url) + embeds = self.format_log_embeds(entries, avatar_url=self.bot.guild.icon.url) if not embeds: embed = discord.Embed( @@ -1136,7 +1136,7 @@ async def logs_responded(self, ctx, *, user: User = None): entries = await self.bot.api.get_responded_logs(user.id) - embeds = self.format_log_embeds(entries, avatar_url=self.bot.guild.icon_url) + embeds = self.format_log_embeds(entries, avatar_url=self.bot.guild.icon.url) if not embeds: embed = discord.Embed( @@ -1161,7 +1161,7 @@ async def logs_search(self, ctx, limit: Optional[int] = None, *, query): entries = await self.bot.api.search_by_text(query, limit) - embeds = self.format_log_embeds(entries, avatar_url=self.bot.guild.icon_url) + embeds = self.format_log_embeds(entries, avatar_url=self.bot.guild.icon.url) if not embeds: embed = discord.Embed( @@ -1452,8 +1452,8 @@ async def contact( color=self.bot.main_color, ) if self.bot.config["show_timestamp"]: - em.timestamp = datetime.utcnow() - em.set_footer(text=f"{creator}", icon_url=creator.avatar_url) + em.timestamp = discord.utils.utcnow() + em.set_footer(text=f"{creator}", icon_url=creator.display_avatar.url) for u in users: await u.send(embed=em) diff --git a/cogs/plugins.py b/cogs/plugins.py index 4cdd0aba3f..e9adf2a240 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -730,7 +730,7 @@ async def plugins_registry_compact(self, ctx): for page in pages: embed = discord.Embed(color=self.bot.main_color, description=page) - embed.set_author(name="Plugin Registry", icon_url=self.bot.user.avatar_url) + embed.set_author(name="Plugin Registry", icon_url=self.bot.user.display_avatar.url) embeds.append(embed) paginator = EmbedPaginatorSession(ctx, *embeds) diff --git a/cogs/utility.py b/cogs/utility.py index bc813e9d6e..7278c350fc 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -5,7 +5,6 @@ import re import traceback from contextlib import redirect_stdout -from datetime import datetime from difflib import get_close_matches from io import BytesIO, StringIO from itertools import takewhile, zip_longest @@ -54,7 +53,7 @@ async def command_callback(self, ctx, *, command=None): async def format_cog_help(self, cog, *, no_cog=False): bot = self.context.bot - prefix = self.clean_prefix + prefix = self.context.clean_prefix formats = [""] for cmd in await self.filter_commands( @@ -92,7 +91,7 @@ async def format_cog_help(self, cog, *, no_cog=False): continued = " (Continued)" if embeds else "" name = cog.qualified_name + " - Help" if not no_cog else "Miscellaneous Commands" - embed.set_author(name=name + continued, icon_url=bot.user.avatar_url) + embed.set_author(name=name + continued, icon_url=bot.user.display_avatar.url) embed.set_footer( text=f'Type "{prefix}{self.command_attrs["name"]} command" ' @@ -102,7 +101,7 @@ async def format_cog_help(self, cog, *, no_cog=False): return embeds def process_help_msg(self, help_: str): - return help_.format(prefix=self.clean_prefix) if help_ else "No help message." + return help_.format(prefix=self.context.clean_prefix) if help_ else "No help message." async def send_bot_help(self, mapping): embeds = [] @@ -174,7 +173,7 @@ async def send_group_help(self, group): embed.add_field(name="Sub Command(s)", value=format_[:1024], inline=False) embed.set_footer( - text=f'Type "{self.clean_prefix}{self.command_attrs["name"]} command" ' + text=f'Type "{self.context.clean_prefix}{self.command_attrs["name"]} command" ' "for more info on a command." ) @@ -216,7 +215,7 @@ async def send_error_message(self, error): embed.add_field(name=f"Step {i}:", value=val) embed.set_footer( - text=f'Type "{self.clean_prefix}{self.command_attrs["name"]} alias" ' + text=f'Type "{self.context.clean_prefix}{self.command_attrs["name"]} alias" ' "for more details on aliases." ) return await self.get_destination().send(embed=embed) @@ -238,7 +237,7 @@ async def send_error_message(self, error): else: embed.title = "Cannot find command or category" embed.set_footer( - text=f'Type "{self.clean_prefix}{self.command_attrs["name"]}" ' + text=f'Type "{self.context.clean_prefix}{self.command_attrs["name"]}" ' "for a list of all available commands." ) await self.get_destination().send(embed=embed) @@ -303,13 +302,13 @@ async def changelog(self, ctx, version: str.lower = ""): @utils.trigger_typing async def about(self, ctx): """Shows information about this bot.""" - embed = discord.Embed(color=self.bot.main_color, timestamp=datetime.utcnow()) + embed = discord.Embed(color=self.bot.main_color, timestamp=discord.utils.utcnow()) embed.set_author( name="Modmail - About", - icon_url=self.bot.user.avatar_url, + icon_url=self.bot.user.display_avatar.url, url="https://discord.gg/F34cRU8", ) - embed.set_thumbnail(url=self.bot.user.avatar_url) + embed.set_thumbnail(url=self.bot.user.display_avatar.url) desc = "This is an open source Discord bot that serves as a means for " desc += "members to easily communicate with server administrators in " @@ -848,7 +847,7 @@ async def config_get(self, ctx, *, key: str.lower = None): if key in keys: desc = f"`{key}` is set to `{self.bot.config[key]}`" embed = discord.Embed(color=self.bot.main_color, description=desc) - embed.set_author(name="Config variable", icon_url=self.bot.user.avatar_url) + embed.set_author(name="Config variable", icon_url=self.bot.user.display_avatar.url) else: embed = discord.Embed( @@ -865,7 +864,7 @@ async def config_get(self, ctx, *, key: str.lower = None): color=self.bot.main_color, description="Here is a list of currently set configuration variable(s).", ) - embed.set_author(name="Current config(s):", icon_url=self.bot.user.avatar_url) + embed.set_author(name="Current config(s):", icon_url=self.bot.user.display_avatar.url) config = self.bot.config.filter_default(self.bot.config) for name, value in config.items(): @@ -1006,7 +1005,7 @@ async def alias(self, ctx, *, name: str.lower = None): color=self.bot.error_color, description="You dont have any aliases at the moment." ) embed.set_footer(text=f'Do "{self.bot.prefix}help alias" for more commands.') - embed.set_author(name="Aliases", icon_url=ctx.guild.icon_url) + embed.set_author(name="Aliases", icon_url=ctx.guild.icon.url) return await ctx.send(embed=embed) embeds = [] @@ -1014,7 +1013,7 @@ async def alias(self, ctx, *, name: str.lower = None): for i, names in enumerate(zip_longest(*(iter(sorted(self.bot.aliases)),) * 15)): description = utils.format_description(i, names) embed = discord.Embed(color=self.bot.main_color, description=description) - embed.set_author(name="Command Aliases", icon_url=ctx.guild.icon_url) + embed.set_author(name="Command Aliases", icon_url=ctx.guild.icon.url) embeds.append(embed) session = EmbedPaginatorSession(ctx, *embeds) @@ -1595,7 +1594,7 @@ async def permissions_get( for name, level in takewhile(lambda x: x is not None, items) ) embed = discord.Embed(color=self.bot.main_color, description=description) - embed.set_author(name="Permission Overrides", icon_url=ctx.guild.icon_url) + embed.set_author(name="Permission Overrides", icon_url=ctx.guild.icon.url) embeds.append(embed) session = EmbedPaginatorSession(ctx, *embeds) diff --git a/core/changelog.py b/core/changelog.py index 7c9af2e1bb..4ede9f09f1 100644 --- a/core/changelog.py +++ b/core/changelog.py @@ -90,14 +90,14 @@ def embed(self) -> Embed: embed = Embed(color=self.bot.main_color, description=self.description) embed.set_author( name=f"v{self.version} - Changelog", - icon_url=self.bot.user.avatar_url, + icon_url=self.bot.user.display_avatar.url, url=self.url, ) for name, value in self.fields.items(): embed.add_field(name=name, value=truncate(value, 1024), inline=False) embed.set_footer(text=f"Current version: v{self.bot.version}") - embed.set_thumbnail(url=self.bot.user.avatar_url) + embed.set_thumbnail(url=self.bot.user.display_avatar.url) return embed diff --git a/core/clients.py b/core/clients.py index 489954e3e4..5caf58f4d2 100644 --- a/core/clients.py +++ b/core/clients.py @@ -1,9 +1,9 @@ import secrets import sys -from datetime import datetime from json import JSONDecodeError from typing import Union, Optional +import discord from discord import Member, DMChannel, TextChannel, Message from discord.ext import commands @@ -507,7 +507,7 @@ async def create_log_entry(self, recipient: Member, channel: TextChannel, creato "_id": key, "key": key, "open": True, - "created_at": str(datetime.utcnow()), + "created_at": str(discord.utils.utcnow()), "closed_at": None, "channel_id": str(channel.id), "guild_id": str(self.bot.guild_id), @@ -516,14 +516,14 @@ async def create_log_entry(self, recipient: Member, channel: TextChannel, creato "id": str(recipient.id), "name": recipient.name, "discriminator": recipient.discriminator, - "avatar_url": str(recipient.avatar_url), + "avatar_url": recipient.display_avatar.url, "mod": False, }, "creator": { "id": str(creator.id), "name": creator.name, "discriminator": creator.discriminator, - "avatar_url": str(creator.avatar_url), + "avatar_url": creator.display_avatar.url, "mod": isinstance(creator, Member), }, "closer": None, @@ -585,7 +585,7 @@ async def append_log( "id": str(message.author.id), "name": message.author.name, "discriminator": message.author.discriminator, - "avatar_url": str(message.author.avatar_url), + "avatar_url": message.author.display_avatar.url, "mod": not isinstance(message.channel, DMChannel), }, "content": message.content, @@ -635,7 +635,7 @@ async def create_note(self, recipient: Member, message: Message, message_id: Uni "id": str(message.author.id), "name": message.author.name, "discriminator": message.author.discriminator, - "avatar_url": str(message.author.avatar_url), + "avatar_url": message.author.display_avatar.url, }, "message": message.content, "message_id": str(message_id), @@ -666,7 +666,7 @@ async def update_repository(self) -> dict: "data": data, "user": { "username": user.username, - "avatar_url": user.avatar_url, + "avatar_url": user.display_avatar.url, "url": user.url, }, } @@ -680,7 +680,7 @@ async def get_user_info(self) -> Optional[dict]: return { "user": { "username": user.username, - "avatar_url": user.avatar_url, + "avatar_url": user.display_avatar.url, "url": user.url, } } diff --git a/core/paginator.py b/core/paginator.py index 7ba1c98b60..934b4670be 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -209,7 +209,13 @@ def __init__(self, ctx: commands.Context, *embeds, **options): footer_text = f"Page {i + 1} of {len(self.pages)}" if embed.footer.text: footer_text = footer_text + " โ€ข " + embed.footer.text - embed.set_footer(text=footer_text, icon_url=embed.footer.icon_url) + + if embed.footer.icon: + icon_url = embed.footer.icon.url + else: + icon_url = Embed.Empty + + embed.set_footer(text=footer_text, icon_url=icon_url) def add_page(self, item: Embed) -> None: if isinstance(item, Embed): @@ -241,7 +247,13 @@ def _set_footer(self): footer_text = f"Page {self.current+1} of {len(self.pages)}" if self.footer_text: footer_text = footer_text + " โ€ข " + self.footer_text - self.embed.set_footer(text=footer_text, icon_url=self.embed.footer.icon_url) + + if self.embed.footer.icon: + icon_url = self.embed.footer.icon.url + else: + icon_url = Embed.Empty + + self.embed.set_footer(text=footer_text, icon_url=icon_url) async def _create_base(self, item: str) -> None: self._set_footer() diff --git a/core/thread.py b/core/thread.py index 536e68b595..2550ab0ad9 100644 --- a/core/thread.py +++ b/core/thread.py @@ -4,7 +4,7 @@ import re import time import typing -from datetime import datetime, timedelta +from datetime import timedelta from types import SimpleNamespace import isodate @@ -159,7 +159,7 @@ async def setup(self, *, creator=None, category=None, initial_message=None): category = category or self.bot.main_category if category is not None: - overwrites = None + overwrites = {} try: channel = await create_thread_channel(self.bot, recipient, category, overwrites) @@ -224,7 +224,7 @@ async def send_recipient_genesis_message(): else: footer = self.bot.config["thread_creation_footer"] - embed.set_footer(text=footer, icon_url=self.bot.guild.icon_url) + embed.set_footer(text=footer, icon_url=self.bot.guild.icon.url) embed.title = self.bot.config["thread_creation_title"] if creator is None or creator == recipient: @@ -250,7 +250,7 @@ class Author: name = author["name"] id = author["id"] discriminator = author["discriminator"] - avatar_url = author["avatar_url"] + display_avatar = SimpleNamespace(url=author["avatar_url"]) data = { "id": round(time.time() * 1000 - discord.utils.DISCORD_EPOCH) << 22, @@ -264,7 +264,7 @@ class Author: "content": note["message"], "author": Author(), } - message = discord.Message(state=State(), channel=None, data=data) + message = discord.Message(state=State(), channel=self.channel, data=data) ids[note["_id"]] = str((await self.note(message, persistent=True, thread_creation=True)).id) await self.bot.api.update_note_ids(ids) @@ -290,7 +290,7 @@ def _format_info_embed(self, user, log_url, log_count, color): """Get information about a member of a server supports users from the guild or not.""" member = self.bot.guild.get_member(user.id) - time = datetime.utcnow() + time = discord.utils.utcnow() # key = log_url.split('/')[-1] @@ -329,7 +329,7 @@ def _format_info_embed(self, user, log_url, log_count, color): else: footer = f"User ID: {user.id}" - embed.set_author(name=str(user), icon_url=user.avatar_url, url=log_url) + embed.set_author(name=str(user), icon_url=user.display_avatar.url, url=log_url) # embed.set_thumbnail(url=avi) if member is not None: @@ -382,7 +382,7 @@ async def close( if after > 0: # TODO: Add somewhere to clean up broken closures # (when channel is already deleted) - now = datetime.utcnow() + now = discord.utils.utcnow() items = { # 'initiation_time': now.isoformat(), "time": (now + timedelta(seconds=after)).isoformat(), @@ -425,14 +425,14 @@ async def _close(self, closer, silent=False, delete_channel=True, message=None, { "open": False, "title": match_title(self.channel.topic), - "closed_at": str(datetime.utcnow()), + "closed_at": str(discord.utils.utcnow()), "nsfw": self.channel.nsfw, "close_message": message, "closer": { "id": str(closer.id), "name": closer.name, "discriminator": closer.discriminator, - "avatar_url": str(closer.avatar_url), + "avatar_url": closer.display_avatar.url, "mod": True, }, }, @@ -483,8 +483,8 @@ async def _close(self, closer, silent=False, delete_channel=True, message=None, event = "Thread Closed as Scheduled" if scheduled else "Thread Closed" # embed.set_author(name=f"Event: {event}", url=log_url) - embed.set_footer(text=f"{event} by {_closer}", icon_url=closer.avatar_url) - embed.timestamp = datetime.utcnow() + embed.set_footer(text=f"{event} by {_closer}", icon_url=closer.display_avatar.url) + embed.timestamp = discord.utils.utcnow() tasks = [self.bot.config.update()] @@ -498,7 +498,7 @@ async def _close(self, closer, silent=False, delete_channel=True, message=None, color=self.bot.error_color, ) if self.bot.config["show_timestamp"]: - embed.timestamp = datetime.utcnow() + embed.timestamp = discord.utils.utcnow() if not message: if self.id == closer.id: @@ -512,7 +512,7 @@ async def _close(self, closer, silent=False, delete_channel=True, message=None, embed.description = message footer = self.bot.config["thread_close_footer"] - embed.set_footer(text=footer, icon_url=self.bot.guild.icon_url) + embed.set_footer(text=footer, icon_url=self.bot.guild.icon.url) if not silent: for user in self.recipients: @@ -558,7 +558,7 @@ async def _restart_close_timer(self): # Set timeout seconds seconds = timeout.total_seconds() # seconds = 20 # Uncomment to debug with just 20 seconds - reset_time = datetime.utcnow() + timedelta(seconds=seconds) + reset_time = discord.utils.utcnow() + timedelta(seconds=seconds) human_time = human_timedelta(dt=reset_time) if self.bot.config.get("thread_auto_close_silently"): @@ -943,7 +943,7 @@ async def send( name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: - avatar_url = self.bot.guild.icon_url + avatar_url = self.bot.guild.icon.url embed.set_author( name=name, icon_url=avatar_url, @@ -952,7 +952,7 @@ async def send( else: # Normal message name = str(author) - avatar_url = author.avatar_url + avatar_url = author.display_avatar.url embed.set_author( name=name, icon_url=avatar_url, diff --git a/core/time.py b/core/time.py index bdec8d2549..376f2074eb 100644 --- a/core/time.py +++ b/core/time.py @@ -6,6 +6,7 @@ import re from datetime import datetime +import discord from discord.ext.commands import BadArgument, Converter import parsedatetime as pdt @@ -13,6 +14,7 @@ from core.models import getLogger + logger = getLogger(__name__) @@ -36,7 +38,7 @@ def __init__(self, argument): raise BadArgument("Invalid time provided.") data = {k: int(v) for k, v in match.groupdict(default="0").items()} - now = datetime.utcnow() + now = discord.utils.utcnow() self.dt = now + relativedelta(**data) @@ -50,7 +52,7 @@ class HumanTime: calendar = pdt.Calendar(version=pdt.VERSION_CONTEXT_STYLE) def __init__(self, argument): - now = datetime.utcnow() + now = discord.utils.utcnow() dt, status = self.calendar.parseDT(argument, sourceTime=now) if not status.hasDateOrTime: raise BadArgument('Invalid time provided, try e.g. "tomorrow" or "3 days".') @@ -104,7 +106,7 @@ def convert(self, ctx, argument): try: calendar = HumanTime.calendar regex = ShortTime.compiled - self.dt = self.now = datetime.utcnow() + self.dt = self.now = discord.utils.utcnow() match = regex.match(argument) if match is not None and match.group(0): @@ -186,7 +188,7 @@ async def convert(self, ctx, argument): def human_timedelta(dt, *, source=None): - now = source or datetime.utcnow() + now = source or discord.utils.utcnow() if dt > now: delta = relativedelta(dt, now) suffix = "" diff --git a/core/utils.py b/core/utils.py index 1440b9c8eb..9b56cbe31d 100644 --- a/core/utils.py +++ b/core/utils.py @@ -245,7 +245,11 @@ def parse_channel_topic(text: str) -> typing.Tuple[typing.Optional[str], int, ty A tuple of title, user ID, and other recipients IDs. """ title, user_id, other_ids = None, -1, [] - match = TOPIC_REGEX.search(text) + if isinstance(text, str): + match = TOPIC_REGEX.search(text) + else: + match = None + if match is not None: groupdict = match.groupdict() title = groupdict["title"] diff --git a/requirements.txt b/requirements.txt index d802cc0c46..fb43d23e2b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,19 +11,19 @@ async-timeout==3.0.1; python_full_version >= '3.5.3' attrs==21.2.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' chardet==4.0.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' colorama==0.4.4 -discord.py==1.7.3 -dnspython==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +dnspython==2.1.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' emoji==1.2.0 -idna==3.2; python_version >= '3.5' +git+https://github.com/Rapptz/discord.py.git@45d498c1b76deaf3b394d17ccf56112fa691d160#egg=discord-py +idna==3.3; python_version >= '3.5' isodate==0.6.0 motor==2.4.0 -multidict==5.1.0; python_version >= '3.6' +multidict==5.2.0; python_version >= '3.6' natural==0.2.0 parsedatetime==2.6 -pymongo[srv]==3.11.4 -python-dateutil==2.8.1 +pymongo[srv]==3.12.1 +python-dateutil==2.8.2 python-dotenv==0.18.0 six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -typing-extensions==3.10.0.0 -uvloop==0.15.2; sys_platform != 'win32' -yarl==1.6.3; python_version >= '3.6' +typing-extensions==4.0.0; python_version >= '3.6' +uvloop==0.16.0; sys_platform != 'win32' +yarl==1.7.2; python_version >= '3.6' \ No newline at end of file From 96a9af069554050387e2b02c69949c07e1ad0b40 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 00:58:58 +0800 Subject: [PATCH 022/225] Update bandit baseline --- .bandit_baseline.json | 62 +++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/.bandit_baseline.json b/.bandit_baseline.json index 28a4e47b9c..12aa666e27 100644 --- a/.bandit_baseline.json +++ b/.bandit_baseline.json @@ -1,6 +1,6 @@ { "errors": [], - "generated_at": "2020-11-26T11:00:36Z", + "generated_at": "2021-11-20T16:58:19Z", "metrics": { "./bot.py": { "CONFIDENCE.HIGH": 1.0, @@ -11,7 +11,7 @@ "SEVERITY.LOW": 1.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 1321, + "loc": 1412, "nosec": 0 }, "./cogs/modmail.py": { @@ -23,7 +23,7 @@ "SEVERITY.LOW": 0.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 1273, + "loc": 1688, "nosec": 0 }, "./cogs/plugins.py": { @@ -35,7 +35,7 @@ "SEVERITY.LOW": 1.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 578, + "loc": 597, "nosec": 0 }, "./cogs/utility.py": { @@ -47,7 +47,7 @@ "SEVERITY.LOW": 1.0, "SEVERITY.MEDIUM": 1.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 1755, + "loc": 1767, "nosec": 0 }, "./core/_color_data.py": { @@ -71,7 +71,7 @@ "SEVERITY.LOW": 1.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 155, + "loc": 159, "nosec": 0 }, "./core/checks.py": { @@ -83,7 +83,7 @@ "SEVERITY.LOW": 0.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 90, + "loc": 105, "nosec": 0 }, "./core/clients.py": { @@ -95,7 +95,7 @@ "SEVERITY.LOW": 1.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 587, + "loc": 598, "nosec": 0 }, "./core/config.py": { @@ -107,7 +107,7 @@ "SEVERITY.LOW": 0.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 352, + "loc": 377, "nosec": 0 }, "./core/decorators.py": { @@ -131,7 +131,7 @@ "SEVERITY.LOW": 0.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 202, + "loc": 204, "nosec": 0 }, "./core/paginator.py": { @@ -143,7 +143,7 @@ "SEVERITY.LOW": 0.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 209, + "loc": 217, "nosec": 0 }, "./core/thread.py": { @@ -155,7 +155,7 @@ "SEVERITY.LOW": 0.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 996, + "loc": 1138, "nosec": 0 }, "./core/time.py": { @@ -167,7 +167,7 @@ "SEVERITY.LOW": 0.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 158, + "loc": 157, "nosec": 0 }, "./core/utils.py": { @@ -179,19 +179,7 @@ "SEVERITY.LOW": 0.0, "SEVERITY.MEDIUM": 0.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 282, - "nosec": 0 - }, - "./plugins/kyb3r/modmail-plugins/profanity-filter-master/profanity-filter.py": { - "CONFIDENCE.HIGH": 0.0, - "CONFIDENCE.LOW": 0.0, - "CONFIDENCE.MEDIUM": 0.0, - "CONFIDENCE.UNDEFINED": 0.0, - "SEVERITY.HIGH": 0.0, - "SEVERITY.LOW": 0.0, - "SEVERITY.MEDIUM": 0.0, - "SEVERITY.UNDEFINED": 0.0, - "loc": 81, + "loc": 389, "nosec": 0 }, "_totals": { @@ -203,20 +191,20 @@ "SEVERITY.LOW": 5.0, "SEVERITY.MEDIUM": 1.0, "SEVERITY.UNDEFINED": 0.0, - "loc": 9214, + "loc": 9983, "nosec": 0 } }, "results": [ { - "code": "11 from datetime import datetime\n12 from subprocess import PIPE\n13 from types import SimpleNamespace\n", + "code": "13 from datetime import datetime\n14 from subprocess import PIPE\n15 from types import SimpleNamespace\n", "filename": "./bot.py", "issue_confidence": "HIGH", "issue_severity": "LOW", "issue_text": "Consider possible security implications associated with PIPE module.", - "line_number": 12, + "line_number": 14, "line_range": [ - 12 + 14 ], "more_info": "https://bandit.readthedocs.io/en/latest/blacklists/blacklist_imports.html#b404-import-subprocess", "test_id": "B404", @@ -238,28 +226,28 @@ "test_name": "blacklist" }, { - "code": "13 from json import JSONDecodeError, loads\n14 from subprocess import PIPE\n15 from textwrap import indent\n", + "code": "11 from json import JSONDecodeError, loads\n12 from subprocess import PIPE\n13 from textwrap import indent\n", "filename": "./cogs/utility.py", "issue_confidence": "HIGH", "issue_severity": "LOW", "issue_text": "Consider possible security implications associated with PIPE module.", - "line_number": 14, + "line_number": 12, "line_range": [ - 14 + 12 ], "more_info": "https://bandit.readthedocs.io/en/latest/blacklists/blacklist_imports.html#b404-import-subprocess", "test_id": "B404", "test_name": "blacklist" }, { - "code": "2039 try:\n2040 exec(to_compile, env) # pylint: disable=exec-used\n2041 except Exception as exc:\n", + "code": "2060 try:\n2061 exec(to_compile, env) # pylint: disable=exec-used\n2062 except Exception as exc:\n", "filename": "./cogs/utility.py", "issue_confidence": "HIGH", "issue_severity": "MEDIUM", "issue_text": "Use of exec detected.", - "line_number": 2040, + "line_number": 2061, "line_range": [ - 2040 + 2061 ], "more_info": "https://bandit.readthedocs.io/en/latest/plugins/b102_exec_used.html", "test_id": "B102", @@ -280,7 +268,7 @@ "test_name": "blacklist" }, { - "code": "67 \n68 def __init__(self, bot, access_token: str = \"\", username: str = \"\", **kwargs):\n69 self.bot = bot\n70 self.session = bot.session\n71 self.headers: dict = None\n72 self.access_token = access_token\n73 self.username = username\n74 self.avatar_url: str = kwargs.pop(\"avatar_url\", \"\")\n75 self.url: str = kwargs.pop(\"url\", \"\")\n76 if self.access_token:\n77 self.headers = {\"Authorization\": \"token \" + str(access_token)}\n78 \n79 @property\n80 def BRANCH(self):\n", + "code": "67 \n68 def __init__(self, bot, access_token: str = \"\", username: str = \"\", **kwargs):\n69 self.bot = bot\n70 self.session = bot.session\n71 self.headers: Optional[dict] = None\n72 self.access_token = access_token\n73 self.username = username\n74 self.avatar_url: str = kwargs.pop(\"avatar_url\", \"\")\n75 self.url: str = kwargs.pop(\"url\", \"\")\n76 if self.access_token:\n77 self.headers = {\"Authorization\": \"token \" + str(access_token)}\n78 \n79 @property\n80 def BRANCH(self):\n", "filename": "./core/clients.py", "issue_confidence": "MEDIUM", "issue_severity": "LOW", From 126455760831a019283943fc00ca75334a475da0 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 01:25:45 +0800 Subject: [PATCH 023/225] Support PNG/APNG stickers --- CHANGELOG.md | 1 + core/thread.py | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe9ec8e3e1..4e4cd95bde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Certain cases where fallback categories were not working as intended. ([PR #3109](https://github.com/kyb3r/modmail/pull/3109)) - `?contact` would create in a random category in silent mode. ([GH #3091](https://github.com/kyb3r/modmail/issues/3091), [PR #3092](https://github.com/kyb3r/modmail/pull/3092)) - Certain cases where `?close` would fail if closer isn't in cache. ([GH #3104](https://github.com/kyb3r/modmail/issues/3104), [PR #3105](https://github.com/kyb3r/modmail/pull/3105)) +- Stickers were not working in Modmail. ### Internal diff --git a/core/thread.py b/core/thread.py index 2550ab0ad9..eb0a23cd2c 100644 --- a/core/thread.py +++ b/core/thread.py @@ -989,8 +989,8 @@ async def send( images.extend(image_urls) images.extend( ( - str(i.image_url) if isinstance(i.image_url, discord.Asset) else i.image_url, - f"{i.name} Sticker", + i.url if i.format in (discord.StickerFormatType.png, discord.StickerFormatType.apng) else None, + i.name, True, ) for i in message.stickers @@ -1012,10 +1012,10 @@ async def send( if filename: if is_sticker: if url is None: - description = "Unable to retrieve sticker image" + description = f"{filename}: Unable to retrieve sticker image" else: - description = "\u200b" - embed.add_field(name=filename, value=description) + description = f"[{filename}]({url})" + embed.add_field(name="Sticker", value=description) else: embed.add_field(name="Image", value=f"[{filename}]({url})") embedded_image = True From 0ee363f64394f4ce9ceecc9b162a78e83b30288f Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sat, 20 Nov 2021 19:28:50 +0200 Subject: [PATCH 024/225] Update baseline --- .bandit_baseline.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bandit_baseline.json b/.bandit_baseline.json index 12aa666e27..c36cbc9f8e 100644 --- a/.bandit_baseline.json +++ b/.bandit_baseline.json @@ -1,6 +1,6 @@ { "errors": [], - "generated_at": "2021-11-20T16:58:19Z", + "generated_at": "2021-11-20T17:28:26Z", "metrics": { "./bot.py": { "CONFIDENCE.HIGH": 1.0, From 9121dce1c49fa3f64bd6b7ceb6fbef48d99c1463 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 01:31:31 +0800 Subject: [PATCH 025/225] Disable bandit --- .github/workflows/lints.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 145a83d489..091e012dd9 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -23,8 +23,8 @@ jobs: run: | python -m pip install --upgrade pip pipenv pipenv install --dev --system - - name: Bandit syntax check - run: bandit -r . -b .bandit_baseline.json + # - name: Bandit syntax check + # run: bandit -r . -b .bandit_baseline.json - name: Pylint run: pylint ./bot.py cogs/*.py core/*.py --exit-zero -r y continue-on-error: true From 50446d4fa02ae72d62ef713ad1dd1d54f179e7b8 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 01:33:49 +0800 Subject: [PATCH 026/225] Resolve linting --- core/thread.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/thread.py b/core/thread.py index eb0a23cd2c..f7bf634435 100644 --- a/core/thread.py +++ b/core/thread.py @@ -989,7 +989,9 @@ async def send( images.extend(image_urls) images.extend( ( - i.url if i.format in (discord.StickerFormatType.png, discord.StickerFormatType.apng) else None, + i.url + if i.format in (discord.StickerFormatType.png, discord.StickerFormatType.apng) + else None, i.name, True, ) From f429c225ff5aeae5c05d41a5fa012848558602e5 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 01:40:35 +0800 Subject: [PATCH 027/225] Bump ver to 3.11.0-dev2 --- README.md | 2 +- bot.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 81cc75929c..cf62cfe5d6 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ <br> <a href="#"> - <img src="https://img.shields.io/badge/Latest%20Version-v3.11.0-dev1-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> + <img src="https://img.shields.io/badge/Latest%20Version-v3.11.0-dev2-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> </a> <br> diff --git a/bot.py b/bot.py index a0d4043b55..fbb6ec9605 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "3.11.0-dev1" +__version__ = "3.11.0-dev2" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 797650d754..f1de75c772 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '3.11.0-dev1' +version = '3.11.0-dev2' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From fb2e9046e677eea0c5a2a0f0f5bcdb423a349d6a Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 16:37:07 +0800 Subject: [PATCH 028/225] check for g.name==None #3088 --- CHANGELOG.md | 1 + bot.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e4cd95bde..75862c62da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `?contact` would create in a random category in silent mode. ([GH #3091](https://github.com/kyb3r/modmail/issues/3091), [PR #3092](https://github.com/kyb3r/modmail/pull/3092)) - Certain cases where `?close` would fail if closer isn't in cache. ([GH #3104](https://github.com/kyb3r/modmail/issues/3104), [PR #3105](https://github.com/kyb3r/modmail/pull/3105)) - Stickers were not working in Modmail. +- Large server sizes results in Guild.name == None. ([GH #3088](https://github.com/kyb3r/modmail/issues/3088)) ### Internal diff --git a/bot.py b/bot.py index fbb6ec9605..fb9836010f 100644 --- a/bot.py +++ b/bot.py @@ -618,7 +618,7 @@ async def on_ready(self): logger.warning( "The bot is in more servers other than the main and staff server. " "This may cause data compromise (%s).", - ", ".join(guild.name for guild in other_guilds), + ", ".join(str(guild.name) for guild in other_guilds), ) logger.warning("If the external servers are valid, you may ignore this message.") From 33adfc30f7c4b309b21a45a76854126f13db84e6 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 17:10:01 +0800 Subject: [PATCH 029/225] Fix attachments in plain messages #3102 --- CHANGELOG.md | 1 + bot.py | 4 ++++ core/thread.py | 24 +++++++++++++----------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75862c62da..18935f9f23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Certain cases where `?close` would fail if closer isn't in cache. ([GH #3104](https://github.com/kyb3r/modmail/issues/3104), [PR #3105](https://github.com/kyb3r/modmail/pull/3105)) - Stickers were not working in Modmail. - Large server sizes results in Guild.name == None. ([GH #3088](https://github.com/kyb3r/modmail/issues/3088)) +- Attachments did not work on plain replies. ([GH #3102](https://github.com/kyb3r/modmail/issues/3102)) ### Internal diff --git a/bot.py b/bot.py index fb9836010f..c2e3ee5adf 100644 --- a/bot.py +++ b/bot.py @@ -50,6 +50,10 @@ logger = getLogger(__name__) +# # prevent "coroutine noop was never awaited" warning. +# asyncio.coroutines._DEBUG = False # type: ignore + + temp_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "temp") if not os.path.exists(temp_dir): os.mkdir(temp_dir) diff --git a/core/thread.py b/core/thread.py index f7bf634435..ff2ea791cd 100644 --- a/core/thread.py +++ b/core/thread.py @@ -4,6 +4,7 @@ import re import time import typing +import warnings from datetime import timedelta from types import SimpleNamespace @@ -835,6 +836,7 @@ async def reply( user_msg = await asyncio.gather(*user_msg_tasks) except Exception as e: logger.error("Message delivery failed:", exc_info=True) + user_msg = None if isinstance(e, discord.Forbidden): description = ( "Your message could not be delivered as " @@ -848,12 +850,10 @@ async def reply( "to an unknown error. Check `?debug` for " "more information" ) - tasks.append( - message.channel.send( - embed=discord.Embed( - color=self.bot.error_color, - description=description, - ) + msg = await message.channel.send( + embed=discord.Embed( + color=self.bot.error_color, + description=description, ) ) else: @@ -1095,17 +1095,19 @@ async def send( if plain: if from_mod and not isinstance(destination, discord.TextChannel): # Plain to user + with warnings.catch_warnings(): + # Catch coroutines not awaited warning + warnings.simplefilter("ignore") + additional_images = [] + if embed.footer.text: plain_message = f"**({embed.footer.text}) " else: plain_message = "**" plain_message += f"{embed.author.name}:** {embed.description}" files = [] - for i in embed.fields: - if "Image" in i.name: - async with self.bot.session.get(i.field[i.field.find("http") : -1]) as resp: - stream = io.BytesIO(await resp.read()) - files.append(discord.File(stream)) + for i in message.attachments: + files.append(await i.to_file()) msg = await destination.send(plain_message, files=files) else: From 2f762025d07c26092e90a2e4f5e45e5d6900364d Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 18:49:41 +0800 Subject: [PATCH 030/225] Support LOTTIE images, resolves #3119 --- CHANGELOG.md | 1 + Pipfile | 1 + Pipfile.lock | 167 +++++++++++++++++++++++++++++++++++++++++++++- README.md | 2 +- bot.py | 11 ++- core/changelog.py | 1 + core/thread.py | 58 +++++++++++++--- 7 files changed, 226 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18935f9f23..5db8a4b950 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Stickers were not working in Modmail. - Large server sizes results in Guild.name == None. ([GH #3088](https://github.com/kyb3r/modmail/issues/3088)) - Attachments did not work on plain replies. ([GH #3102](https://github.com/kyb3r/modmail/issues/3102)) +- Support LOTTIE stickers. ([GH #3119](https://github.com/kyb3r/modmail/issues/3119)) ### Internal diff --git a/Pipfile b/Pipfile index 51569d26e5..a78db95d18 100644 --- a/Pipfile +++ b/Pipfile @@ -21,6 +21,7 @@ pymongo = {extras = ["srv"], version = "*"} # Required by motor python-dateutil = "~=2.8.1" python-dotenv = "~=0.18.0" uvloop = {version = ">=0.15.2", markers = "sys_platform != 'win32'"} +lottie = {version = "==0.6.10", extras = ["pdf"]} [scripts] bot = "python bot.py" diff --git a/Pipfile.lock b/Pipfile.lock index e1a77d86b5..1fa9e5e64a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "aaa53487befe4f19feda64131fbc5bde140c1ec1a59ff2656d2ad1da2c50b390" + "sha256": "29d6f377cdb874102deb4df1406ff6d0a66834fcb89660f3c9599a2343cda038" }, "pipfile-spec": 6, "requires": { @@ -75,6 +75,76 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==21.2.0" }, + "cairocffi": { + "hashes": [ + "sha256:108a3a7cb09e203bdd8501d9baad91d786d204561bd71e9364e8b34897c47b91" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0" + }, + "cairosvg": { + "hashes": [ + "sha256:98c276b7e4f0caf01e5c7176765c104ffa1aa1461d63b2053b04ab663cf7052b", + "sha256:b0b9929cf5dba005178d746a8036fcf0025550f498ca54db61873322384783bc" + ], + "markers": "python_version >= '3.5'", + "version": "==2.5.2" + }, + "cffi": { + "hashes": [ + "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3", + "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2", + "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636", + "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20", + "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728", + "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27", + "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66", + "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443", + "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0", + "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7", + "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39", + "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605", + "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a", + "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37", + "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029", + "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139", + "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc", + "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df", + "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14", + "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880", + "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2", + "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a", + "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e", + "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474", + "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024", + "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8", + "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0", + "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e", + "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a", + "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e", + "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032", + "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6", + "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e", + "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b", + "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e", + "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954", + "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962", + "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c", + "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4", + "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55", + "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962", + "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023", + "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c", + "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6", + "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8", + "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382", + "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7", + "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc", + "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997", + "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796" + ], + "version": "==1.15.0" + }, "chardet": { "hashes": [ "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", @@ -91,6 +161,22 @@ "index": "pypi", "version": "==0.4.4" }, + "cssselect2": { + "hashes": [ + "sha256:2f4a9f20965367bae459e3bb42561f7927e0cfe5b7ea1692757cf67ef5d7dace", + "sha256:93fbb9af860e95dd40bf18c3b2b6ed99189a07c0f29ba76f9c5be71344664ec8" + ], + "markers": "python_version >= '3.6'", + "version": "==0.4.1" + }, + "defusedxml": { + "hashes": [ + "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", + "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.7.1" + }, "discord-py": { "git": "https://github.com/Rapptz/discord.py.git", "ref": "45d498c1b76deaf3b394d17ccf56112fa691d160" @@ -131,6 +217,16 @@ "index": "pypi", "version": "==0.6.0" }, + "lottie": { + "extras": [ + "pdf" + ], + "hashes": [ + "sha256:d3281d09a8db94da49f60267123b9e0473e3a51c282da2d5e61908d33843f1cc" + ], + "index": "pypi", + "version": "==0.6.10" + }, "motor": { "hashes": [ "sha256:1196db507142ef8f00d953efa2f37b39335ef2d72af6ce4fbccfd870b65c5e9f", @@ -232,6 +328,60 @@ "index": "pypi", "version": "==2.6" }, + "pillow": { + "hashes": [ + "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76", + "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585", + "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b", + "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8", + "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55", + "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc", + "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645", + "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff", + "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc", + "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b", + "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6", + "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20", + "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e", + "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a", + "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779", + "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02", + "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39", + "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f", + "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a", + "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409", + "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c", + "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488", + "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b", + "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d", + "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09", + "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b", + "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153", + "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9", + "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad", + "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df", + "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df", + "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed", + "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed", + "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698", + "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29", + "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649", + "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49", + "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b", + "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2", + "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a", + "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78" + ], + "markers": "python_version >= '3.6'", + "version": "==8.4.0" + }, + "pycparser": { + "hashes": [ + "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", + "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" + ], + "version": "==2.21" + }, "pymongo": { "extras": [ "srv" @@ -372,6 +522,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, + "tinycss2": { + "hashes": [ + "sha256:0353b5234bcaee7b1ac7ca3dea7e02cd338a9f8dcbb8f2dcd32a5795ec1e5f9a", + "sha256:fbdcac3044d60eb85fdb2aa840ece43cf7dbe798e373e6ee0be545d4d134e18a" + ], + "markers": "python_version >= '3.6'", + "version": "==1.1.0" + }, "typing-extensions": { "hashes": [ "sha256:2cdf80e4e04866a9b3689a51869016d36db0814d84b8d8a568d22781d45d27ed", @@ -402,6 +560,13 @@ "markers": "sys_platform != 'win32'", "version": "==0.16.0" }, + "webencodings": { + "hashes": [ + "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", + "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" + ], + "version": "==0.5.1" + }, "yarl": { "hashes": [ "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac", diff --git a/README.md b/README.md index cf62cfe5d6..7492a53116 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ <br> <a href="#"> - <img src="https://img.shields.io/badge/Latest%20Version-v3.11.0-dev2-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> + <img src="https://img.shields.io/badge/Latest%20Version-v3.11.0-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> </a> <br> diff --git a/bot.py b/bot.py index c2e3ee5adf..38bd6423b2 100644 --- a/bot.py +++ b/bot.py @@ -50,9 +50,6 @@ logger = getLogger(__name__) -# # prevent "coroutine noop was never awaited" warning. -# asyncio.coroutines._DEBUG = False # type: ignore - temp_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "temp") if not os.path.exists(temp_dir): @@ -1691,6 +1688,14 @@ def main(): except ImportError: pass + try: + import cairosvg + except OSError: + logger.error( + "Unable to import cairosvg, install GTK Installer for Windows: https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer/releases/latest" + ) + sys.exit(0) + # check discord version if discord.__version__ != "2.0.0a": logger.error( diff --git a/core/changelog.py b/core/changelog.py index 4ede9f09f1..a4f88ed323 100644 --- a/core/changelog.py +++ b/core/changelog.py @@ -97,6 +97,7 @@ def embed(self) -> Embed: for name, value in self.fields.items(): embed.add_field(name=name, value=truncate(value, 1024), inline=False) embed.set_footer(text=f"Current version: v{self.bot.version}") + embed.set_thumbnail(url=self.bot.user.display_avatar.url) return embed diff --git a/core/thread.py b/core/thread.py index ff2ea791cd..09f8bd3d41 100644 --- a/core/thread.py +++ b/core/thread.py @@ -1,8 +1,11 @@ import asyncio +import base64 import copy +import functools import io import re import time +import traceback import typing import warnings from datetime import timedelta @@ -12,6 +15,8 @@ import discord from discord.ext.commands import MissingRequiredArgument, CommandError +from lottie.importers import importers as l_importers +from lottie.exporters import exporters as l_exporters from core.models import DMDisabled, DummyMessage, getLogger from core.time import human_timedelta @@ -987,16 +992,49 @@ async def send( if is_image_url(url, convert_size=False) ] images.extend(image_urls) - images.extend( - ( - i.url - if i.format in (discord.StickerFormatType.png, discord.StickerFormatType.apng) - else None, - i.name, - True, - ) - for i in message.stickers - ) + + def lottie_to_png(data): + importer = l_importers.get("lottie") + exporter = l_exporters.get("png") + with io.BytesIO() as stream: + stream.write(data) + stream.seek(0) + an = importer.process(stream) + + with io.BytesIO() as stream: + exporter.process(an, stream) + stream.seek(0) + return stream.read() + + for i in message.stickers: + if i.format in (discord.StickerFormatType.png, discord.StickerFormatType.apng): + images.append((i.url, i.name, True)) + elif i.format == discord.StickerFormatType.lottie: + # save the json lottie representation + try: + async with self.bot.session.get(i.url) as resp: + data = await resp.read() + + # convert to a png + img_data = await self.bot.loop.run_in_executor(None, functools.partial(lottie_to_png, data)) + b64_data = base64.b64encode(img_data).decode() + + # upload to imgur + async with self.bot.session.post( + "https://api.imgur.com/3/image", + headers={"Authorization": "Client-ID 50e96145ac5e085"}, + data={"image": b64_data}, + ) as resp: + result = await resp.json() + url = result["data"]["link"] + + except Exception: + traceback.print_exc() + images.append((None, i.name, True)) + else: + images.append((url, i.name, True)) + else: + images.append((None, i.name, True)) embedded_image = False From 0de26a3e0cd4dd20e36a4b5df70076e4b38bd5d8 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 18:51:36 +0800 Subject: [PATCH 031/225] Bump version to 3.11-dev3 --- bot.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index 38bd6423b2..b3364ad1f1 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "3.11.0-dev2" +__version__ = "3.11.0-dev3" import asyncio diff --git a/pyproject.toml b/pyproject.toml index f1de75c772..1e1a13f5c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '3.11.0-dev2' +version = '3.11.0-dev3' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 8d76a3279ef70c06afc3743c5b53922664a2c0f4 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 18:55:18 +0800 Subject: [PATCH 032/225] Fix editing notes, resolve #3094 --- CHANGELOG.md | 1 + core/thread.py | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5db8a4b950..aa0a6d3121 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Large server sizes results in Guild.name == None. ([GH #3088](https://github.com/kyb3r/modmail/issues/3088)) - Attachments did not work on plain replies. ([GH #3102](https://github.com/kyb3r/modmail/issues/3102)) - Support LOTTIE stickers. ([GH #3119](https://github.com/kyb3r/modmail/issues/3119)) +- Editing notes now work. ([GH #3094](https://github.com/kyb3r/modmail/issues/3094)) ### Internal diff --git a/core/thread.py b/core/thread.py index 09f8bd3d41..5209b1b615 100644 --- a/core/thread.py +++ b/core/thread.py @@ -677,13 +677,14 @@ async def edit_message(self, message_id: typing.Optional[int], message: str) -> embed1.description = message tasks = [self.bot.api.edit_message(message1.id, message), message1.edit(embed=embed1)] - if message2 is not [None]: - for m2 in message2: - embed2 = m2.embeds[0] - embed2.description = message - tasks += [m2.edit(embed=embed2)] - elif message1.embeds[0].author.name.startswith("Persistent Note"): + if message1.embeds[0].author.name.startswith("Persistent Note"): tasks += [self.bot.api.edit_note(message1.id, message)] + else: + for m2 in message2: + if m2 is not None: + embed2 = m2.embeds[0] + embed2.description = message + tasks += [m2.edit(embed=embed2)] await asyncio.gather(*tasks) From 8e4d4b033a8fc6b3eff08d583f065662549d39ab Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 19:12:15 +0800 Subject: [PATCH 033/225] Test potential fix for addusers #3090 --- cogs/modmail.py | 33 +++++++++++++++++++++++++-------- core/thread.py | 8 +++++--- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index 60c18594ac..7080a7bdf5 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1,4 +1,5 @@ import asyncio +from asyncio import tasks import re from datetime import datetime from itertools import zip_longest @@ -735,6 +736,7 @@ async def adduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, str ctx.command.reset_cooldown(ctx) return + tasks = [] if not silent: description = self.bot.formatter.format( self.bot.config["private_added_to_group_response"], moderator=ctx.author @@ -748,7 +750,7 @@ async def adduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, str em.timestamp = discord.utils.utcnow() em.set_footer(text=str(ctx.author), icon_url=ctx.author.display_avatar.url) for u in users: - await u.send(embed=em) + tasks.append(u.send(embed=em)) description = self.bot.formatter.format( self.bot.config["public_added_to_group_response"], @@ -766,9 +768,12 @@ async def adduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, str for i in ctx.thread.recipients: if i not in users: - await i.send(embed=em) + tasks.append(i.send(embed=em)) await ctx.thread.add_users(users) + if tasks: + await asyncio.gather(*tasks) + sent_emoji, _ = await self.bot.retrieve_emoji() await self.bot.add_reaction(ctx.message, sent_emoji) @@ -824,6 +829,7 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role, ctx.command.reset_cooldown(ctx) return + tasks = [] if not silent: description = self.bot.formatter.format( self.bot.config["private_removed_from_group_response"], moderator=ctx.author @@ -837,7 +843,7 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role, em.timestamp = discord.utils.utcnow() em.set_footer(text=str(ctx.author), icon_url=ctx.author.display_avatar.url) for u in users: - await u.send(embed=em) + tasks.append(u.send(embed=em)) description = self.bot.formatter.format( self.bot.config["public_removed_from_group_response"], @@ -855,9 +861,12 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role, for i in ctx.thread.recipients: if i not in users: - await i.send(embed=em) + tasks.append(i.send(embed=em)) await ctx.thread.remove_users(users) + if tasks: + await asyncio.gather(*tasks) + sent_emoji, _ = await self.bot.retrieve_emoji() await self.bot.add_reaction(ctx.message, sent_emoji) @@ -907,6 +916,7 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, ctx.command.reset_cooldown(ctx) return + tasks = [] if not silent: em = discord.Embed( title=self.bot.config["private_added_to_group_title"], @@ -928,7 +938,7 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, em.set_footer(text=name, icon_url=avatar_url) for u in users: - await u.send(embed=em) + tasks.append(u.send(embed=em)) description = self.bot.formatter.format( self.bot.config["public_added_to_group_description_anon"], @@ -945,9 +955,12 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, for i in ctx.thread.recipients: if i not in users: - await i.send(embed=em) + tasks.append(i.send(embed=em)) await ctx.thread.add_users(users) + if tasks: + await asyncio.gather(*tasks) + sent_emoji, _ = await self.bot.retrieve_emoji() await self.bot.add_reaction(ctx.message, sent_emoji) @@ -992,6 +1005,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro ctx.command.reset_cooldown(ctx) return + tasks = [] if not silent: em = discord.Embed( title=self.bot.config["private_removed_from_group_title"], @@ -1013,7 +1027,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro em.set_footer(text=name, icon_url=avatar_url) for u in users: - await u.send(embed=em) + tasks.append(u.send(embed=em)) description = self.bot.formatter.format( self.bot.config["public_removed_from_group_description_anon"], @@ -1030,9 +1044,12 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro for i in ctx.thread.recipients: if i not in users: - await i.send(embed=em) + tasks.append(i.send(embed=em)) await ctx.thread.remove_users(users) + if tasks: + await asyncio.gather(*tasks) + sent_emoji, _ = await self.bot.retrieve_emoji() await self.bot.add_reaction(ctx.message, sent_emoji) diff --git a/core/thread.py b/core/thread.py index 5209b1b615..4aea00734e 100644 --- a/core/thread.py +++ b/core/thread.py @@ -1203,7 +1203,7 @@ async def _update_users_genesis(self): embed.add_field(name="Other Recipients", value=value, inline=False) else: if value: - embed.set_field_at(index, value=value) + embed.set_field_at(index, name="Other Recipients", value=value, inline=False) else: embed.remove_field(index) @@ -1211,13 +1211,15 @@ async def _update_users_genesis(self): async def add_users(self, users: typing.List[typing.Union[discord.Member, discord.User]]) -> None: topic = "" - title, user_id, _ = parse_channel_topic(self.channel.topic) + title, _, _ = parse_channel_topic(self.channel.topic) if title is not None: topic += f"Title: {title}\n" - topic += f"User ID: {user_id}" + topic += f"User ID: {self._id}" self._other_recipients += users + self._other_recipients = list(set(self._other_recipients)) + ids = ",".join(str(i.id) for i in self._other_recipients) topic += f"\nOther Recipients: {ids}" From a89a3fe593011fab26557daf6350f79175a7fdf8 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 19:19:10 +0800 Subject: [PATCH 034/225] Update changelog --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa0a6d3121..9613ba44c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,13 +10,17 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Breaking -- Upgraded to discord.py v2.0 master ([internal changes](https://gist.github.com/apple502j/f75b4f24652f04de85c7084ffd73ec58)). +- Upgraded to discord.py v2.0 master ([internal changes](https://gist.github.com/apple502j/f75b4f24652f04de85c7084ffd73ec58), [GH #2990](https://github.com/kyb3r/modmail/issues/2990)). - Python 3.8 or higher is required. ### Added - `use_hoisted_top_role` config to use change how default mod tags work, see `v3.10.0#Added` for details. ([PR #3093](https://github.com/kyb3r/modmail/pull/3093)) +### Improved + +- Modmail now uses per-server avatars if applicable. ([GH #3048](https://github.com/kyb3r/modmail/issues/3048)) + ### Fixed - Several minor typos. ([PR #3095](https://github.com/kyb3r/modmail/pull/3095), [PR #3116](https://github.com/kyb3r/modmail/pull/3116)) @@ -31,7 +35,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Internal -- Improve regex parsing of channel topics. ([PR #3111](https://github.com/kyb3r/modmail/pull/3111)) +- Improve regex parsing of channel topics. ([GH #3114](https://github.com/kyb3r/modmail/issues/3114), [PR #3111](https://github.com/kyb3r/modmail/pull/3111)) - Add warning if deploying on a developmental version. # v3.10.3 From 1444c1d97444e4c3cc4a6caa01c5d35e2be7a1df Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 19:19:47 +0800 Subject: [PATCH 035/225] Formatting --- core/thread.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/thread.py b/core/thread.py index 4aea00734e..145864e815 100644 --- a/core/thread.py +++ b/core/thread.py @@ -1017,7 +1017,9 @@ def lottie_to_png(data): data = await resp.read() # convert to a png - img_data = await self.bot.loop.run_in_executor(None, functools.partial(lottie_to_png, data)) + img_data = await self.bot.loop.run_in_executor( + None, functools.partial(lottie_to_png, data) + ) b64_data = base64.b64encode(img_data).decode() # upload to imgur From 13a22cf003333acfb61bbadd7f81b0a711c89a79 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 21:49:26 +0800 Subject: [PATCH 036/225] require_close_reason config, resolves #3107 --- CHANGELOG.md | 5 +++-- bot.py | 2 +- cogs/modmail.py | 3 +++ core/config.py | 2 ++ core/config_help.json | 8 ++++++++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9613ba44c4..ff96521f8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Added - `use_hoisted_top_role` config to use change how default mod tags work, see `v3.10.0#Added` for details. ([PR #3093](https://github.com/kyb3r/modmail/pull/3093)) +- `require_close_reason` to require a reason to close a thread. ([GH #3107](https://github.com/kyb3r/modmail/issues/3107)) ### Improved @@ -27,9 +28,9 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Certain cases where fallback categories were not working as intended. ([PR #3109](https://github.com/kyb3r/modmail/pull/3109)) - `?contact` would create in a random category in silent mode. ([GH #3091](https://github.com/kyb3r/modmail/issues/3091), [PR #3092](https://github.com/kyb3r/modmail/pull/3092)) - Certain cases where `?close` would fail if closer isn't in cache. ([GH #3104](https://github.com/kyb3r/modmail/issues/3104), [PR #3105](https://github.com/kyb3r/modmail/pull/3105)) -- Stickers were not working in Modmail. +- Stickers now work in Modmail. - Large server sizes results in Guild.name == None. ([GH #3088](https://github.com/kyb3r/modmail/issues/3088)) -- Attachments did not work on plain replies. ([GH #3102](https://github.com/kyb3r/modmail/issues/3102)) +- Attachments now work on plain replies. ([GH #3102](https://github.com/kyb3r/modmail/issues/3102)) - Support LOTTIE stickers. ([GH #3119](https://github.com/kyb3r/modmail/issues/3119)) - Editing notes now work. ([GH #3094](https://github.com/kyb3r/modmail/issues/3094)) diff --git a/bot.py b/bot.py index b3364ad1f1..38bd6423b2 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "3.11.0-dev3" +__version__ = "3.11.0-dev2" import asyncio diff --git a/cogs/modmail.py b/cogs/modmail.py index 7080a7bdf5..5871f76fb6 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -419,6 +419,9 @@ async def close(self, ctx, *, after: UserFriendlyTime = None): return await ctx.send(embed=embed) + if self.bot.config["require_close_reason"] and message is None: + raise commands.BadArgument("Provide a reason for closing the thread.") + if after and after.dt > now: await self.send_scheduled_close_message(ctx, after, silent) diff --git a/core/config.py b/core/config.py index e9de7d516d..d06443a6a3 100644 --- a/core/config.py +++ b/core/config.py @@ -91,6 +91,7 @@ class ConfigManager: "silent_alert_on_mention": False, "show_timestamp": True, "anonymous_snippets": False, + "require_close_reason": False, # group conversations "private_added_to_group_title": "New Thread (Group)", "private_added_to_group_response": "{moderator.name} has added you to a Modmail thread.", @@ -206,6 +207,7 @@ class ConfigManager: "update_notifications", "thread_contact_silently", "anonymous_snippets", + "require_close_reason", "recipient_thread_close", "thread_show_roles", "thread_show_account_age", diff --git a/core/config_help.json b/core/config_help.json index 04f177cd97..ee03aca24a 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -797,6 +797,14 @@ "See also: `anon_avatar_url`, `anon_tag`." ] }, + "require_close_reason": { + "default" : "No", + "description": "Require a reason to close threads.", + "examples": [ + "`{prefix}config set require_close_reason yes`" + ], + "notes": [] + }, "private_added_to_group_title": { "default": "New Thread (Group)", "description": "This is the message embed title sent to the recipient that is just added to a thread.", From e44fb12e90dbb5974a7e9d066a68d0d39d6e023c Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 21:58:17 +0800 Subject: [PATCH 037/225] plain_snippets, ?fpareply and ?fpreply, resolves #3083 --- CHANGELOG.md | 4 +- bot.py | 8 ++-- cogs/modmail.py | 85 ++++++++++++++++++++++++++++++++----------- core/config.py | 2 + core/config_help.json | 12 +++++- 5 files changed, 85 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff96521f8d..42a1744d12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,9 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Added - `use_hoisted_top_role` config to use change how default mod tags work, see `v3.10.0#Added` for details. ([PR #3093](https://github.com/kyb3r/modmail/pull/3093)) -- `require_close_reason` to require a reason to close a thread. ([GH #3107](https://github.com/kyb3r/modmail/issues/3107)) +- `require_close_reason` config to require a reason to close a thread. ([GH #3107](https://github.com/kyb3r/modmail/issues/3107)) +- `plain_snippets` config to force all snippets to be plain. ([GH #3083](https://github.com/kyb3r/modmail/issues/3083)) +- `?fpareply` and `?fpreply` to reply to messages with variables plainly. ### Improved diff --git a/bot.py b/bot.py index 38bd6423b2..fcdf8011aa 100644 --- a/bot.py +++ b/bot.py @@ -1144,10 +1144,12 @@ async def process_commands(self, message): cmd = cmd.lower() if cmd in self.snippets: snippet = self.snippets[cmd] + modifiers = "f" + if self.config["plain_snippets"]: + modifiers += "p" if self.config["anonymous_snippets"]: - message.content = f"{self.prefix}fareply {snippet}" - else: - message.content = f"{self.prefix}freply {snippet}" + modifiers += "a" + message.content = f"{self.prefix}{modifiers}reply {snippet}" ctxs = await self.get_contexts(message) for ctx in ctxs: diff --git a/cogs/modmail.py b/cogs/modmail.py index 5871f76fb6..c17b580370 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1,5 +1,4 @@ import asyncio -from asyncio import tasks import re from datetime import datetime from itertools import zip_longest @@ -739,7 +738,7 @@ async def adduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, str ctx.command.reset_cooldown(ctx) return - tasks = [] + to_exec = [] if not silent: description = self.bot.formatter.format( self.bot.config["private_added_to_group_response"], moderator=ctx.author @@ -753,7 +752,7 @@ async def adduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, str em.timestamp = discord.utils.utcnow() em.set_footer(text=str(ctx.author), icon_url=ctx.author.display_avatar.url) for u in users: - tasks.append(u.send(embed=em)) + to_exec.append(u.send(embed=em)) description = self.bot.formatter.format( self.bot.config["public_added_to_group_response"], @@ -771,11 +770,11 @@ async def adduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, str for i in ctx.thread.recipients: if i not in users: - tasks.append(i.send(embed=em)) + to_exec.append(i.send(embed=em)) await ctx.thread.add_users(users) - if tasks: - await asyncio.gather(*tasks) + if to_exec: + await asyncio.gather(*to_exec) sent_emoji, _ = await self.bot.retrieve_emoji() await self.bot.add_reaction(ctx.message, sent_emoji) @@ -832,7 +831,7 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role, ctx.command.reset_cooldown(ctx) return - tasks = [] + to_exec = [] if not silent: description = self.bot.formatter.format( self.bot.config["private_removed_from_group_response"], moderator=ctx.author @@ -846,7 +845,7 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role, em.timestamp = discord.utils.utcnow() em.set_footer(text=str(ctx.author), icon_url=ctx.author.display_avatar.url) for u in users: - tasks.append(u.send(embed=em)) + to_exec.append(u.send(embed=em)) description = self.bot.formatter.format( self.bot.config["public_removed_from_group_response"], @@ -864,11 +863,11 @@ async def removeuser(self, ctx, *users_arg: Union[discord.Member, discord.Role, for i in ctx.thread.recipients: if i not in users: - tasks.append(i.send(embed=em)) + to_exec.append(i.send(embed=em)) await ctx.thread.remove_users(users) - if tasks: - await asyncio.gather(*tasks) + if to_exec: + await asyncio.gather(*to_exec) sent_emoji, _ = await self.bot.retrieve_emoji() await self.bot.add_reaction(ctx.message, sent_emoji) @@ -919,7 +918,7 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, ctx.command.reset_cooldown(ctx) return - tasks = [] + to_exec = [] if not silent: em = discord.Embed( title=self.bot.config["private_added_to_group_title"], @@ -941,7 +940,7 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, em.set_footer(text=name, icon_url=avatar_url) for u in users: - tasks.append(u.send(embed=em)) + to_exec.append(u.send(embed=em)) description = self.bot.formatter.format( self.bot.config["public_added_to_group_description_anon"], @@ -958,11 +957,11 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, for i in ctx.thread.recipients: if i not in users: - tasks.append(i.send(embed=em)) + to_exec.append(i.send(embed=em)) await ctx.thread.add_users(users) - if tasks: - await asyncio.gather(*tasks) + if to_exec: + await asyncio.gather(*to_exec) sent_emoji, _ = await self.bot.retrieve_emoji() await self.bot.add_reaction(ctx.message, sent_emoji) @@ -1008,7 +1007,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro ctx.command.reset_cooldown(ctx) return - tasks = [] + to_exec = [] if not silent: em = discord.Embed( title=self.bot.config["private_removed_from_group_title"], @@ -1030,7 +1029,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro em.set_footer(text=name, icon_url=avatar_url) for u in users: - tasks.append(u.send(embed=em)) + to_exec.append(u.send(embed=em)) description = self.bot.formatter.format( self.bot.config["public_removed_from_group_description_anon"], @@ -1047,11 +1046,11 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro for i in ctx.thread.recipients: if i not in users: - tasks.append(i.send(embed=em)) + to_exec.append(i.send(embed=em)) await ctx.thread.remove_users(users) - if tasks: - await asyncio.gather(*tasks) + if to_exec: + await asyncio.gather(*to_exec) sent_emoji, _ = await self.bot.retrieve_emoji() await self.bot.add_reaction(ctx.message, sent_emoji) @@ -1253,6 +1252,50 @@ async def fareply(self, ctx, *, msg: str = ""): async with ctx.typing(): await ctx.thread.reply(ctx.message, anonymous=True) + @commands.command(aliases=["formatplainreply"]) + @checks.has_permissions(PermissionLevel.SUPPORTER) + @checks.thread_only() + async def fpreply(self, ctx, *, msg: str = ""): + """ + Reply to a Modmail thread with variables and a plain message. + + Works just like `{prefix}areply`, however with the addition of three variables: + - `{{channel}}` - the `discord.TextChannel` object + - `{{recipient}}` - the `discord.User` object of the recipient + - `{{author}}` - the `discord.User` object of the author + + Supports attachments and images as well as + automatically embedding image URLs. + """ + msg = self.bot.formatter.format( + msg, channel=ctx.channel, recipient=ctx.thread.recipient, author=ctx.message.author + ) + ctx.message.content = msg + async with ctx.typing(): + await ctx.thread.reply(ctx.message, plain=True) + + @commands.command(aliases=["formatplainanonreply"]) + @checks.has_permissions(PermissionLevel.SUPPORTER) + @checks.thread_only() + async def fpareply(self, ctx, *, msg: str = ""): + """ + Anonymously reply to a Modmail thread with variables and a plain message. + + Works just like `{prefix}areply`, however with the addition of three variables: + - `{{channel}}` - the `discord.TextChannel` object + - `{{recipient}}` - the `discord.User` object of the recipient + - `{{author}}` - the `discord.User` object of the author + + Supports attachments and images as well as + automatically embedding image URLs. + """ + msg = self.bot.formatter.format( + msg, channel=ctx.channel, recipient=ctx.thread.recipient, author=ctx.message.author + ) + ctx.message.content = msg + async with ctx.typing(): + await ctx.thread.reply(ctx.message, anonymous=True, plain=True) + @commands.command(aliases=["anonreply", "anonymousreply"]) @checks.has_permissions(PermissionLevel.SUPPORTER) @checks.thread_only() diff --git a/core/config.py b/core/config.py index d06443a6a3..4af16e8272 100644 --- a/core/config.py +++ b/core/config.py @@ -91,6 +91,7 @@ class ConfigManager: "silent_alert_on_mention": False, "show_timestamp": True, "anonymous_snippets": False, + "plain_snippets": False, "require_close_reason": False, # group conversations "private_added_to_group_title": "New Thread (Group)", @@ -207,6 +208,7 @@ class ConfigManager: "update_notifications", "thread_contact_silently", "anonymous_snippets", + "plain_snippets", "require_close_reason", "recipient_thread_close", "thread_show_roles", diff --git a/core/config_help.json b/core/config_help.json index ee03aca24a..c31be337d6 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -794,7 +794,17 @@ "`{prefix}config set anonymous_snippets yes`" ], "notes": [ - "See also: `anon_avatar_url`, `anon_tag`." + "See also: `anon_avatar_url`, `anon_tag`, `plain_snippets`." + ] + }, + "plain_snippets": { + "default": "No", + "description": "Sends snippets with a plain interface.", + "examples":[ + "`{prefix}config set plain_snippets yes`" + ], + "notes": [ + "See also: `anonymous_snippets`." ] }, "require_close_reason": { From ec8fb29f7553f9961495b1fe36e09ec0e38429b9 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 22:08:33 +0800 Subject: [PATCH 038/225] use_nickname_channel_name, resolves #3112 --- CHANGELOG.md | 1 + bot.py | 9 +++++++-- core/config.py | 2 ++ core/config_help.json | 21 +++++++++++++++++---- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42a1744d12..4744e57bba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `require_close_reason` config to require a reason to close a thread. ([GH #3107](https://github.com/kyb3r/modmail/issues/3107)) - `plain_snippets` config to force all snippets to be plain. ([GH #3083](https://github.com/kyb3r/modmail/issues/3083)) - `?fpareply` and `?fpreply` to reply to messages with variables plainly. +- `use_nickname_channel_name` config to use nicknames instead of usernames for channel names. ([GH #3112](https://github.com/kyb3r/modmail/issues/3112)) ### Improved diff --git a/bot.py b/bot.py index fcdf8011aa..dcd447eed4 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "3.11.0-dev2" +__version__ = "3.11.0-dev3" import asyncio @@ -1663,7 +1663,12 @@ def format_channel_name(self, author, exclude_channel=None, force_null=False): elif self.config["use_timestamp_channel_name"]: name = new_name = author.created_at.isoformat(sep="-", timespec="minutes") else: - name = author.name.lower() + if self.config["use_nickname_channel_name"]: + author_member = self.guild.get_member(author.id) + name = author_member.display_name.lower() + else: + name = author.name.lower() + if force_null: name = "null" diff --git a/core/config.py b/core/config.py index 4af16e8272..6d2a2eb1cd 100644 --- a/core/config.py +++ b/core/config.py @@ -52,6 +52,7 @@ class ConfigManager: "close_emoji": "\N{LOCK}", "use_user_id_channel_name": False, "use_timestamp_channel_name": False, + "use_nickname_channel_name": False, "recipient_thread_close": False, "thread_show_roles": True, "thread_show_account_age": True, @@ -184,6 +185,7 @@ class ConfigManager: booleans = { "use_user_id_channel_name", "use_timestamp_channel_name", + "use_nickname_channel_name", "user_typing", "mod_typing", "reply_without_command", diff --git a/core/config_help.json b/core/config_help.json index c31be337d6..53d1d4daec 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -106,8 +106,8 @@ ], "notes": [ "This config is suitable for servers in Server Discovery to comply with channel name restrictions.", - "This cannot be applied with `use_timestamp_channel_name`.", - "See also: `use_timestamp_channel_name`." + "This cannot be applied with `use_timestamp_channel_name` or `use_nickname_channel_name`.", + "See also: `use_timestamp_channel_name`, `use_nickname_channel_name`." ] }, "use_timestamp_channel_name": { @@ -119,8 +119,21 @@ ], "notes": [ "This config is suitable for servers in Server Discovery to comply with channel name restrictions.", - "This cannot be applied with `use_user_id_channel_name`.", - "See also: `use_user_id_channel_name`." + "This cannot be applied with `use_user_id_channel_name` or `use_nickname_channel_name`.", + "See also: `use_user_id_channel_name`, `use_nickname_channel_name`." + ] + }, + "use_nickname_channel_name": { + "default": "No", + "description": "When this is set to `yes`, new thread channels will be named with the recipient's nickname instead of the recipient's name.", + "examples": [ + "`{prefix}config set use_nickname_channel_name yes`", + "`{prefix}config set use_nickname_channel_name no`" + ], + "notes": [ + "This config is suitable for servers in Server Discovery to comply with channel name restrictions.", + "This cannot be applied with `use_timestamp_channel_name` or `use_user_id_channel_name`.", + "See also: `use_timestamp_channel_name`, `use_user_id_channel_name`." ] }, "mod_typing": { From d741738e1e71ed8b047bfe96502308d95119d851 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 22:29:45 +0800 Subject: [PATCH 039/225] Use discord relative timedeltas, resolves #3046 --- CHANGELOG.md | 1 + bot.py | 4 +-- cogs/modmail.py | 9 +++--- core/config.py | 2 +- core/config_help.json | 2 +- core/thread.py | 2 +- core/time.py | 66 +++++++++++++++++++++++-------------------- 7 files changed, 45 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4744e57bba..2ef596f888 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Improved - Modmail now uses per-server avatars if applicable. ([GH #3048](https://github.com/kyb3r/modmail/issues/3048)) +- Use discord relative timedeltas. ([GH #3046](https://github.com/kyb3r/modmail/issues/3046)) ### Fixed diff --git a/bot.py b/bot.py index dcd447eed4..45da7fa953 100644 --- a/bot.py +++ b/bot.py @@ -685,7 +685,7 @@ def check_account_age(self, author: discord.Member) -> bool: logger.debug("Blocked due to account age, user %s.", author.name) if str(author.id) not in self.blocked_users: - new_reason = f"System Message: New Account. Required to wait for {delta}." + new_reason = f"System Message: New Account. User can try again {delta}." self.blocked_users[str(author.id)] = new_reason return False @@ -711,7 +711,7 @@ def check_guild_age(self, author: discord.Member) -> bool: logger.debug("Blocked due to guild age, user %s.", author.name) if str(author.id) not in self.blocked_users: - new_reason = f"System Message: Recently Joined. Required to wait for {delta}." + new_reason = f"System Message: Recently Joined. User can try again {delta}." self.blocked_users[str(author.id)] = new_reason return False diff --git a/cogs/modmail.py b/cogs/modmail.py index c17b580370..7900f0eeef 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1,6 +1,6 @@ import asyncio import re -from datetime import datetime +from datetime import datetime, timezone from itertools import zip_longest from typing import Optional, Union from types import SimpleNamespace @@ -12,7 +12,6 @@ from discord.utils import escape_markdown from dateutil import parser -from natural.date import duration from core import checks from core.models import DMDisabled, PermissionLevel, SimilarCategoryConverter, getLogger @@ -359,7 +358,7 @@ async def send_scheduled_close_message(self, ctx, after, silent=False): embed = discord.Embed( title="Scheduled close", - description=f"This thread will close {silent}in {human_delta}.", + description=f"This thread will close {silent}{human_delta}.", color=self.bot.error_color, ) @@ -631,7 +630,7 @@ def format_log_embeds(self, logs, avatar_url): title = f"Total Results Found ({len(logs)})" for entry in logs: - created_at = parser.parse(entry["created_at"]) + created_at = parser.parse(entry["created_at"]).astimezone(timezone.utc) prefix = self.bot.config["log_url_prefix"].strip("/") if prefix == "NONE": @@ -646,7 +645,7 @@ def format_log_embeds(self, logs, avatar_url): embed = discord.Embed(color=self.bot.main_color, timestamp=created_at) embed.set_author(name=f"{title} - {username}", icon_url=avatar_url, url=log_url) embed.url = log_url - embed.add_field(name="Created", value=duration(created_at, now=discord.utils.utcnow())) + embed.add_field(name="Created", value=human_timedelta(created_at)) closer = entry.get("closer") if closer is None: closer_msg = "Unknown" diff --git a/core/config.py b/core/config.py index 6d2a2eb1cd..399592e055 100644 --- a/core/config.py +++ b/core/config.py @@ -78,7 +78,7 @@ class ConfigManager: "thread_move_notify_mods": False, "thread_move_response": "This thread has been moved.", "cooldown_thread_title": "Message not sent!", - "cooldown_thread_response": "You must wait for {delta} before you can contact me again.", + "cooldown_thread_response": "Your cooldown ends {delta}. Try contacting me then.", "disabled_new_thread_title": "Not Delivered", "disabled_new_thread_response": "We are not accepting new threads.", "disabled_new_thread_footer": "Please try again later...", diff --git a/core/config_help.json b/core/config_help.json index 53d1d4daec..6ee84eee15 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -571,7 +571,7 @@ ] }, "cooldown_thread_response": { - "default": "You must wait for {delta} before you can contact me again.", + "default": "Your cooldown ends {delta}. Try contacting me then.", "description": "The description of the message embed when the user has a cooldown before creating a new thread.", "examples": [ "`{prefix}config set cooldown_thread_response Be patient! You are on cooldown, wait {delta} more.`" diff --git a/core/thread.py b/core/thread.py index 145864e815..9fa504152e 100644 --- a/core/thread.py +++ b/core/thread.py @@ -565,7 +565,7 @@ async def _restart_close_timer(self): seconds = timeout.total_seconds() # seconds = 20 # Uncomment to debug with just 20 seconds reset_time = discord.utils.utcnow() + timedelta(seconds=seconds) - human_time = human_timedelta(dt=reset_time) + human_time = human_timedelta(dt=reset_time, spec="manual") if self.bot.config.get("thread_auto_close_silently"): return await self.close(closer=self.bot.user, silent=True, after=int(seconds), auto_close=True) diff --git a/core/time.py b/core/time.py index 376f2074eb..26b41b9043 100644 --- a/core/time.py +++ b/core/time.py @@ -187,35 +187,39 @@ async def convert(self, ctx, argument): return super().convert(ctx, argument) -def human_timedelta(dt, *, source=None): - now = source or discord.utils.utcnow() - if dt > now: - delta = relativedelta(dt, now) - suffix = "" - else: - delta = relativedelta(now, dt) - suffix = " ago" - - if delta.microseconds and delta.seconds: - delta = delta + relativedelta(seconds=+1) - - attrs = ["years", "months", "days", "hours", "minutes", "seconds"] - - output = [] - for attr in attrs: - elem = getattr(delta, attr) - if not elem: - continue - - if elem > 1: - output.append(f"{elem} {attr}") +def human_timedelta(dt, *, spec="R"): + if spec == "manual": + now = discord.utils.utcnow() + if dt > now: + delta = relativedelta(dt, now) + suffix = "" else: - output.append(f"{elem} {attr[:-1]}") - - if not output: - return "now" - if len(output) == 1: - return output[0] + suffix - if len(output) == 2: - return f"{output[0]} and {output[1]}{suffix}" - return f"{output[0]}, {output[1]} and {output[2]}{suffix}" + delta = relativedelta(now, dt) + suffix = " ago" + + if delta.microseconds and delta.seconds: + delta = delta + relativedelta(seconds=+1) + + attrs = ["years", "months", "days", "hours", "minutes", "seconds"] + + output = [] + for attr in attrs: + elem = getattr(delta, attr) + if not elem: + continue + + if elem > 1: + output.append(f"{elem} {attr}") + else: + output.append(f"{elem} {attr[:-1]}") + + if not output: + return "now" + if len(output) == 1: + return output[0] + suffix + if len(output) == 2: + return f"{output[0]} and {output[1]}{suffix}" + return f"{output[0]}, {output[1]} and {output[2]}{suffix}" + else: + unixtime = int(dt.timestamp()) + return f"<t:{unixtime}:{spec}>" From 3af772f0c1bd9fd034b4e2b5ce7e119ea1c14f28 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 22:40:28 +0800 Subject: [PATCH 040/225] Properly implement per-server avatars --- core/thread.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/core/thread.py b/core/thread.py index 9fa504152e..eb47ba9cdc 100644 --- a/core/thread.py +++ b/core/thread.py @@ -335,10 +335,9 @@ def _format_info_embed(self, user, log_url, log_count, color): else: footer = f"User ID: {user.id}" - embed.set_author(name=str(user), icon_url=user.display_avatar.url, url=log_url) - # embed.set_thumbnail(url=avi) - if member is not None: + embed.set_author(name=str(user), icon_url=member.display_avatar.url, url=log_url) + joined = str((time - member.joined_at).days) # embed.add_field(name='Joined', value=joined + days(joined)) if self.bot.config["thread_show_join_age"]: @@ -350,6 +349,7 @@ def _format_info_embed(self, user, log_url, log_count, color): embed.add_field(name="Roles", value=role_names, inline=True) embed.set_footer(text=footer) else: + embed.set_author(name=str(user), icon_url=user.display_avatar.url, url=log_url) embed.set_footer(text=f"{footer} โ€ข (not in main server)") embed.description += ", ".join(user_info) @@ -931,6 +931,11 @@ async def send( destination = destination or self.channel author = message.author + member = self.bot.guild.get_member(author.id) + if member: + avatar_url = member.display_avatar.url + else: + avatar_url = author.display_avatar.url embed = discord.Embed(description=message.content) if self.bot.config["show_timestamp"]: @@ -958,7 +963,7 @@ async def send( else: # Normal message name = str(author) - avatar_url = author.display_avatar.url + avatar_url = avatar_url embed.set_author( name=name, icon_url=avatar_url, From 998d938f33ed9fe3bfe59ff6934c1ffd0bb67116 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 22:49:42 +0800 Subject: [PATCH 041/225] Modmail now work in threads --- CHANGELOG.md | 1 + core/thread.py | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ef596f888..c2fca71128 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Attachments now work on plain replies. ([GH #3102](https://github.com/kyb3r/modmail/issues/3102)) - Support LOTTIE stickers. ([GH #3119](https://github.com/kyb3r/modmail/issues/3119)) - Editing notes now work. ([GH #3094](https://github.com/kyb3r/modmail/issues/3094)) +- Commands now work in threads. ### Internal diff --git a/core/thread.py b/core/thread.py index eb47ba9cdc..1d41c0a18a 100644 --- a/core/thread.py +++ b/core/thread.py @@ -1281,7 +1281,7 @@ async def find( recipient_id: int = None, ) -> typing.Optional[Thread]: """Finds a thread from cache or from discord channel topics.""" - if recipient is None and channel is not None: + if recipient is None and channel is not None and isinstance(channel, discord.TextChannel): thread = await self._find_from_channel(channel) if thread is None: user_id, thread = next( @@ -1310,7 +1310,6 @@ async def find( await thread.close(closer=self.bot.user, silent=True, delete_channel=False) thread = None else: - def check(topic): _, user_id, other_ids = parse_channel_topic(topic) return recipient_id == user_id or recipient_id in other_ids From 67781cae9cc149d2d847e96292377fab0341c029 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 22:54:20 +0800 Subject: [PATCH 042/225] Formatting --- core/thread.py | 1 + 1 file changed, 1 insertion(+) diff --git a/core/thread.py b/core/thread.py index 1d41c0a18a..c95ce09cb6 100644 --- a/core/thread.py +++ b/core/thread.py @@ -1310,6 +1310,7 @@ async def find( await thread.close(closer=self.bot.user, silent=True, delete_channel=False) thread = None else: + def check(topic): _, user_id, other_ids = parse_channel_topic(topic) return recipient_id == user_id or recipient_id in other_ids From ae1af88c2966606611386b76cf46836be5fab6be Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 22:58:16 +0800 Subject: [PATCH 043/225] Bunp version to v4-dev4 --- CHANGELOG.md | 2 +- README.md | 2 +- bot.py | 2 +- pyproject.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2fca71128..a4409e12bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html); however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. -# v3.11.0 +# v4.0.0 ### Breaking diff --git a/README.md b/README.md index 7492a53116..4487438a5c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ <br> <a href="#"> - <img src="https://img.shields.io/badge/Latest%20Version-v3.11.0-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> + <img src="https://img.shields.io/badge/Latest%20Version-v4.0.0-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> </a> <br> diff --git a/bot.py b/bot.py index 45da7fa953..77d6327a4f 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "3.11.0-dev3" +__version__ = "4.0.0-dev4" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 1e1a13f5c9..9b541f6243 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '3.11.0-dev3' +version = '4.0.0-dev4' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 68bc5733cbf5a57394879e2b370023e550ba061c Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 23:26:43 +0800 Subject: [PATCH 044/225] Fix timezone mismatch --- bot.py | 6 +++--- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bot.py b/bot.py index 77d6327a4f..c9ad1ee638 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev4" +__version__ = "4.0.0-dev5" import asyncio @@ -10,7 +10,7 @@ import string import sys import typing -from datetime import datetime +from datetime import datetime, timezone from subprocess import PIPE from types import SimpleNamespace @@ -565,7 +565,7 @@ async def on_ready(self): logger.line() for recipient_id, items in tuple(closures.items()): - after = (datetime.fromisoformat(items["time"]) - discord.utils.utcnow()).total_seconds() + after = (datetime.fromisoformat(items["time"]).astimezone(timezone.utc) - discord.utils.utcnow()).total_seconds() if after <= 0: logger.debug("Closing thread for recipient %s.", recipient_id) after = 0 diff --git a/pyproject.toml b/pyproject.toml index 9b541f6243..9f722227eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev4' +version = '4.0.0-dev5' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 459b81dbec086193a59c4c5490800ba5e9182cf6 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 21 Nov 2021 23:38:21 +0800 Subject: [PATCH 045/225] format --- bot.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index c9ad1ee638..fb4f8b04a2 100644 --- a/bot.py +++ b/bot.py @@ -565,7 +565,9 @@ async def on_ready(self): logger.line() for recipient_id, items in tuple(closures.items()): - after = (datetime.fromisoformat(items["time"]).astimezone(timezone.utc) - discord.utils.utcnow()).total_seconds() + after = ( + datetime.fromisoformat(items["time"]).astimezone(timezone.utc) - discord.utils.utcnow() + ).total_seconds() if after <= 0: logger.debug("Closing thread for recipient %s.", recipient_id) after = 0 From da92d04a5325a644e475f514f01d20a78a5c2431 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Nov 2021 00:52:33 +0800 Subject: [PATCH 046/225] improve cairo warnings --- bot.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/bot.py b/bot.py index fb4f8b04a2..c553686852 100644 --- a/bot.py +++ b/bot.py @@ -8,6 +8,7 @@ import re import signal import string +import struct import sys import typing from datetime import datetime, timezone @@ -1690,7 +1691,7 @@ def format_channel_name(self, author, exclude_channel=None, force_null=False): def main(): try: # noinspection PyUnresolvedReferences - import uvloop + import uvloop # type: ignore logger.debug("Setting up with uvloop.") uvloop.install() @@ -1698,11 +1699,21 @@ def main(): pass try: - import cairosvg + import cairosvg # noqa: F401 except OSError: - logger.error( - "Unable to import cairosvg, install GTK Installer for Windows: https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer/releases/latest" - ) + if os.name == "nt": + if struct.calcsize("P") * 8 != 64: + logger.error( + "Unable to import cairosvg, ensure your Python is a 64-bit version: https://www.python.org/downloads/" + ) + else: + logger.error( + "Unable to import cairosvg, install GTK Installer for Windows: https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer/releases/latest" + ) + else: + logger.error( + "Unable to import cairosvg, report on our support server with your OS details: https://discord.gg/etJNHCQ" + ) sys.exit(0) # check discord version From 28d86764f46807cbdd18f271c37734d2f66bfaad Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Nov 2021 17:32:51 +0800 Subject: [PATCH 047/225] show_log_url_button for log urls resolves #3122 --- CHANGELOG.md | 1 + core/config.py | 2 ++ core/config_help.json | 8 ++++++++ core/thread.py | 7 ++++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4409e12bb..b3dae23d78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `plain_snippets` config to force all snippets to be plain. ([GH #3083](https://github.com/kyb3r/modmail/issues/3083)) - `?fpareply` and `?fpreply` to reply to messages with variables plainly. - `use_nickname_channel_name` config to use nicknames instead of usernames for channel names. ([GH #3112](https://github.com/kyb3r/modmail/issues/3112)) +- `show_log_url_button` config to show Log URL button. ([GH #3122](https://github.com/kyb3r/modmail/issues/3122)) ### Improved diff --git a/core/config.py b/core/config.py index 399592e055..14f86ecd2e 100644 --- a/core/config.py +++ b/core/config.py @@ -94,6 +94,7 @@ class ConfigManager: "anonymous_snippets": False, "plain_snippets": False, "require_close_reason": False, + "show_log_url_button": False, # group conversations "private_added_to_group_title": "New Thread (Group)", "private_added_to_group_response": "{moderator.name} has added you to a Modmail thread.", @@ -191,6 +192,7 @@ class ConfigManager: "reply_without_command", "anon_reply_without_command", "plain_reply_without_command", + "show_log_url_button", "recipient_thread_close", "thread_auto_close_silently", "thread_move_notify", diff --git a/core/config_help.json b/core/config_help.json index 6ee84eee15..342652456d 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -828,6 +828,14 @@ ], "notes": [] }, + "show_log_url_button": { + "default" : "No", + "description": "Shows the button to open the Log URL.", + "examples": [ + "`{prefix}config set show_log_url_button yes`" + ], + "notes": [] + }, "private_added_to_group_title": { "default": "New Thread (Group)", "description": "This is the message embed title sent to the recipient that is just added to a thread.", diff --git a/core/thread.py b/core/thread.py index c95ce09cb6..67458f0017 100644 --- a/core/thread.py +++ b/core/thread.py @@ -495,7 +495,12 @@ async def _close(self, closer, silent=False, delete_channel=True, message=None, tasks = [self.bot.config.update()] if self.bot.log_channel is not None and self.channel is not None: - tasks.append(self.bot.log_channel.send(embed=embed)) + if self.bot.config["show_log_url_button"]: + view = discord.ui.View() + view.add_item(discord.ui.Button(label='Log link', url=log_url, style=discord.ButtonStyle.url)) + else: + view = None + tasks.append(self.bot.log_channel.send(embed=embed, view=view)) # Thread closed message From 9866141817bd9d63adee3b238979d743878b1216 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Nov 2021 18:54:27 +0800 Subject: [PATCH 048/225] Use discord native buttons for pagination --- CHANGELOG.md | 1 + core/paginator.py | 259 ++++++++++++++++++++++++++++------------------ core/thread.py | 2 +- 3 files changed, 159 insertions(+), 103 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3dae23d78..641b3ffcf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Modmail now uses per-server avatars if applicable. ([GH #3048](https://github.com/kyb3r/modmail/issues/3048)) - Use discord relative timedeltas. ([GH #3046](https://github.com/kyb3r/modmail/issues/3046)) +- Use discord native buttons for all paginator sessions. ### Fixed diff --git a/core/paginator.py b/core/paginator.py index 934b4670be..b208bff0a3 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -1,8 +1,8 @@ import typing -import asyncio -from discord import User, Reaction, Message, Embed -from discord import HTTPException, InvalidArgument +import discord +from discord import Message, Embed, ButtonStyle, Interaction +from discord.ui import View, Button from discord.ext import commands @@ -33,8 +33,8 @@ class PaginatorSession: The `Message` of the `Embed`. current : int The current page number. - reaction_map : Dict[str, method] - A mapping for reaction to method. + callback_map : Dict[str, method] + A mapping for text to method. """ def __init__(self, ctx: commands.Context, *pages, **options): @@ -45,38 +45,15 @@ def __init__(self, ctx: commands.Context, *pages, **options): self.current = 0 self.pages = list(pages) self.destination = options.get("destination", ctx) - self.reaction_map = { - "โฎ": self.first_page, - "โ—€": self.previous_page, - "โ–ถ": self.next_page, - "โญ": self.last_page, - "๐Ÿ›‘": self.close, - } - - def add_page(self, item) -> None: - """ - Add a page. - """ - raise NotImplementedError - - async def create_base(self, item) -> None: - """ - Create a base `Message`. - """ - await self._create_base(item) + self.view = None - if len(self.pages) == 1: - self.running = False - return - - self.running = True - for reaction in self.reaction_map: - if len(self.pages) == 2 and reaction in "โฎโญ": - continue - await self.ctx.bot.add_reaction(self.base, reaction) - - async def _create_base(self, item) -> None: - raise NotImplementedError + self.callback_map = { + "<<": self.first_page, + "<": self.previous_page, + ">": self.next_page, + ">>": self.last_page, + } + self._buttons_map = {"<<": None, "<": None, ">": None, ">>": None} async def show_page(self, index: int) -> None: """ @@ -98,66 +75,77 @@ async def show_page(self, index: int) -> None: else: await self.create_base(page) + self.update_disabled_status() + + def update_disabled_status(self): + if self.current == self.first_page(): + # disable << button + if self._buttons_map["<<"]: + self._buttons_map["<<"].disabled = True + + self._buttons_map["<"].disabled = True + else: + if self._buttons_map["<<"]: + self._buttons_map["<<"].disabled = False + + self._buttons_map["<"].disabled = False + + if self.current == self.last_page(): + # disable >> button + if self._buttons_map[">>"] is not None: + self._buttons_map[">>"].disabled = True + + self._buttons_map[">"].disabled = True + else: + if self._buttons_map[">>"] is not None: + self._buttons_map[">>"].disabled = False + + self._buttons_map[">"].disabled = False + + async def create_base(self, item) -> None: + """ + Create a base `Message`. + """ + if len(self.pages) == 1: + self.view = None + self.running = False + else: + self.view = PaginatorView(self, timeout=self.timeout) + self.update_disabled_status() + self.running = True + + await self._create_base(item, self.view) + + async def _create_base(self, item, view: View) -> None: + raise NotImplementedError + async def _show_page(self, page): raise NotImplementedError - def react_check(self, reaction: Reaction, user: User) -> bool: - """ + def first_page(self): + """Returns the index of the first page""" + return 0 - Parameters - ---------- - reaction : Reaction - The `Reaction` object of the reaction. - user : User - The `User` or `Member` object of who sent the reaction. + def next_page(self): + """Returns the index of the next page""" + return min(self.current + 1, self.last_page()) - Returns - ------- - bool - """ - return ( - reaction.message.id == self.base.id - and user.id == self.ctx.author.id - and reaction.emoji in self.reaction_map.keys() - ) + def previous_page(self): + """Returns the index of the previous page""" + return max(self.current - 1, self.first_page()) + + def last_page(self): + """Returns the index of the last page""" + return len(self.pages) - 1 async def run(self) -> typing.Optional[Message]: """ Starts the pagination session. - - Returns - ------- - Optional[Message] - If it's closed before running ends. """ if not self.running: await self.show_page(self.current) - while self.running: - try: - reaction, user = await self.ctx.bot.wait_for( - "reaction_add", check=self.react_check, timeout=self.timeout - ) - except asyncio.TimeoutError: - return await self.close(delete=False) - else: - action = self.reaction_map.get(reaction.emoji) - await action() - try: - await self.base.remove_reaction(reaction, user) - except (HTTPException, InvalidArgument): - pass - - async def previous_page(self) -> None: - """ - Go to the previous page. - """ - await self.show_page(self.current - 1) - - async def next_page(self) -> None: - """ - Go to the next page. - """ - await self.show_page(self.current + 1) + await self.view.wait() + await self.close(delete=False) async def close(self, delete: bool = True) -> typing.Optional[Message]: """ @@ -179,25 +167,92 @@ async def close(self, delete: bool = True) -> typing.Optional[Message]: sent_emoji, _ = await self.ctx.bot.retrieve_emoji() await self.ctx.bot.add_reaction(self.ctx.message, sent_emoji) + self.view.clear_items() + self.view.stop() if delete: return await self.base.delete() - try: - await self.base.clear_reactions() - except HTTPException: - pass - async def first_page(self) -> None: - """ - Go to the first page. - """ - await self.show_page(0) +class PaginatorView(View): + """ + View that is used for pagination. - async def last_page(self) -> None: - """ - Go to the last page. - """ - await self.show_page(len(self.pages) - 1) + Parameters + ---------- + handler : PaginatorSession + The paginator session that spawned this view. + timeout : float + How long to wait for before the session closes. + + Attributes + ---------- + handler : PaginatorSession + The paginator session that spawned this view. + timeout : float + How long to wait for before the session closes. + """ + + def __init__(self, handler: PaginatorSession, *args, **kwargs): + super().__init__(*args, **kwargs) + self.handler = handler + self.clear_items() + self.fill_items() + + @discord.ui.button(label="Stop", style=ButtonStyle.danger) + async def stop_button(self, button: Button, interaction: Interaction): + await interaction.response.edit_message(view=self) + await self.handler.close() + + def fill_items(self): + for label, callback in self.handler.callback_map.items(): + if len(self.handler.pages) == 2 and label in ("<<", ">>"): + continue + + if label in ("<<", ">>"): + style = ButtonStyle.secondary + else: + style = ButtonStyle.primary + + button = PageButton(self.handler, callback, label=label, style=style) + + self.handler._buttons_map[label] = button + self.add_item(button) + self.add_item(self.stop_button) + + async def interaction_check(self, interaction: Interaction): + """Only allow the message author to interact""" + if interaction.user != self.handler.ctx.author: + return False + return True + + +class PageButton(Button): + """ + A button that has a callback to jump to the next page + + Parameters + ---------- + handler : PaginatorSession + The paginator session that spawned this view. + page_callback : Callable + A callable that returns an int of the page to go to. + + Attributes + ---------- + handler : PaginatorSession + The paginator session that spawned this view. + page_callback : Callable + A callable that returns an int of the page to go to. + """ + + def __init__(self, handler, page_callback, **kwargs): + super().__init__(**kwargs) + self.handler = handler + self.page_callback = page_callback + + async def callback(self, interaction: Interaction): + await self.handler.show_page(self.page_callback()) + await interaction.response.edit_message(view=self.view) class EmbedPaginatorSession(PaginatorSession): @@ -223,8 +278,8 @@ def add_page(self, item: Embed) -> None: else: raise TypeError("Page must be an Embed object.") - async def _create_base(self, item: Embed) -> None: - self.base = await self.destination.send(embed=item) + async def _create_base(self, item: Embed, view: View) -> None: + self.base = await self.destination.send(embed=item, view=view) async def _show_page(self, page): await self.base.edit(embed=page) @@ -255,9 +310,9 @@ def _set_footer(self): self.embed.set_footer(text=footer_text, icon_url=icon_url) - async def _create_base(self, item: str) -> None: + async def _create_base(self, item: str, view: View) -> None: self._set_footer() - self.base = await self.ctx.send(content=item, embed=self.embed) + self.base = await self.ctx.send(content=item, embed=self.embed, view=view) async def _show_page(self, page) -> None: self._set_footer() diff --git a/core/thread.py b/core/thread.py index 67458f0017..87ffc45ee3 100644 --- a/core/thread.py +++ b/core/thread.py @@ -497,7 +497,7 @@ async def _close(self, closer, silent=False, delete_channel=True, message=None, if self.bot.log_channel is not None and self.channel is not None: if self.bot.config["show_log_url_button"]: view = discord.ui.View() - view.add_item(discord.ui.Button(label='Log link', url=log_url, style=discord.ButtonStyle.url)) + view.add_item(discord.ui.Button(label="Log link", url=log_url, style=discord.ButtonStyle.url)) else: view = None tasks.append(self.bot.log_channel.send(embed=embed, view=view)) From e50cf1fdb60fd10e2952a5cc40b2b648cda9e3d4 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Nov 2021 19:24:41 +0800 Subject: [PATCH 049/225] Select menus for some embed paginations #2913 --- CHANGELOG.md | 1 + core/paginator.py | 56 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 641b3ffcf4..aa4dea5219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `?fpareply` and `?fpreply` to reply to messages with variables plainly. - `use_nickname_channel_name` config to use nicknames instead of usernames for channel names. ([GH #3112](https://github.com/kyb3r/modmail/issues/3112)) - `show_log_url_button` config to show Log URL button. ([GH #3122](https://github.com/kyb3r/modmail/issues/3122)) +- Select menus for certain paginators. ### Improved diff --git a/core/paginator.py b/core/paginator.py index b208bff0a3..bb84aa350f 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -1,8 +1,9 @@ +from collections import OrderedDict import typing import discord from discord import Message, Embed, ButtonStyle, Interaction -from discord.ui import View, Button +from discord.ui import View, Button, Select from discord.ext import commands @@ -35,6 +36,10 @@ class PaginatorSession: The current page number. callback_map : Dict[str, method] A mapping for text to method. + view : PaginatorView + The view that is sent along with the base message. + select_menu : Select + A select menu that will be added to the View. """ def __init__(self, ctx: commands.Context, *pages, **options): @@ -46,6 +51,7 @@ def __init__(self, ctx: commands.Context, *pages, **options): self.pages = list(pages) self.destination = options.get("destination", ctx) self.view = None + self.select_menu = None self.callback_map = { "<<": self.first_page, @@ -195,7 +201,7 @@ class PaginatorView(View): def __init__(self, handler: PaginatorSession, *args, **kwargs): super().__init__(*args, **kwargs) self.handler = handler - self.clear_items() + self.clear_items() # clear first so we can control the order self.fill_items() @discord.ui.button(label="Stop", style=ButtonStyle.danger) @@ -204,6 +210,9 @@ async def stop_button(self, button: Button, interaction: Interaction): await self.handler.close() def fill_items(self): + if self.handler.select_menu is not None: + self.add_item(self.handler.select_menu) + for label, callback in self.handler.callback_map.items(): if len(self.handler.pages) == 2 and label in ("<<", ">>"): continue @@ -255,11 +264,29 @@ async def callback(self, interaction: Interaction): await interaction.response.edit_message(view=self.view) +class PageSelect(Select): + def __init__(self, handler: PaginatorSession, pages: typing.List[typing.Tuple[str]]): + self.handler = handler + options = [] + for n, (label, description) in enumerate(pages): + options.append(discord.SelectOption(label=label, description=description, value=str(n))) + + options = options[:25] # max 25 options + super().__init__(placeholder="Select a page", min_values=1, max_values=1, options=options) + + async def callback(self, interaction: Interaction): + page = int(self.values[0]) + await self.handler.show_page(page) + await interaction.response.edit_message(view=self.view) + + class EmbedPaginatorSession(PaginatorSession): def __init__(self, ctx: commands.Context, *embeds, **options): super().__init__(ctx, *embeds, **options) if len(self.pages) > 1: + select_options = [] + create_select = True for i, embed in enumerate(self.pages): footer_text = f"Page {i + 1} of {len(self.pages)}" if embed.footer.text: @@ -269,9 +296,32 @@ def __init__(self, ctx: commands.Context, *embeds, **options): icon_url = embed.footer.icon.url else: icon_url = Embed.Empty - embed.set_footer(text=footer_text, icon_url=icon_url) + # select menu + if embed.author.name: + title = embed.author.name[:30].strip() + if len(embed.author.name) > 30: + title += "..." + else: + title = embed.title[:30].strip() + if len(embed.title) > 30: + title += "..." + if not title: + create_select = False + + if embed.description: + description = embed.description[:40].replace("*", "").replace("`", "").strip() + if len(embed.description) > 40: + description += "..." + else: + description = "" + select_options.append((title, description)) + + if create_select: + if len(set(x[0] for x in select_options)) != 1: # must have unique authors + self.select_menu = PageSelect(self, select_options) + def add_page(self, item: Embed) -> None: if isinstance(item, Embed): self.pages.append(item) From 77ed926f87949e2fa55bb1c2e6b6b56c2be667ab Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Nov 2021 19:26:15 +0800 Subject: [PATCH 050/225] Bump version to v4-dev6 --- bot.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index c553686852..3e3a6ec5cf 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev5" +__version__ = "4.0.0-dev6" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 9f722227eb..031fc5073f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev5' +version = '4.0.0-dev6' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 0bdaba666c7540dd9b7b0c2be2fb99677278a040 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Nov 2021 19:26:36 +0800 Subject: [PATCH 051/225] Remove unused import --- core/paginator.py | 1 - 1 file changed, 1 deletion(-) diff --git a/core/paginator.py b/core/paginator.py index bb84aa350f..c4a4772337 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -1,4 +1,3 @@ -from collections import OrderedDict import typing import discord From a743321e01a8339b07f1dd5e8d2dac46b9f21960 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Nov 2021 19:56:28 +0800 Subject: [PATCH 052/225] Remove unused import --- core/paginator.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/paginator.py b/core/paginator.py index c4a4772337..3126ddc527 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -173,6 +173,8 @@ async def close(self, delete: bool = True) -> typing.Optional[Message]: await self.ctx.bot.add_reaction(self.ctx.message, sent_emoji) self.view.clear_items() + await self.message.edit(view=self.view) + self.view.stop() if delete: return await self.base.delete() From 8011ccd6b71bd2a4b9902e13625a50dc52cddc0a Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Nov 2021 20:04:39 +0800 Subject: [PATCH 053/225] Fix closing paginators --- core/paginator.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/core/paginator.py b/core/paginator.py index 3126ddc527..3fbd990c4a 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -167,17 +167,18 @@ async def close(self, delete: bool = True) -> typing.Optional[Message]: Optional[Message] If `delete` is `True`. """ - self.running = False - - sent_emoji, _ = await self.ctx.bot.retrieve_emoji() - await self.ctx.bot.add_reaction(self.ctx.message, sent_emoji) + if self.running: + self.running = False - self.view.clear_items() - await self.message.edit(view=self.view) + self.view.stop() + if delete: + await self.base.delete() + else: + self.view.clear_items() + await self.base.edit(view=self.view) - self.view.stop() - if delete: - return await self.base.delete() + sent_emoji, _ = await self.ctx.bot.retrieve_emoji() + await self.ctx.bot.add_reaction(self.ctx.message, sent_emoji) class PaginatorView(View): From f7a882a62fa7375f89449e1669168fc14c84e1f1 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Nov 2021 20:15:13 +0800 Subject: [PATCH 054/225] Optimise paginators page switching --- core/paginator.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/core/paginator.py b/core/paginator.py index 3fbd990c4a..6525d0ddd0 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -60,7 +60,7 @@ def __init__(self, ctx: commands.Context, *pages, **options): } self._buttons_map = {"<<": None, "<": None, ">": None, ">>": None} - async def show_page(self, index: int) -> None: + async def show_page(self, index: int) -> typing.Optional[typing.Dict]: """ Show a page by page number. @@ -74,13 +74,15 @@ async def show_page(self, index: int) -> None: self.current = index page = self.pages[index] + result = None if self.running: - await self._show_page(page) + result = self._show_page(page) else: await self.create_base(page) self.update_disabled_status() + return result def update_disabled_status(self): if self.current == self.first_page(): @@ -124,7 +126,7 @@ async def create_base(self, item) -> None: async def _create_base(self, item, view: View) -> None: raise NotImplementedError - async def _show_page(self, page): + def _show_page(self, page): raise NotImplementedError def first_page(self): @@ -233,6 +235,7 @@ def fill_items(self): async def interaction_check(self, interaction: Interaction): """Only allow the message author to interact""" if interaction.user != self.handler.ctx.author: + await interaction.response.send_message("Only the original author can control this!", ephemeral=True) return False return True @@ -262,8 +265,8 @@ def __init__(self, handler, page_callback, **kwargs): self.page_callback = page_callback async def callback(self, interaction: Interaction): - await self.handler.show_page(self.page_callback()) - await interaction.response.edit_message(view=self.view) + kwargs = await self.handler.show_page(self.page_callback()) + await interaction.response.edit_message(**kwargs, view=self.view) class PageSelect(Select): @@ -278,8 +281,8 @@ def __init__(self, handler: PaginatorSession, pages: typing.List[typing.Tuple[st async def callback(self, interaction: Interaction): page = int(self.values[0]) - await self.handler.show_page(page) - await interaction.response.edit_message(view=self.view) + kwargs = await self.handler.show_page(page) + await interaction.response.edit_message(**kwargs, view=self.view) class EmbedPaginatorSession(PaginatorSession): @@ -333,8 +336,8 @@ def add_page(self, item: Embed) -> None: async def _create_base(self, item: Embed, view: View) -> None: self.base = await self.destination.send(embed=item, view=view) - async def _show_page(self, page): - await self.base.edit(embed=page) + def _show_page(self, page): + return dict(embed=page) class MessagePaginatorSession(PaginatorSession): @@ -366,6 +369,6 @@ async def _create_base(self, item: str, view: View) -> None: self._set_footer() self.base = await self.ctx.send(content=item, embed=self.embed, view=view) - async def _show_page(self, page) -> None: + def _show_page(self, page) -> typing.Dict: self._set_footer() - await self.base.edit(content=page, embed=self.embed) + return dict(content=page, embed=self.embed) From c16ff261f204f5831da577d26a011db5d65d4610 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Nov 2021 20:21:56 +0800 Subject: [PATCH 055/225] Optimise Stop pagination --- core/paginator.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/core/paginator.py b/core/paginator.py index 6525d0ddd0..b9cd29a26b 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -154,7 +154,9 @@ async def run(self) -> typing.Optional[Message]: await self.view.wait() await self.close(delete=False) - async def close(self, delete: bool = True) -> typing.Optional[Message]: + async def close( + self, delete: bool = True, *, interaction: Interaction = None + ) -> typing.Optional[Message]: """ Closes the pagination session. @@ -170,17 +172,22 @@ async def close(self, delete: bool = True) -> typing.Optional[Message]: If `delete` is `True`. """ if self.running: + sent_emoji, _ = await self.ctx.bot.retrieve_emoji() + await self.ctx.bot.add_reaction(self.ctx.message, sent_emoji) + + if interaction: + message = interaction.message + else: + message = self.base + self.running = False self.view.stop() if delete: - await self.base.delete() + await message.delete() else: self.view.clear_items() - await self.base.edit(view=self.view) - - sent_emoji, _ = await self.ctx.bot.retrieve_emoji() - await self.ctx.bot.add_reaction(self.ctx.message, sent_emoji) + await message.edit(view=self.view) class PaginatorView(View): @@ -210,8 +217,7 @@ def __init__(self, handler: PaginatorSession, *args, **kwargs): @discord.ui.button(label="Stop", style=ButtonStyle.danger) async def stop_button(self, button: Button, interaction: Interaction): - await interaction.response.edit_message(view=self) - await self.handler.close() + await self.handler.close(interaction=interaction) def fill_items(self): if self.handler.select_menu is not None: @@ -235,7 +241,9 @@ def fill_items(self): async def interaction_check(self, interaction: Interaction): """Only allow the message author to interact""" if interaction.user != self.handler.ctx.author: - await interaction.response.send_message("Only the original author can control this!", ephemeral=True) + await interaction.response.send_message( + "Only the original author can control this!", ephemeral=True + ) return False return True From 6adcd048d5cd82e6f68487d039249933a51006ab Mon Sep 17 00:00:00 2001 From: lorenzo132 <50767078+lorenzo132@users.noreply.github.com> Date: Mon, 22 Nov 2021 22:48:40 +0100 Subject: [PATCH 056/225] make config readable --- cogs/utility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/utility.py b/cogs/utility.py index 7278c350fc..dbd3ccf279 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -913,7 +913,7 @@ def fmt(val): if current_key == key: index = i embed = discord.Embed( - title=f"Configuration description on {current_key}:", color=self.bot.main_color + title=f"{current_key}", color=self.bot.main_color ) embed.add_field(name="Default:", value=fmt(info["default"]), inline=False) embed.add_field(name="Information:", value=fmt(info["description"]), inline=False) From f8ad5fd16e3b660d1e303dc52b87152af4b5878e Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Tue, 23 Nov 2021 13:15:33 +0530 Subject: [PATCH 057/225] Process snippets in get_contexts --- bot.py | 54 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/bot.py b/bot.py index fb4f8b04a2..d65eee3a48 100644 --- a/bot.py +++ b/bot.py @@ -955,6 +955,16 @@ async def process_dm_modmail(self, message: discord.Message) -> None: await self.add_reaction(message, sent_emoji) self.dispatch("thread_reply", thread, False, message, False, False) + def _get_snippet_command(self) -> commands.Command: + """Get the correct reply command based on the snippet config""" + modifiers = "f" + if self.config["plain_snippets"]: + modifiers += "p" + if self.config["anonymous_snippets"]: + modifiers += "a" + + return self.get_command(f'{modifiers}reply') + async def get_contexts(self, message, *, cls=commands.Context): """ Returns all invocation contexts from the message. @@ -986,18 +996,40 @@ async def get_contexts(self, message, *, cls=commands.Context): self.aliases.pop(invoker) for alias in aliases: - view = StringView(invoked_prefix + alias) + command = None + try: + snippet_text = self.snippets[alias] + except KeyError: + command_invocation_text = alias + else: + command = self._get_snippet_command() + command_invocation_text = f'{invoked_prefix}{command} {snippet_text}' + + view = StringView(invoked_prefix + command_invocation_text) ctx_ = cls(prefix=self.prefix, view=view, bot=self, message=message) ctx_.thread = thread discord.utils.find(view.skip_string, prefixes) ctx_.invoked_with = view.get_word().lower() - ctx_.command = self.all_commands.get(ctx_.invoked_with) + ctx_.command = command or self.all_commands.get(ctx_.invoked_with) ctxs += [ctx_] return ctxs ctx.thread = thread - ctx.invoked_with = invoker - ctx.command = self.all_commands.get(invoker) + + try: + snippet_text = self.snippets[invoker] + except KeyError: + # Process regular commands + ctx.command = self.all_commands.get(invoker) + ctx.invoked_with = invoker + else: + # Process snippets + ctx.command = self._get_snippet_command() + reply_view = StringView(f'{invoked_prefix}{ctx.command} {snippet_text}') + discord.utils.find(reply_view.skip_string, prefixes) + ctx.invoked_with = reply_view.get_word().lower() + ctx.view = reply_view + return [ctx] async def trigger_auto_triggers(self, message, channel, *, cls=commands.Context): @@ -1139,20 +1171,6 @@ async def process_commands(self, message): if isinstance(message.channel, discord.DMChannel): return await self.process_dm_modmail(message) - if message.content.startswith(self.prefix): - cmd = message.content[len(self.prefix) :].strip() - - # Process snippets - cmd = cmd.lower() - if cmd in self.snippets: - snippet = self.snippets[cmd] - modifiers = "f" - if self.config["plain_snippets"]: - modifiers += "p" - if self.config["anonymous_snippets"]: - modifiers += "a" - message.content = f"{self.prefix}{modifiers}reply {snippet}" - ctxs = await self.get_contexts(message) for ctx in ctxs: if ctx.command: From 4de349111ea1e070bb886e1d69a2cb1d1a038dae Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Tue, 23 Nov 2021 13:17:59 +0530 Subject: [PATCH 058/225] Allow the usage of snippets in `alias add` --- cogs/utility.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cogs/utility.py b/cogs/utility.py index 7278c350fc..89c4467109 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -1070,7 +1070,9 @@ async def make_alias(self, name, value, action): linked_command = view.get_word().lower() message = view.read_rest() - if not self.bot.get_command(linked_command): + is_snippet = linked_command in self.bot.snippets and not message + + if not self.bot.get_command(linked_command) and not is_snippet: alias_command = self.bot.aliases.get(linked_command) if alias_command is not None: save_aliases.extend(utils.normalize_alias(alias_command, message)) From 55e90f564dc5fe097f71685e4c1adb29eff9989a Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Sat, 27 Nov 2021 21:42:25 +0530 Subject: [PATCH 059/225] Handle snippet deletions and resolve aliases --- bot.py | 26 +++++++++++- cogs/modmail.py | 104 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 120 insertions(+), 10 deletions(-) diff --git a/bot.py b/bot.py index d65eee3a48..df513ed8ad 100644 --- a/bot.py +++ b/bot.py @@ -46,7 +46,7 @@ ) from core.thread import ThreadManager from core.time import human_timedelta -from core.utils import normalize_alias, truncate, tryint +from core.utils import normalize_alias, parse_alias, truncate, tryint logger = getLogger(__name__) @@ -85,6 +85,30 @@ def __init__(self): self.plugin_db = PluginDatabaseClient(self) # Deprecated self.startup() + def _resolve_snippet(self, name: str) -> typing.Optional[str]: + """ + Get actual snippet names from direct aliases to snippets. + + If the provided name is a snippet, it's returned unchanged. + If there is an alias by this name, it is parsed to see if it + refers only to a snippet, in which case that snippet name is + returned. + + If no snippets were found, None is returned. + """ + if name in self.snippets: + return name + + try: + command, = parse_alias(self.aliases[name]) + except (KeyError, ValueError): + # There is either no alias by this name present or the + # alias has multiple steps. + pass + else: + if command in self.snippets: + return command + @property def uptime(self) -> str: now = discord.utils.utcnow() diff --git a/cogs/modmail.py b/cogs/modmail.py index 7900f0eeef..3d29523421 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -7,6 +7,7 @@ import discord from discord.ext import commands +from discord.ext.commands.view import StringView from discord.ext.commands.cooldowns import BucketType from discord.role import Role from discord.utils import escape_markdown @@ -143,12 +144,14 @@ async def snippet(self, ctx, *, name: str.lower = None): """ if name is not None: - val = self.bot.snippets.get(name) - if val is None: + snippet_name = self.bot._resolve_snippet(name) + + if snippet_name is None: embed = create_not_found_embed(name, self.bot.snippets.keys(), "Snippet") else: + val = self.bot.snippets[snippet_name] embed = discord.Embed( - title=f'Snippet - "{name}":', description=val, color=self.bot.main_color + title=f'Snippet - "{snippet_name}":', description=val, color=self.bot.main_color ) return await ctx.send(embed=embed) @@ -177,13 +180,13 @@ async def snippet_raw(self, ctx, *, name: str.lower): """ View the raw content of a snippet. """ - val = self.bot.snippets.get(name) - if val is None: + snippet_name = self.bot._resolve_snippet(name) + if snippet_name is None: embed = create_not_found_embed(name, self.bot.snippets.keys(), "Snippet") else: - val = truncate(escape_code_block(val), 2048 - 7) + val = truncate(escape_code_block(self.bot.snippets[snippet_name]), 2048 - 7) embed = discord.Embed( - title=f'Raw snippet - "{name}":', + title=f'Raw snippet - "{snippet_name}":', description=f"```\n{val}```", color=self.bot.main_color, ) @@ -246,16 +249,99 @@ async def snippet_add(self, ctx, name: str.lower, *, value: commands.clean_conte ) return await ctx.send(embed=embed) + def _fix_aliases(self, snippet_being_deleted: str) -> tuple[list[str]]: + """ + Remove references to the snippet being deleted from aliases. + + Direct aliases to snippets are deleted, and aliases having + other steps are edited. + + A tuple of dictionaries are returned. The first dictionary + contains a mapping of alias names which were deleted to their + original value, and the second dictionary contains a mapping + of alias names which were edited to their original value. + """ + deleted = {} + edited = {} + + # Using a copy since we might need to delete aliases + for alias, val in self.bot.aliases.copy().items(): + values = parse_alias(val) + + save_aliases = [] + + for val in values: + view = StringView(val) + linked_command = view.get_word().lower() + message = view.read_rest() + + if linked_command == snippet_being_deleted: + continue + + is_valid_snippet = snippet_being_deleted in self.bot.snippets + + if not self.bot.get_command(linked_command) and not is_valid_snippet: + alias_command = self.bot.aliases[linked_command] + save_aliases.extend(normalize_alias(alias_command, message)) + else: + save_aliases.append(val) + + if not save_aliases: + original_value = self.bot.aliases.pop(alias) + deleted[alias] = original_value + else: + original_alias = self.bot.aliases[alias] + new_alias = " && ".join(f'"{a}"' for a in save_aliases) + + if original_alias != new_alias: + self.bot.aliases[alias] = new_alias + edited[alias] = original_alias + + return deleted, edited + @snippet.command(name="remove", aliases=["del", "delete"]) @checks.has_permissions(PermissionLevel.SUPPORTER) async def snippet_remove(self, ctx, *, name: str.lower): """Remove a snippet.""" - if name in self.bot.snippets: + deleted_aliases, edited_aliases = self._fix_aliases(name) + + deleted_aliases_string = ','.join(f'`{alias}`' for alias in deleted_aliases) + if len(deleted_aliases) == 1: + deleted_aliases_output = f'The `{deleted_aliases_string}` direct alias has been removed.' + elif deleted_aliases: + deleted_aliases_output = f'The following direct aliases have been removed: {deleted_aliases_string}.' + else: + deleted_aliases_output = None + + if len(edited_aliases) == 1: + alias, val = edited_aliases.popitem() + edited_aliases_output = ( + f'Steps pointing to this snippet have been removed from the `{alias}` alias' + f' (previous value: `{val}`).`' + ) + elif edited_aliases: + alias_list = '\n'.join([ + f'- `{alias_name}` (previous value: `{val}`)' + for alias_name, val in edited_aliases.items() + ]) + edited_aliases_output = ( + f'Steps pointing to this snippet have been removed from the following aliases:' + f'\n\n{alias_list}' + ) + else: + edited_aliases_output = None + + description = f"Snippet `{name}` is now deleted." + if deleted_aliases_output: + description += f'\n\n{deleted_aliases_output}' + if edited_aliases_output: + description += f'\n\n{edited_aliases_output}' + embed = discord.Embed( title="Removed snippet", color=self.bot.main_color, - description=f"Snippet `{name}` is now deleted.", + description=description, ) self.bot.snippets.pop(name) await self.bot.config.update() From 3599f02874a8611ca3e3979d7596fecacd0c1faa Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Sat, 27 Nov 2021 21:42:41 +0530 Subject: [PATCH 060/225] make the help output for snippets list its aliases --- cogs/utility.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/cogs/utility.py b/cogs/utility.py index 89c4467109..e38fc0984b 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -184,7 +184,20 @@ async def send_error_message(self, error): val = self.context.bot.snippets.get(command) if val is not None: embed = discord.Embed(title=f"{command} is a snippet.", color=self.context.bot.main_color) - embed.add_field(name=f"`{command}` will send:", value=val) + embed.add_field(name=f"`{command}` will send:", value=val, inline=False) + + snippet_aliases = [] + for alias in self.context.bot.aliases: + if self.context.bot._resolve_snippet(alias) == command: + snippet_aliases.append(f'`{alias}`') + + if snippet_aliases: + embed.add_field( + name=f'Aliases to this snippet:', + value=','.join(snippet_aliases), + inline=False + ) + return await self.get_destination().send(embed=embed) val = self.context.bot.aliases.get(command) From ba93b9c4cf1cd279f5bcf1a148c25435a748dec3 Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Sat, 27 Nov 2021 23:54:44 +0530 Subject: [PATCH 061/225] Handle multi-word snippets --- bot.py | 22 +++++++++++++--------- cogs/utility.py | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/bot.py b/bot.py index df513ed8ad..f808448429 100644 --- a/bot.py +++ b/bot.py @@ -1010,9 +1010,17 @@ async def get_contexts(self, message, *, cls=commands.Context): invoker = view.get_word().lower() + # Check if a snippet is being called. + # This needs to be done before checking for aliases since + # snippets can have multiple words. + try: + snippet_text = self.snippets[message.content.removeprefix(invoked_prefix)] + except KeyError: + snippet_text = None + # Check if there is any aliases being called. alias = self.aliases.get(invoker) - if alias is not None: + if alias is not None and snippet_text is None: ctxs = [] aliases = normalize_alias(alias, message.content[len(f"{invoked_prefix}{invoker}") :]) if not aliases: @@ -1028,7 +1036,6 @@ async def get_contexts(self, message, *, cls=commands.Context): else: command = self._get_snippet_command() command_invocation_text = f'{invoked_prefix}{command} {snippet_text}' - view = StringView(invoked_prefix + command_invocation_text) ctx_ = cls(prefix=self.prefix, view=view, bot=self, message=message) ctx_.thread = thread @@ -1040,19 +1047,16 @@ async def get_contexts(self, message, *, cls=commands.Context): ctx.thread = thread - try: - snippet_text = self.snippets[invoker] - except KeyError: - # Process regular commands - ctx.command = self.all_commands.get(invoker) - ctx.invoked_with = invoker - else: + if snippet_text is not None: # Process snippets ctx.command = self._get_snippet_command() reply_view = StringView(f'{invoked_prefix}{ctx.command} {snippet_text}') discord.utils.find(reply_view.skip_string, prefixes) ctx.invoked_with = reply_view.get_word().lower() ctx.view = reply_view + else: + ctx.command = self.all_commands.get(invoker) + ctx.invoked_with = invoker return [ctx] diff --git a/cogs/utility.py b/cogs/utility.py index e38fc0984b..a3f5597519 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -1083,7 +1083,7 @@ async def make_alias(self, name, value, action): linked_command = view.get_word().lower() message = view.read_rest() - is_snippet = linked_command in self.bot.snippets and not message + is_snippet = val in self.bot.snippets if not self.bot.get_command(linked_command) and not is_snippet: alias_command = self.bot.aliases.get(linked_command) From 6041d37fbfe2990eb7f9ef2aedce40065b8ea341 Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Sun, 28 Nov 2021 00:08:18 +0530 Subject: [PATCH 062/225] Update the CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4409e12bb..803b5f0c1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Modmail now uses per-server avatars if applicable. ([GH #3048](https://github.com/kyb3r/modmail/issues/3048)) - Use discord relative timedeltas. ([GH #3046](https://github.com/kyb3r/modmail/issues/3046)) +- Snippets can be used in aliases. ([GH #3108](https://github.com/kyb3r/modmail/issues/3108)) ### Fixed From 893acc982f738c2384ddd2d274c974322bb8a697 Mon Sep 17 00:00:00 2001 From: Qwerty-133 <74311372+Qwerty-133@users.noreply.github.com> Date: Sun, 28 Nov 2021 17:45:43 +0530 Subject: [PATCH 063/225] Lint --- bot.py | 8 ++++---- cogs/modmail.py | 30 +++++++++++++++++------------- cogs/utility.py | 8 +++----- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/bot.py b/bot.py index f808448429..b01bc30ee9 100644 --- a/bot.py +++ b/bot.py @@ -100,7 +100,7 @@ def _resolve_snippet(self, name: str) -> typing.Optional[str]: return name try: - command, = parse_alias(self.aliases[name]) + (command,) = parse_alias(self.aliases[name]) except (KeyError, ValueError): # There is either no alias by this name present or the # alias has multiple steps. @@ -987,7 +987,7 @@ def _get_snippet_command(self) -> commands.Command: if self.config["anonymous_snippets"]: modifiers += "a" - return self.get_command(f'{modifiers}reply') + return self.get_command(f"{modifiers}reply") async def get_contexts(self, message, *, cls=commands.Context): """ @@ -1035,7 +1035,7 @@ async def get_contexts(self, message, *, cls=commands.Context): command_invocation_text = alias else: command = self._get_snippet_command() - command_invocation_text = f'{invoked_prefix}{command} {snippet_text}' + command_invocation_text = f"{invoked_prefix}{command} {snippet_text}" view = StringView(invoked_prefix + command_invocation_text) ctx_ = cls(prefix=self.prefix, view=view, bot=self, message=message) ctx_.thread = thread @@ -1050,7 +1050,7 @@ async def get_contexts(self, message, *, cls=commands.Context): if snippet_text is not None: # Process snippets ctx.command = self._get_snippet_command() - reply_view = StringView(f'{invoked_prefix}{ctx.command} {snippet_text}') + reply_view = StringView(f"{invoked_prefix}{ctx.command} {snippet_text}") discord.utils.find(reply_view.skip_string, prefixes) ctx.invoked_with = reply_view.get_word().lower() ctx.view = reply_view diff --git a/cogs/modmail.py b/cogs/modmail.py index 3d29523421..f06dc4339c 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -306,37 +306,41 @@ async def snippet_remove(self, ctx, *, name: str.lower): if name in self.bot.snippets: deleted_aliases, edited_aliases = self._fix_aliases(name) - deleted_aliases_string = ','.join(f'`{alias}`' for alias in deleted_aliases) + deleted_aliases_string = ",".join(f"`{alias}`" for alias in deleted_aliases) if len(deleted_aliases) == 1: - deleted_aliases_output = f'The `{deleted_aliases_string}` direct alias has been removed.' + deleted_aliases_output = f"The `{deleted_aliases_string}` direct alias has been removed." elif deleted_aliases: - deleted_aliases_output = f'The following direct aliases have been removed: {deleted_aliases_string}.' + deleted_aliases_output = ( + f"The following direct aliases have been removed: {deleted_aliases_string}." + ) else: deleted_aliases_output = None if len(edited_aliases) == 1: alias, val = edited_aliases.popitem() edited_aliases_output = ( - f'Steps pointing to this snippet have been removed from the `{alias}` alias' - f' (previous value: `{val}`).`' + f"Steps pointing to this snippet have been removed from the `{alias}` alias" + f" (previous value: `{val}`).`" ) elif edited_aliases: - alias_list = '\n'.join([ - f'- `{alias_name}` (previous value: `{val}`)' - for alias_name, val in edited_aliases.items() - ]) + alias_list = "\n".join( + [ + f"- `{alias_name}` (previous value: `{val}`)" + for alias_name, val in edited_aliases.items() + ] + ) edited_aliases_output = ( - f'Steps pointing to this snippet have been removed from the following aliases:' - f'\n\n{alias_list}' + f"Steps pointing to this snippet have been removed from the following aliases:" + f"\n\n{alias_list}" ) else: edited_aliases_output = None description = f"Snippet `{name}` is now deleted." if deleted_aliases_output: - description += f'\n\n{deleted_aliases_output}' + description += f"\n\n{deleted_aliases_output}" if edited_aliases_output: - description += f'\n\n{edited_aliases_output}' + description += f"\n\n{edited_aliases_output}" embed = discord.Embed( title="Removed snippet", diff --git a/cogs/utility.py b/cogs/utility.py index a3f5597519..26ae936ffc 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -189,13 +189,11 @@ async def send_error_message(self, error): snippet_aliases = [] for alias in self.context.bot.aliases: if self.context.bot._resolve_snippet(alias) == command: - snippet_aliases.append(f'`{alias}`') + snippet_aliases.append(f"`{alias}`") if snippet_aliases: embed.add_field( - name=f'Aliases to this snippet:', - value=','.join(snippet_aliases), - inline=False + name=f"Aliases to this snippet:", value=",".join(snippet_aliases), inline=False ) return await self.get_destination().send(embed=embed) @@ -1083,7 +1081,7 @@ async def make_alias(self, name, value, action): linked_command = view.get_word().lower() message = view.read_rest() - is_snippet = val in self.bot.snippets + is_snippet = val in self.bot.snippets if not self.bot.get_command(linked_command) and not is_snippet: alias_command = self.bot.aliases.get(linked_command) From aeb1128d83b2a9136cee411e7abe68dce428a18a Mon Sep 17 00:00:00 2001 From: Chris Lovering <chris.lovering.95@gmail.com> Date: Sun, 5 Dec 2021 21:28:56 +0000 Subject: [PATCH 064/225] Add git to Dockerfile Since discord.py is installed via git in requirements.txt the Dockerfile needs to have git installed to download it. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 34aba25ce6..76992efcc5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.9-slim as py FROM py as build -RUN apt update && apt install -y g++ +RUN apt update && apt install -y g++ git COPY requirements.txt / RUN pip install --prefix=/inst -U -r /requirements.txt From d90c1ecf0d05d2ae6e8aa95a62ab534a32cc3b02 Mon Sep 17 00:00:00 2001 From: Chris Lovering <chris.lovering.95@gmail.com> Date: Sun, 5 Dec 2021 23:04:15 +0000 Subject: [PATCH 065/225] Regenerate reqs.txt and use full python image This is so that all of the requirements for lottie are available within the image --- Dockerfile | 2 +- requirements.txt | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 76992efcc5..2906f4508f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9-slim as py +FROM python:3.9 as py FROM py as build diff --git a/requirements.txt b/requirements.txt index fb43d23e2b..737a58c219 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,21 +9,31 @@ aiohttp==3.7.4.post0 async-timeout==3.0.1; python_full_version >= '3.5.3' attrs==21.2.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +cairocffi==1.3.0; python_version >= '3.7' +cairosvg==2.5.2; python_version >= '3.5' +cffi==1.15.0 chardet==4.0.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' colorama==0.4.4 +cssselect2==0.4.1; python_version >= '3.6' +defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' dnspython==2.1.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' emoji==1.2.0 git+https://github.com/Rapptz/discord.py.git@45d498c1b76deaf3b394d17ccf56112fa691d160#egg=discord-py idna==3.3; python_version >= '3.5' isodate==0.6.0 +lottie[pdf]==0.6.10 motor==2.4.0 multidict==5.2.0; python_version >= '3.6' natural==0.2.0 parsedatetime==2.6 +pillow==8.4.0; python_version >= '3.6' +pycparser==2.21 pymongo[srv]==3.12.1 python-dateutil==2.8.2 python-dotenv==0.18.0 six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +tinycss2==1.1.0; python_version >= '3.6' typing-extensions==4.0.0; python_version >= '3.6' uvloop==0.16.0; sys_platform != 'win32' +webencodings==0.5.1 yarl==1.7.2; python_version >= '3.6' \ No newline at end of file From fa718e4023a2b52f90d228e37556e7a5e90225e8 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 21 Mar 2022 15:11:20 +0800 Subject: [PATCH 066/225] Update to dpy@97fe07edb2f3d0f5a980917fb6ee479bf396fd94 & async changes --- CHANGELOG.md | 4 + Pipfile | 2 +- Pipfile.lock | 708 ++++++++++++++++++++++++---------------------- bot.py | 162 +++++------ cogs/modmail.py | 4 +- cogs/plugins.py | 18 +- cogs/utility.py | 8 +- core/paginator.py | 4 +- core/thread.py | 11 +- pyproject.toml | 2 +- 10 files changed, 466 insertions(+), 457 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa4dea5219..209bbcfcea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,10 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Breaking +- Modmail now requires [`Message Content` privileged intent](https://support-dev.discord.com/hc/en-us/articles/4404772028055-Message-Content-Privileged-Intent-for-Verified-Bots). - Upgraded to discord.py v2.0 master ([internal changes](https://gist.github.com/apple502j/f75b4f24652f04de85c7084ffd73ec58), [GH #2990](https://github.com/kyb3r/modmail/issues/2990)). - Python 3.8 or higher is required. +- Asyncio changes ([gist](https://gist.github.com/Rapptz/6706e1c8f23ac27c98cee4dd985c8120)) ### Added @@ -41,11 +43,13 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Support LOTTIE stickers. ([GH #3119](https://github.com/kyb3r/modmail/issues/3119)) - Editing notes now work. ([GH #3094](https://github.com/kyb3r/modmail/issues/3094)) - Commands now work in threads. +- Audit log searching now properly works. ### Internal - Improve regex parsing of channel topics. ([GH #3114](https://github.com/kyb3r/modmail/issues/3114), [PR #3111](https://github.com/kyb3r/modmail/pull/3111)) - Add warning if deploying on a developmental version. +- Extensions are now loaded `on_connect`. # v3.10.3 diff --git a/Pipfile b/Pipfile index a78db95d18..04d998cbc8 100644 --- a/Pipfile +++ b/Pipfile @@ -11,7 +11,7 @@ pylint = "~=2.9.3" [packages] aiohttp = "==3.7.4.post0" colorama = "~=0.4.4" # Doesn't officially support Python 3.9 yet, v0.4.5 will support 3.9 -"discord.py" = {ref = "45d498c1b76deaf3b394d17ccf56112fa691d160", git = "https://github.com/Rapptz/discord.py.git"} +"discord.py" = {ref = "97fe07edb2f3d0f5a980917fb6ee479bf396fd94", git = "https://github.com/Rapptz/discord.py.git"} emoji = "~=1.2.0" isodate = "~=0.6.0" motor = "~=2.4.0" diff --git a/Pipfile.lock b/Pipfile.lock index 1fa9e5e64a..5cd3d63616 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "29d6f377cdb874102deb4df1406ff6d0a66834fcb89660f3c9599a2343cda038" + "sha256": "5f3ca86a89bbc9bcda36bdb3503c91f81ff9c5e12409c3ad056524aa920f4fad" }, "pipfile-spec": 6, "requires": { @@ -69,11 +69,11 @@ }, "attrs": { "hashes": [ - "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1", - "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb" + "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", + "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==21.2.0" + "version": "==21.4.0" }, "cairocffi": { "hashes": [ @@ -163,11 +163,11 @@ }, "cssselect2": { "hashes": [ - "sha256:2f4a9f20965367bae459e3bb42561f7927e0cfe5b7ea1692757cf67ef5d7dace", - "sha256:93fbb9af860e95dd40bf18c3b2b6ed99189a07c0f29ba76f9c5be71344664ec8" + "sha256:8d4690bce5f25013262997e64cef3e7bade877d3ef126f9cc624e5b1f294d934", + "sha256:d98a7bbdd8ebc46093279195d669a3359bd5a23f90c19e82c19d9eeef333e617" ], - "markers": "python_version >= '3.6'", - "version": "==0.4.1" + "markers": "python_version >= '3.7'", + "version": "==0.5.0" }, "defusedxml": { "hashes": [ @@ -179,19 +179,19 @@ }, "discord-py": { "git": "https://github.com/Rapptz/discord.py.git", - "ref": "45d498c1b76deaf3b394d17ccf56112fa691d160" + "ref": "97fe07edb2f3d0f5a980917fb6ee479bf396fd94" }, "discord.py": { "git": "https://github.com/Rapptz/discord.py.git", - "ref": "45d498c1b76deaf3b394d17ccf56112fa691d160" + "ref": "97fe07edb2f3d0f5a980917fb6ee479bf396fd94" }, "dnspython": { "hashes": [ - "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216", - "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4" + "sha256:0f7569a4a6ff151958b64304071d370daa3243d15941a7beedf0c9fe5105603e", + "sha256:a851e51367fb93e9e1361732c1d60dab63eff98712e503ea7d92e6eccb109b4f" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.1.0" + "version": "==2.2.1" }, "emoji": { "hashes": [ @@ -211,11 +211,11 @@ }, "isodate": { "hashes": [ - "sha256:2e364a3d5759479cdb2d37cce6b9376ea504db2ff90252a2e5b7cc89cc9ff2d8", - "sha256:aa4d33c06640f5352aca96e4b81afd8ab3b47337cc12089822d6f322ac772c81" + "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96", + "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9" ], "index": "pypi", - "version": "==0.6.0" + "version": "==0.6.1" }, "lottie": { "extras": [ @@ -237,81 +237,68 @@ }, "multidict": { "hashes": [ - "sha256:06560fbdcf22c9387100979e65b26fba0816c162b888cb65b845d3def7a54c9b", - "sha256:067150fad08e6f2dd91a650c7a49ba65085303fcc3decbd64a57dc13a2733031", - "sha256:0a2cbcfbea6dc776782a444db819c8b78afe4db597211298dd8b2222f73e9cd0", - "sha256:0dd1c93edb444b33ba2274b66f63def8a327d607c6c790772f448a53b6ea59ce", - "sha256:0fed465af2e0eb6357ba95795d003ac0bdb546305cc2366b1fc8f0ad67cc3fda", - "sha256:116347c63ba049c1ea56e157fa8aa6edaf5e92925c9b64f3da7769bdfa012858", - "sha256:1b4ac3ba7a97b35a5ccf34f41b5a8642a01d1e55454b699e5e8e7a99b5a3acf5", - "sha256:1c7976cd1c157fa7ba5456ae5d31ccdf1479680dc9b8d8aa28afabc370df42b8", - "sha256:246145bff76cc4b19310f0ad28bd0769b940c2a49fc601b86bfd150cbd72bb22", - "sha256:25cbd39a9029b409167aa0a20d8a17f502d43f2efebfe9e3ac019fe6796c59ac", - "sha256:28e6d883acd8674887d7edc896b91751dc2d8e87fbdca8359591a13872799e4e", - "sha256:2d1d55cdf706ddc62822d394d1df53573d32a7a07d4f099470d3cb9323b721b6", - "sha256:2e77282fd1d677c313ffcaddfec236bf23f273c4fba7cdf198108f5940ae10f5", - "sha256:32fdba7333eb2351fee2596b756d730d62b5827d5e1ab2f84e6cbb287cc67fe0", - "sha256:35591729668a303a02b06e8dba0eb8140c4a1bfd4c4b3209a436a02a5ac1de11", - "sha256:380b868f55f63d048a25931a1632818f90e4be71d2081c2338fcf656d299949a", - "sha256:3822c5894c72e3b35aae9909bef66ec83e44522faf767c0ad39e0e2de11d3b55", - "sha256:38ba256ee9b310da6a1a0f013ef4e422fca30a685bcbec86a969bd520504e341", - "sha256:3bc3b1621b979621cee9f7b09f024ec76ec03cc365e638126a056317470bde1b", - "sha256:3d2d7d1fff8e09d99354c04c3fd5b560fb04639fd45926b34e27cfdec678a704", - "sha256:517d75522b7b18a3385726b54a081afd425d4f41144a5399e5abd97ccafdf36b", - "sha256:5f79c19c6420962eb17c7e48878a03053b7ccd7b69f389d5831c0a4a7f1ac0a1", - "sha256:5f841c4f14331fd1e36cbf3336ed7be2cb2a8f110ce40ea253e5573387db7621", - "sha256:637c1896497ff19e1ee27c1c2c2ddaa9f2d134bbb5e0c52254361ea20486418d", - "sha256:6ee908c070020d682e9b42c8f621e8bb10c767d04416e2ebe44e37d0f44d9ad5", - "sha256:77f0fb7200cc7dedda7a60912f2059086e29ff67cefbc58d2506638c1a9132d7", - "sha256:7878b61c867fb2df7a95e44b316f88d5a3742390c99dfba6c557a21b30180cac", - "sha256:78c106b2b506b4d895ddc801ff509f941119394b89c9115580014127414e6c2d", - "sha256:8b911d74acdc1fe2941e59b4f1a278a330e9c34c6c8ca1ee21264c51ec9b67ef", - "sha256:93de39267c4c676c9ebb2057e98a8138bade0d806aad4d864322eee0803140a0", - "sha256:9416cf11bcd73c861267e88aea71e9fcc35302b3943e45e1dbb4317f91a4b34f", - "sha256:94b117e27efd8e08b4046c57461d5a114d26b40824995a2eb58372b94f9fca02", - "sha256:9815765f9dcda04921ba467957be543423e5ec6a1136135d84f2ae092c50d87b", - "sha256:98ec9aea6223adf46999f22e2c0ab6cf33f5914be604a404f658386a8f1fba37", - "sha256:a37e9a68349f6abe24130846e2f1d2e38f7ddab30b81b754e5a1fde32f782b23", - "sha256:a43616aec0f0d53c411582c451f5d3e1123a68cc7b3475d6f7d97a626f8ff90d", - "sha256:a4771d0d0ac9d9fe9e24e33bed482a13dfc1256d008d101485fe460359476065", - "sha256:a5635bcf1b75f0f6ef3c8a1ad07b500104a971e38d3683167b9454cb6465ac86", - "sha256:a9acb76d5f3dd9421874923da2ed1e76041cb51b9337fd7f507edde1d86535d6", - "sha256:ac42181292099d91217a82e3fa3ce0e0ddf3a74fd891b7c2b347a7f5aa0edded", - "sha256:b227345e4186809d31f22087d0265655114af7cda442ecaf72246275865bebe4", - "sha256:b61f85101ef08cbbc37846ac0e43f027f7844f3fade9b7f6dd087178caedeee7", - "sha256:b70913cbf2e14275013be98a06ef4b412329fe7b4f83d64eb70dce8269ed1e1a", - "sha256:b9aad49466b8d828b96b9e3630006234879c8d3e2b0a9d99219b3121bc5cdb17", - "sha256:baf1856fab8212bf35230c019cde7c641887e3fc08cadd39d32a421a30151ea3", - "sha256:bd6c9c50bf2ad3f0448edaa1a3b55b2e6866ef8feca5d8dbec10ec7c94371d21", - "sha256:c1ff762e2ee126e6f1258650ac641e2b8e1f3d927a925aafcfde943b77a36d24", - "sha256:c30ac9f562106cd9e8071c23949a067b10211917fdcb75b4718cf5775356a940", - "sha256:c9631c642e08b9fff1c6255487e62971d8b8e821808ddd013d8ac058087591ac", - "sha256:cdd68778f96216596218b4e8882944d24a634d984ee1a5a049b300377878fa7c", - "sha256:ce8cacda0b679ebc25624d5de66c705bc53dcc7c6f02a7fb0f3ca5e227d80422", - "sha256:cfde464ca4af42a629648c0b0d79b8f295cf5b695412451716531d6916461628", - "sha256:d3def943bfd5f1c47d51fd324df1e806d8da1f8e105cc7f1c76a1daf0f7e17b0", - "sha256:d9b668c065968c5979fe6b6fa6760bb6ab9aeb94b75b73c0a9c1acf6393ac3bf", - "sha256:da7d57ea65744d249427793c042094c4016789eb2562576fb831870f9c878d9e", - "sha256:dc3a866cf6c13d59a01878cd806f219340f3e82eed514485e094321f24900677", - "sha256:df23c83398715b26ab09574217ca21e14694917a0c857e356fd39e1c64f8283f", - "sha256:dfc924a7e946dd3c6360e50e8f750d51e3ef5395c95dc054bc9eab0f70df4f9c", - "sha256:e4a67f1080123de76e4e97a18d10350df6a7182e243312426d508712e99988d4", - "sha256:e5283c0a00f48e8cafcecadebfa0ed1dac8b39e295c7248c44c665c16dc1138b", - "sha256:e58a9b5cc96e014ddf93c2227cbdeca94b56a7eb77300205d6e4001805391747", - "sha256:e6453f3cbeb78440747096f239d282cc57a2997a16b5197c9bc839099e1633d0", - "sha256:e6c4fa1ec16e01e292315ba76eb1d012c025b99d22896bd14a66628b245e3e01", - "sha256:e7d81ce5744757d2f05fc41896e3b2ae0458464b14b5a2c1e87a6a9d69aefaa8", - "sha256:ea21d4d5104b4f840b91d9dc8cbc832aba9612121eaba503e54eaab1ad140eb9", - "sha256:ecc99bce8ee42dcad15848c7885197d26841cb24fa2ee6e89d23b8993c871c64", - "sha256:f0bb0973f42ffcb5e3537548e0767079420aefd94ba990b61cf7bb8d47f4916d", - "sha256:f19001e790013ed580abfde2a4465388950728861b52f0da73e8e8a9418533c0", - "sha256:f76440e480c3b2ca7f843ff8a48dc82446b86ed4930552d736c0bac507498a52", - "sha256:f9bef5cff994ca3026fcc90680e326d1a19df9841c5e3d224076407cc21471a1", - "sha256:fc66d4016f6e50ed36fb39cd287a3878ffcebfa90008535c62e0e90a7ab713ae", - "sha256:fd77c8f3cba815aa69cb97ee2b2ef385c7c12ada9c734b0f3b32e26bb88bbf1d" + "sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60", + "sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c", + "sha256:0556a1d4ea2d949efe5fd76a09b4a82e3a4a30700553a6725535098d8d9fb672", + "sha256:05f6949d6169878a03e607a21e3b862eaf8e356590e8bdae4227eedadacf6e51", + "sha256:07a017cfa00c9890011628eab2503bee5872f27144936a52eaab449be5eaf032", + "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2", + "sha256:19adcfc2a7197cdc3987044e3f415168fc5dc1f720c932eb1ef4f71a2067e08b", + "sha256:19d9bad105dfb34eb539c97b132057a4e709919ec4dd883ece5838bcbf262b80", + "sha256:225383a6603c086e6cef0f2f05564acb4f4d5f019a4e3e983f572b8530f70c88", + "sha256:23b616fdc3c74c9fe01d76ce0d1ce872d2d396d8fa8e4899398ad64fb5aa214a", + "sha256:2957489cba47c2539a8eb7ab32ff49101439ccf78eab724c828c1a54ff3ff98d", + "sha256:2d36e929d7f6a16d4eb11b250719c39560dd70545356365b494249e2186bc389", + "sha256:2e4a0785b84fb59e43c18a015ffc575ba93f7d1dbd272b4cdad9f5134b8a006c", + "sha256:3368bf2398b0e0fcbf46d85795adc4c259299fec50c1416d0f77c0a843a3eed9", + "sha256:373ba9d1d061c76462d74e7de1c0c8e267e9791ee8cfefcf6b0b2495762c370c", + "sha256:4070613ea2227da2bfb2c35a6041e4371b0af6b0be57f424fe2318b42a748516", + "sha256:45183c96ddf61bf96d2684d9fbaf6f3564d86b34cb125761f9a0ef9e36c1d55b", + "sha256:4571f1beddff25f3e925eea34268422622963cd8dc395bb8778eb28418248e43", + "sha256:47e6a7e923e9cada7c139531feac59448f1f47727a79076c0b1ee80274cd8eee", + "sha256:47fbeedbf94bed6547d3aa632075d804867a352d86688c04e606971595460227", + "sha256:497988d6b6ec6ed6f87030ec03280b696ca47dbf0648045e4e1d28b80346560d", + "sha256:4bae31803d708f6f15fd98be6a6ac0b6958fcf68fda3c77a048a4f9073704aae", + "sha256:50bd442726e288e884f7be9071016c15a8742eb689a593a0cac49ea093eef0a7", + "sha256:514fe2b8d750d6cdb4712346a2c5084a80220821a3e91f3f71eec11cf8d28fd4", + "sha256:5774d9218d77befa7b70d836004a768fb9aa4fdb53c97498f4d8d3f67bb9cfa9", + "sha256:5fdda29a3c7e76a064f2477c9aab1ba96fd94e02e386f1e665bca1807fc5386f", + "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013", + "sha256:626fe10ac87851f4cffecee161fc6f8f9853f0f6f1035b59337a51d29ff3b4f9", + "sha256:6701bf8a5d03a43375909ac91b6980aea74b0f5402fbe9428fc3f6edf5d9677e", + "sha256:684133b1e1fe91eda8fa7447f137c9490a064c6b7f392aa857bba83a28cfb693", + "sha256:6f3cdef8a247d1eafa649085812f8a310e728bdf3900ff6c434eafb2d443b23a", + "sha256:75bdf08716edde767b09e76829db8c1e5ca9d8bb0a8d4bd94ae1eafe3dac5e15", + "sha256:7c40b7bbece294ae3a87c1bc2abff0ff9beef41d14188cda94ada7bcea99b0fb", + "sha256:8004dca28e15b86d1b1372515f32eb6f814bdf6f00952699bdeb541691091f96", + "sha256:8064b7c6f0af936a741ea1efd18690bacfbae4078c0c385d7c3f611d11f0cf87", + "sha256:89171b2c769e03a953d5969b2f272efa931426355b6c0cb508022976a17fd376", + "sha256:8cbf0132f3de7cc6c6ce00147cc78e6439ea736cee6bca4f068bcf892b0fd658", + "sha256:9cc57c68cb9139c7cd6fc39f211b02198e69fb90ce4bc4a094cf5fe0d20fd8b0", + "sha256:a007b1638e148c3cfb6bf0bdc4f82776cef0ac487191d093cdc316905e504071", + "sha256:a2c34a93e1d2aa35fbf1485e5010337c72c6791407d03aa5f4eed920343dd360", + "sha256:a45e1135cb07086833ce969555df39149680e5471c04dfd6a915abd2fc3f6dbc", + "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3", + "sha256:aef9cc3d9c7d63d924adac329c33835e0243b5052a6dfcbf7732a921c6e918ba", + "sha256:b9d153e7f1f9ba0b23ad1568b3b9e17301e23b042c23870f9ee0522dc5cc79e8", + "sha256:bfba7c6d5d7c9099ba21f84662b037a0ffd4a5e6b26ac07d19e423e6fdf965a9", + "sha256:c207fff63adcdf5a485969131dc70e4b194327666b7e8a87a97fbc4fd80a53b2", + "sha256:d0509e469d48940147e1235d994cd849a8f8195e0bca65f8f5439c56e17872a3", + "sha256:d16cce709ebfadc91278a1c005e3c17dd5f71f5098bfae1035149785ea6e9c68", + "sha256:d48b8ee1d4068561ce8033d2c344cf5232cb29ee1a0206a7b828c79cbc5982b8", + "sha256:de989b195c3d636ba000ee4281cd03bb1234635b124bf4cd89eeee9ca8fcb09d", + "sha256:e07c8e79d6e6fd37b42f3250dba122053fddb319e84b55dd3a8d6446e1a7ee49", + "sha256:e2c2e459f7050aeb7c1b1276763364884595d47000c1cddb51764c0d8976e608", + "sha256:e5b20e9599ba74391ca0cfbd7b328fcc20976823ba19bc573983a25b32e92b57", + "sha256:e875b6086e325bab7e680e4316d667fc0e5e174bb5611eb16b3ea121c8951b86", + "sha256:f4f052ee022928d34fe1f4d2bc743f32609fb79ed9c49a1710a5ad6b2198db20", + "sha256:fcb91630817aa8b9bc4a74023e4198480587269c272c58b3279875ed7235c293", + "sha256:fd9fc9c4849a07f3635ccffa895d57abce554b467d611a5009ba4f39b78a8849", + "sha256:feba80698173761cddd814fa22e88b0661e98cb810f9f986c54aa34d281e4937", + "sha256:feea820722e69451743a3d56ad74948b68bf456984d63c1a92e8347b7b88452d" ], - "markers": "python_version >= '3.6'", - "version": "==5.2.0" + "markers": "python_version >= '3.7'", + "version": "==6.0.2" }, "natural": { "hashes": [ @@ -330,50 +317,44 @@ }, "pillow": { "hashes": [ - "sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76", - "sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585", - "sha256:0b052a619a8bfcf26bd8b3f48f45283f9e977890263e4571f2393ed8898d331b", - "sha256:1394a6ad5abc838c5cd8a92c5a07535648cdf6d09e8e2d6df916dfa9ea86ead8", - "sha256:1bc723b434fbc4ab50bb68e11e93ce5fb69866ad621e3c2c9bdb0cd70e345f55", - "sha256:244cf3b97802c34c41905d22810846802a3329ddcb93ccc432870243211c79fc", - "sha256:25a49dc2e2f74e65efaa32b153527fc5ac98508d502fa46e74fa4fd678ed6645", - "sha256:2e4440b8f00f504ee4b53fe30f4e381aae30b0568193be305256b1462216feff", - "sha256:3862b7256046fcd950618ed22d1d60b842e3a40a48236a5498746f21189afbbc", - "sha256:3eb1ce5f65908556c2d8685a8f0a6e989d887ec4057326f6c22b24e8a172c66b", - "sha256:3f97cfb1e5a392d75dd8b9fd274d205404729923840ca94ca45a0af57e13dbe6", - "sha256:493cb4e415f44cd601fcec11c99836f707bb714ab03f5ed46ac25713baf0ff20", - "sha256:4acc0985ddf39d1bc969a9220b51d94ed51695d455c228d8ac29fcdb25810e6e", - "sha256:5503c86916d27c2e101b7f71c2ae2cddba01a2cf55b8395b0255fd33fa4d1f1a", - "sha256:5b7bb9de00197fb4261825c15551adf7605cf14a80badf1761d61e59da347779", - "sha256:5e9ac5f66616b87d4da618a20ab0a38324dbe88d8a39b55be8964eb520021e02", - "sha256:620582db2a85b2df5f8a82ddeb52116560d7e5e6b055095f04ad828d1b0baa39", - "sha256:62cc1afda735a8d109007164714e73771b499768b9bb5afcbbee9d0ff374b43f", - "sha256:70ad9e5c6cb9b8487280a02c0ad8a51581dcbbe8484ce058477692a27c151c0a", - "sha256:72b9e656e340447f827885b8d7a15fc8c4e68d410dc2297ef6787eec0f0ea409", - "sha256:72cbcfd54df6caf85cc35264c77ede902452d6df41166010262374155947460c", - "sha256:792e5c12376594bfcb986ebf3855aa4b7c225754e9a9521298e460e92fb4a488", - "sha256:7b7017b61bbcdd7f6363aeceb881e23c46583739cb69a3ab39cb384f6ec82e5b", - "sha256:81f8d5c81e483a9442d72d182e1fb6dcb9723f289a57e8030811bac9ea3fef8d", - "sha256:82aafa8d5eb68c8463b6e9baeb4f19043bb31fefc03eb7b216b51e6a9981ae09", - "sha256:84c471a734240653a0ec91dec0996696eea227eafe72a33bd06c92697728046b", - "sha256:8c803ac3c28bbc53763e6825746f05cc407b20e4a69d0122e526a582e3b5e153", - "sha256:93ce9e955cc95959df98505e4608ad98281fff037350d8c2671c9aa86bcf10a9", - "sha256:9a3e5ddc44c14042f0844b8cf7d2cd455f6cc80fd7f5eefbe657292cf601d9ad", - "sha256:a4901622493f88b1a29bd30ec1a2f683782e57c3c16a2dbc7f2595ba01f639df", - "sha256:a5a4532a12314149d8b4e4ad8ff09dde7427731fcfa5917ff16d0291f13609df", - "sha256:b8831cb7332eda5dc89b21a7bce7ef6ad305548820595033a4b03cf3091235ed", - "sha256:b8e2f83c56e141920c39464b852de3719dfbfb6e3c99a2d8da0edf4fb33176ed", - "sha256:c70e94281588ef053ae8998039610dbd71bc509e4acbc77ab59d7d2937b10698", - "sha256:c8a17b5d948f4ceeceb66384727dde11b240736fddeda54ca740b9b8b1556b29", - "sha256:d82cdb63100ef5eedb8391732375e6d05993b765f72cb34311fab92103314649", - "sha256:d89363f02658e253dbd171f7c3716a5d340a24ee82d38aab9183f7fdf0cdca49", - "sha256:d99ec152570e4196772e7a8e4ba5320d2d27bf22fdf11743dd882936ed64305b", - "sha256:ddc4d832a0f0b4c52fff973a0d44b6c99839a9d016fe4e6a1cb8f3eea96479c2", - "sha256:e3dacecfbeec9a33e932f00c6cd7996e62f53ad46fbe677577394aaa90ee419a", - "sha256:eb9fc393f3c61f9054e1ed26e6fe912c7321af2f41ff49d3f83d05bacf22cc78" + "sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97", + "sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049", + "sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c", + "sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae", + "sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28", + "sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030", + "sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56", + "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976", + "sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e", + "sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e", + "sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f", + "sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b", + "sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a", + "sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e", + "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa", + "sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7", + "sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00", + "sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838", + "sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360", + "sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b", + "sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a", + "sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd", + "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4", + "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70", + "sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204", + "sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc", + "sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b", + "sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669", + "sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7", + "sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e", + "sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c", + "sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092", + "sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c", + "sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5", + "sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac" ], - "markers": "python_version >= '3.6'", - "version": "==8.4.0" + "markers": "python_version >= '3.7'", + "version": "==9.0.1" }, "pycparser": { "hashes": [ @@ -387,116 +368,116 @@ "srv" ], "hashes": [ - "sha256:02e0c088f189ca69fac094cb5f851b43bbbd7cec42114495777d4d8f297f7f8a", - "sha256:138248c542051eb462f88b50b0267bd5286d6661064bab06faa0ef6ac30cdb4b", - "sha256:13a7c6d055af58a1e9c505e736da8b6a2e95ccc8cec10b008143f7a536e5de8a", - "sha256:13d74bf3435c1e58d8fafccc0d5e87f246ae2c6e9cbef4b35e32a1c3759e354f", - "sha256:15dae01341571d0af51526b7a21648ca575e9375e16ba045c9860848dfa8952f", - "sha256:17238115e6d37f5423b046cb829f1ca02c4ea7edb163f5b8b88e0c975dc3fec9", - "sha256:180b405e17b90a877ea5dbc5efe7f4c171af4c89323148e100c0f12cedb86f12", - "sha256:1821ce4e5a293313947fd017bbd2d2535aa6309680fa29b33d0442d15da296ec", - "sha256:1a7b138a04fdd17849930dc8bf664002e17db38448850bfb96d200c9c5a8b3a1", - "sha256:1c4e51a3b69789b6f468a8e881a13f2d1e8f5e99e41f80fd44845e6ec0f701e1", - "sha256:1d55982e5335925c55e2b87467043866ce72bd30ea7e7e3eeed6ec3d95a806d4", - "sha256:1fa6f08ddb6975371777f97592d35c771e713ee2250e55618148a5e57e260aff", - "sha256:2174d3279b8e2b6d7613b338f684cd78ff7adf1e7ec5b7b7bde5609a129c9898", - "sha256:2462a68f6675da548e333fa299d8e9807e00f95a4d198cfe9194d7be69f40c9b", - "sha256:25fd76deabe9ea37c8360c362b32f702cc095a208dd1c5328189938ca7685847", - "sha256:287c2a0063267c1458c4ddf528b44063ce7f376a6436eea5bccd7f625bbc3b5e", - "sha256:2d3abe548a280b49269c7907d5b71199882510c484d680a5ea7860f30c4a695f", - "sha256:2fa101bb23619120673899694a65b094364269e597f551a87c4bdae3a474d726", - "sha256:2fda3b3fb5c0d159195ab834b322a23808f1b059bcc7e475765abeddee6a2529", - "sha256:303531649fa45f96b694054c1aa02f79bda32ef57affe42c5c339336717eed74", - "sha256:36806ee53a85c3ba73939652f2ced2961e6a77cfbae385cd83f2e24cd97964b7", - "sha256:37a63da5ee623acdf98e6d511171c8a5827a6106b0712c18af4441ef4f11e6be", - "sha256:3a2fcbd04273a509fa85285d9eccf17ab65ce440bd4f5e5a58c978e563cd9e9a", - "sha256:3b40e36d3036bfe69ba63ec8e746a390721f75467085a0384b528e1dda532c69", - "sha256:4168b6c425d783e81723fc3dc382d374a228ff29530436a472a36d9f27593e73", - "sha256:444c00ebc20f2f9dc62e34f7dc9453dc2f5f5a72419c8dccad6e26d546c35712", - "sha256:45d6b47d70ed44e3c40bef618ed61866c48176e7e5dff80d06d8b1a6192e8584", - "sha256:460bdaa3f65ddb5b7474ae08589a1763b5da1a78b8348351b9ba1c63b459d67d", - "sha256:47ed77f62c8417a86f9ad158b803f3459a636386cb9d3d4e9e7d6a82d051f907", - "sha256:48722e91981bb22a16b0431ea01da3e1cc5b96805634d3b8d3c2a5315c1ce7f1", - "sha256:49b0d92724d3fce1174fd30b0b428595072d5c6b14d6203e46a9ea347ae7b439", - "sha256:4a2d73a9281faefb273a5448f6d25f44ebd311ada9eb79b6801ae890508fe231", - "sha256:4f4bc64fe9cbd70d46f519f1e88c9e4677f7af18ab9cd4942abce2bcfa7549c3", - "sha256:5067c04d3b19c820faac6342854d887ade58e8d38c3db79b68c2a102bbb100e7", - "sha256:51437c77030bed72d57d8a61e22758e3c389b13fea7787c808030002bb05ca39", - "sha256:515e4708d6567901ffc06476a38abe2c9093733f52638235d9f149579c1d3de0", - "sha256:5183b698d6542219e4135de583b57bc6286bd37df7f645b688278eb919bfa785", - "sha256:56feb80ea1f5334ccab9bd16a5161571ab70392e51fcc752fb8a1dc67125f663", - "sha256:573e2387d0686976642142c50740dfc4d3494cc627e2a7d22782b99f70879055", - "sha256:58a67b3800476232f9989e533d0244060309451b436d46670a53e6d189f1a7e7", - "sha256:5e3833c001a04aa06a28c6fd9628256862a654c09b0f81c07734b5629bc014ab", - "sha256:5f5fe59328838fa28958cc06ecf94be585726b97d637012f168bc3c7abe4fd81", - "sha256:6235bf2157aa46e53568ed79b70603aa8874baa202d5d1de82fa0eb917696e73", - "sha256:63be03f7ae1e15e72a234637ec7941ef229c7ab252c9ff6af48bba1e5418961c", - "sha256:65f159c445761cab04b665fc448b3fc008aebc98e54fdcbfd1aff195ef1b1408", - "sha256:67e0b2ad3692f6d0335ae231a40de55ec395b6c2e971ad6f55b162244d1ec542", - "sha256:68409171ab2aa7ccd6e8e839233e4b8ddeec246383c9a3698614e814739356f9", - "sha256:6a96c04ce39d66df60d9ce89f4c254c4967bc7d9e2e2c52adc58f47be826ee96", - "sha256:6ead0126fb4424c6c6a4fdc603d699a9db7c03cdb8eac374c352a75fec8a820a", - "sha256:6eb6789f26c398c383225e1313c8e75a7d290d323b8eaf65f3f3ddd0eb8a5a3c", - "sha256:6f07888e3b73c0dfa46f12d098760494f5f23fd66923a6615edfe486e6a7649c", - "sha256:6f0f0a10f128ea0898e607d351ebfabf70941494fc94e87f12c76e2894d8e6c4", - "sha256:704879b6a54c45ad76cea7c6789c1ae7185050acea7afd15b58318fa1932ed45", - "sha256:7117bfd8827cfe550f65a3c399dcd6e02226197a91c6d11a3540c3e8efc686d6", - "sha256:712de1876608fd5d76abc3fc8ec55077278dd5044073fbe9492631c9a2c58351", - "sha256:75c7ef67b4b8ec070e7a4740764f6c03ec9246b59d95e2ae45c029d41cb9efa1", - "sha256:77dddf596fb065de29fb39992fbc81301f7fd0003be649b7fa7448c77ca53bed", - "sha256:7abc87e45b572eb6d17a50422e69a9e5d6f13e691e821fe2312df512500faa50", - "sha256:7d8cdd2f070c71366e64990653522cce84b08dc26ab0d1fa19aa8d14ee0cf9ba", - "sha256:81ce5f871f5d8e82615c8bd0b34b68a9650204c8b1a04ce7890d58c98eb66e39", - "sha256:837cdef094f39c6f4a2967abc646a412999c2540fbf5d3cce1dd3b671f4b876c", - "sha256:849e641cfed05c75d772f9e9018f42c5fbd00655d43d52da1b9c56346fd3e4cc", - "sha256:87114b995506e7584cf3daf891e419b5f6e7e383e7df6267494da3a76312aa22", - "sha256:87db421c9eb915b8d9a9a13c5b2ee338350e36ee83e26ff0adfc48abc5db3ac3", - "sha256:8851544168703fb519e95556e3b463fca4beeef7ed3f731d81a68c8268515d9d", - "sha256:891f541c7ed29b95799da0cd249ae1db1842777b564e8205a197b038c5df6135", - "sha256:8f87f53c9cd89010ae45490ec2c963ff18b31f5f290dc08b04151709589fe8d9", - "sha256:9641be893ccce7d192a0094efd0a0d9f1783a1ebf314b4128f8a27bfadb8a77c", - "sha256:979e34db4f3dc5710c18db437aaf282f691092b352e708cb2afd4df287698c76", - "sha256:9b62d84478f471fdb0dcea3876acff38f146bd23cbdbed15074fb4622064ec2e", - "sha256:a472ca3d43d33e596ff5836c6cc71c3e61be33f44fe1cfdab4a1100f4af60333", - "sha256:a5dbeeea6a375fbd79448b48a54c46fc9351611a03ef8398d2a40b684ce46194", - "sha256:a7430f3987d232e782304c109be1d0e6fff46ca6405cb2479e4d8d08cd29541e", - "sha256:a81e52dbf95f236a0c89a5abcd2b6e1331da0c0312f471c73fae76c79d2acf6b", - "sha256:aa434534cc91f51a85e3099dc257ee8034b3d2be77f2ca58fb335a686e3a681f", - "sha256:ab27d6d7d41a66d9e54269a290d27cd5c74f08e9add0054a754b4821026c4f42", - "sha256:adb37bf22d25a51b84d989a2a5c770d4514ac590201eea1cb50ce8c9c5257f1d", - "sha256:afb16330ab6efbbf995375ad94e970fa2f89bb46bd10d854b7047620fdb0d67d", - "sha256:b1b06038c9940a49c73db0aeb0f6809b308e198da1326171768cf68d843af521", - "sha256:b1e6d1cf4bd6552b5f519432cce1530c09e6b0aab98d44803b991f7e880bd332", - "sha256:bf2d9d62178bb5c05e77d40becf89c309b1966fbcfb5c306238f81bf1ec2d6a2", - "sha256:bfd073fea04061019a103a288847846b5ef40dfa2f73b940ed61e399ca95314f", - "sha256:c04e84ccf590933a266180286d8b6a5fc844078a5d934432628301bd8b5f9ca7", - "sha256:c0947d7be30335cb4c3d5d0983d8ebc8294ae52503cf1d596c926f7e7183900b", - "sha256:c2a17752f97a942bdb4ff4a0516a67c5ade1658ebe1ab2edacdec0b42e39fa75", - "sha256:c4653830375ab019b86d218c749ad38908b74182b2863d09936aa8d7f990d30e", - "sha256:c660fd1e4a4b52f79f7d134a3d31d452948477b7f46ff5061074a534c5805ba6", - "sha256:cb48ff6cc6109190e1ccf8ea1fc71cc244c9185813ce7d1c415dce991cfb8709", - "sha256:cef2675004d85d85a4ccc24730b73a99931547368d18ceeed1259a2d9fcddbc1", - "sha256:d1b98539b0de822b6f717498e59ae3e5ae2e7f564370ab513e6d0c060753e447", - "sha256:d6c6989c10008ac70c2bb2ad2b940fcfe883712746c89f7e3308c14c213a70d7", - "sha256:db3efec9dcecd96555d752215797816da40315d61878f90ca39c8e269791bf17", - "sha256:dc4749c230a71b34db50ac2481d9008bb17b67c92671c443c3b40e192fbea78e", - "sha256:dcf906c1f7a33e4222e4bff18da1554d69323bc4dd95fe867a6fa80709ee5f93", - "sha256:e2bccadbe313b11704160aaba5eec95d2da1aa663f02f41d2d1520d02bbbdcd5", - "sha256:e30cce3cc86d6082c8596b3fbee0d4f54bc4d337a4fa1bf536920e2e319e24f0", - "sha256:e5d6428b8b422ba5205140e8be11722fa7292a0bedaa8bc80fb34c92eb19ba45", - "sha256:e841695b5dbea38909ab2dbf17e91e9a823412d8d88d1ef77f1b94a7bc551c0f", - "sha256:eb65ec0255a0fccc47c87d44e505ef5180bfd71690bd5f84161b1f23949fb209", - "sha256:ed20ec5a01c43254f6047c5d8124b70d28e39f128c8ad960b437644fe94e1827", - "sha256:ed751a20840a31242e7bea566fcf93ba75bc11b33afe2777bbf46069c1af5094", - "sha256:ef8b927813c27c3bdfc82c55682d7767403bcdadfd9f9c0fc49f4be4553a877b", - "sha256:f43cacda46fc188f998e6d308afe1c61ff41dcb300949f4cbf731e9a0a5eb2d3", - "sha256:f44bea60fd2178d7153deef9621c4b526a93939da30010bba24d3408a98b0f79", - "sha256:fcc021530b7c71069132fe4846d95a3cdd74d143adc2f7e398d5fabf610f111c", - "sha256:fe16517b275031d61261a4e3941c411fb7c46a9cd012f02381b56e7907cc9e06", - "sha256:fe3ae4294d593da54862f0140fdcc89d1aeeb94258ca97f094119ed7f0e5882d" + "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", + "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", + "sha256:0a02313e71b7c370c43056f6b16c45effbb2d29a44d24403a3d5ba6ed322fa3f", + "sha256:0a89cadc0062a5e53664dde043f6c097172b8c1c5f0094490095282ff9995a5f", + "sha256:0be605bfb8461384a4cb81e80f51eb5ca1b89851f2d0e69a75458c788a7263a4", + "sha256:0d52a70350ec3dfc39b513df12b03b7f4c8f8ec6873bbf958299999db7b05eb1", + "sha256:0e7a5d0b9077e8c3e57727f797ee8adf12e1d5e7534642230d98980d160d1320", + "sha256:145d78c345a38011497e55aff22c0f8edd40ee676a6810f7e69563d68a125e83", + "sha256:14dee106a10b77224bba5efeeb6aee025aabe88eb87a2b850c46d3ee55bdab4a", + "sha256:176fdca18391e1206c32fb1d8265628a84d28333c20ad19468d91e3e98312cd1", + "sha256:1b4c535f524c9d8c86c3afd71d199025daa070859a2bdaf94a298120b0de16db", + "sha256:1b5cb75d2642ff7db823f509641f143f752c0d1ab03166cafea1e42e50469834", + "sha256:1c6c71e198b36f0f0dfe354f06d3655ecfa30d69493a1da125a9a54668aad652", + "sha256:1c771f1a8b3cd2d697baaf57e9cfa4ae42371cacfbea42ea01d9577c06d92f96", + "sha256:208a61db8b8b647fb5b1ff3b52b4ed6dbced01eac3b61009958adb203596ee99", + "sha256:2157d68f85c28688e8b723bbe70c8013e0aba5570e08c48b3562f74d33fc05c4", + "sha256:2301051701b27aff2cbdf83fae22b7ca883c9563dfd088033267291b46196643", + "sha256:2567885ff0c8c7c0887ba6cefe4ae4af96364a66a7069f924ce0cd12eb971d04", + "sha256:2577b8161eeae4dd376d13100b2137d883c10bb457dd08935f60c9f9d4b5c5f6", + "sha256:27e5ea64332385385b75414888ce9d1a9806be8616d7cef4ef409f4f256c6d06", + "sha256:28bfd5244d32faf3e49b5a8d1fab0631e922c26e8add089312e4be19fb05af50", + "sha256:295a5beaecb7bf054c1c6a28749ed72b19f4d4b61edcd8a0815d892424baf780", + "sha256:2c46a0afef69d61938a6fe32c3afd75b91dec3ab3056085dc72abbeedcc94166", + "sha256:3100a2352bdded6232b385ceda0c0a4624598c517d52c2d8cf014b7abbebd84d", + "sha256:320a1fe403dd83a35709fcf01083d14bc1462e9789b711201349a9158db3a87e", + "sha256:320f8734553c50cffe8a8e1ae36dfc7d7be1941c047489db20a814d2a170d7b5", + "sha256:33ab8c031f788609924e329003088831045f683931932a52a361d4a955b7dce2", + "sha256:3492ae1f97209c66af70e863e6420e6301cecb0a51a5efa701058aa73a8ca29e", + "sha256:351a2efe1c9566c348ad0076f4bf541f4905a0ebe2d271f112f60852575f3c16", + "sha256:3f0ac6e0203bd88863649e6ed9c7cfe53afab304bc8225f2597c4c0a74e4d1f0", + "sha256:3fedad05147b40ff8a93fcd016c421e6c159f149a2a481cfa0b94bfa3e473bab", + "sha256:4294f2c1cd069b793e31c2e6d7ac44b121cf7cedccd03ebcc30f3fc3417b314a", + "sha256:463b974b7f49d65a16ca1435bc1c25a681bb7d630509dd23b2e819ed36da0b7f", + "sha256:4e0a3ea7fd01cf0a36509f320226bd8491e0f448f00b8cb89f601c109f6874e1", + "sha256:514e78d20d8382d5b97f32b20c83d1d0452c302c9a135f0a9022236eb9940fda", + "sha256:517b09b1dd842390a965a896d1327c55dfe78199c9f5840595d40facbcd81854", + "sha256:51d1d061df3995c2332ae78f036492cc188cb3da8ef122caeab3631a67bb477e", + "sha256:5296669bff390135528001b4e48d33a7acaffcd361d98659628ece7f282f11aa", + "sha256:5296e5e69243ffd76bd919854c4da6630ae52e46175c804bc4c0e050d937b705", + "sha256:58db209da08a502ce6948841d522dcec80921d714024354153d00b054571993c", + "sha256:5b779e87300635b8075e8d5cfd4fdf7f46078cd7610c381d956bca5556bb8f97", + "sha256:5cf113a46d81cff0559d57aa66ffa473d57d1a9496f97426318b6b5b14fdec1c", + "sha256:5d20072d81cbfdd8e15e6a0c91fc7e3a4948c71e0adebfc67d3b4bcbe8602711", + "sha256:5d67dbc8da2dac1644d71c1839d12d12aa333e266a9964d5b1a49feed036bc94", + "sha256:5f530f35e1a57d4360eddcbed6945aecdaee2a491cd3f17025e7b5f2eea88ee7", + "sha256:5fdffb0cfeb4dc8646a5381d32ec981ae8472f29c695bf09e8f7a8edb2db12ca", + "sha256:602284e652bb56ca8760f8e88a5280636c5b63d7946fca1c2fe0f83c37dffc64", + "sha256:648fcfd8e019b122b7be0e26830a3a2224d57c3e934f19c1e53a77b8380e6675", + "sha256:64b9122be1c404ce4eb367ad609b590394587a676d84bfed8e03c3ce76d70560", + "sha256:6526933760ee1e6090db808f1690a111ec409699c1990efc96f134d26925c37f", + "sha256:6632b1c63d58cddc72f43ab9f17267354ddce563dd5e11eadabd222dcc808808", + "sha256:6f93dbfa5a461107bc3f5026e0d5180499e13379e9404f07a9f79eb5e9e1303d", + "sha256:71c0db2c313ea8a80825fb61b7826b8015874aec29ee6364ade5cb774fe4511b", + "sha256:71c5c200fd37a5322706080b09c3ec8907cf01c377a7187f354fc9e9e13abc73", + "sha256:7738147cd9dbd6d18d5593b3491b4620e13b61de975fd737283e4ad6c255c273", + "sha256:7a6e4dccae8ef5dd76052647d78f02d5d0ffaff1856277d951666c54aeba3ad2", + "sha256:7b4a9fcd95e978cd3c96cdc2096aa54705266551422cf0883c12a4044def31c6", + "sha256:80710d7591d579442c67a3bc7ae9dcba9ff95ea8414ac98001198d894fc4ff46", + "sha256:81a3ebc33b1367f301d1c8eda57eec4868e951504986d5d3fe437479dcdac5b2", + "sha256:8455176fd1b86de97d859fed4ae0ef867bf998581f584c7a1a591246dfec330f", + "sha256:845b178bd127bb074835d2eac635b980c58ec5e700ebadc8355062df708d5a71", + "sha256:87e18f29bac4a6be76a30e74de9c9005475e27100acf0830679420ce1fd9a6fd", + "sha256:89d7baa847383b9814de640c6f1a8553d125ec65e2761ad146ea2e75a7ad197c", + "sha256:8c7ad5cab282f53b9d78d51504330d1c88c83fbe187e472c07e6908a0293142e", + "sha256:8d92c6bb9174d47c2257528f64645a00bbc6324a9ff45a626192797aff01dc14", + "sha256:9252c991e8176b5a2fa574c5ab9a841679e315f6e576eb7cf0bd958f3e39b0ad", + "sha256:93111fd4e08fa889c126aa8baf5c009a941880a539c87672e04583286517450a", + "sha256:95d15cf81cd2fb926f2a6151a9f94c7aacc102b415e72bc0e040e29332b6731c", + "sha256:9d5b66d457d2c5739c184a777455c8fde7ab3600a56d8bbebecf64f7c55169e1", + "sha256:a055d29f1302892a9389a382bed10a3f77708bcf3e49bfb76f7712fa5f391cc6", + "sha256:a1ba93be779a9b8e5e44f5c133dc1db4313661cead8a2fd27661e6cb8d942ee9", + "sha256:a283425e6a474facd73072d8968812d1d9058490a5781e022ccf8895500b83ce", + "sha256:a351986d6c9006308f163c359ced40f80b6cffb42069f3e569b979829951038d", + "sha256:a766157b195a897c64945d4ff87b050bb0e763bb78f3964e996378621c703b00", + "sha256:a8a3540e21213cb8ce232e68a7d0ee49cdd35194856c50b8bd87eeb572fadd42", + "sha256:a8e0a086dbbee406cc6f603931dfe54d1cb2fba585758e06a2de01037784b737", + "sha256:ab23b0545ec71ea346bf50a5d376d674f56205b729980eaa62cdb7871805014b", + "sha256:b0db9a4691074c347f5d7ee830ab3529bc5ad860939de21c1f9c403daf1eda9a", + "sha256:b1b5be40ebf52c3c67ee547e2c4435ed5bc6352f38d23e394520b686641a6be4", + "sha256:b3e08aef4ea05afbc0a70cd23c13684e7f5e074f02450964ec5cfa1c759d33d2", + "sha256:b7df0d99e189b7027d417d4bfd9b8c53c9c7ed5a0a1495d26a6f547d820eca88", + "sha256:be1f10145f7ea76e3e836fdc5c8429c605675bdcddb0bca9725ee6e26874c00c", + "sha256:bf254a1a95e95fdf4eaa25faa1ea450a6533ed7a997f9f8e49ab971b61ea514d", + "sha256:bfc2d763d05ec7211313a06e8571236017d3e61d5fef97fcf34ec4b36c0b6556", + "sha256:c164eda0be9048f83c24b9b2656900041e069ddf72de81c17d874d0c32f6079f", + "sha256:c22591cff80188dd8543be0b559d0c807f7288bd353dc0bcfe539b4588b3a5cd", + "sha256:c5f83bb59d0ff60c6fdb1f8a7b0288fbc4640b1f0fd56f5ae2387749c35d34e3", + "sha256:c7e8221278e5f9e2b6d3893cfc3a3e46c017161a57bb0e6f244826e4cee97916", + "sha256:c8d6bf6fcd42cde2f02efb8126812a010c297eacefcd090a609639d2aeda6185", + "sha256:c8f7dd025cb0bf19e2f60a64dfc24b513c8330e0cfe4a34ccf941eafd6194d9e", + "sha256:c9d212e2af72d5c8d082775a43eb726520e95bf1c84826440f74225843975136", + "sha256:cebb3d8bcac4a6b48be65ebbc5c9881ed4a738e27bb96c86d9d7580a1fb09e05", + "sha256:d3082e5c4d7b388792124f5e805b469109e58f1ab1eb1fbd8b998e8ab766ffb7", + "sha256:d81047341ab56061aa4b6823c54d4632579c3b16e675089e8f520e9b918a133b", + "sha256:d81299f63dc33cc172c26faf59cc54dd795fc6dd5821a7676cca112a5ee8bbd6", + "sha256:dfa217bf8cf3ff6b30c8e6a89014e0c0e7b50941af787b970060ae5ba04a4ce5", + "sha256:dfec57f15f53d677b8e4535695ff3f37df7f8fe431f2efa8c3c8c4025b53d1eb", + "sha256:e099b79ccf7c40f18b149a64d3d10639980035f9ceb223169dd806ff1bb0d9cc", + "sha256:e1fc4d3985868860b6585376e511bb32403c5ffb58b0ed913496c27fd791deea", + "sha256:e2b4c95c47fb81b19ea77dc1c50d23af3eba87c9628fcc2e03d44124a3d336ea", + "sha256:e4e5d163e6644c2bc84dd9f67bfa89288c23af26983d08fefcc2cbc22f6e57e6", + "sha256:e66b3c9f8b89d4fd58a59c04fdbf10602a17c914fbaaa5e6ea593f1d54b06362", + "sha256:ed7d11330e443aeecab23866055e08a5a536c95d2c25333aeb441af2dbac38d2", + "sha256:f340a2a908644ea6cccd399be0fb308c66e05d2800107345f9f0f0d59e1731c4", + "sha256:f38b35ecd2628bf0267761ed659e48af7e620a7fcccfccf5774e7308fb18325c", + "sha256:f6d5443104f89a840250087863c91484a72f254574848e951d1bdd7d8b2ce7c9", + "sha256:fc2048d13ff427605fea328cbe5369dce549b8c7657b0e22051a5b8831170af6" ], "index": "pypi", - "version": "==3.12.1" + "version": "==3.12.3" }, "python-dateutil": { "hashes": [ @@ -524,19 +505,19 @@ }, "tinycss2": { "hashes": [ - "sha256:0353b5234bcaee7b1ac7ca3dea7e02cd338a9f8dcbb8f2dcd32a5795ec1e5f9a", - "sha256:fbdcac3044d60eb85fdb2aa840ece43cf7dbe798e373e6ee0be545d4d134e18a" + "sha256:b2e44dd8883c360c35dd0d1b5aad0b610e5156c2cb3b33434634e539ead9d8bf", + "sha256:fe794ceaadfe3cf3e686b22155d0da5780dd0e273471a51846d0a02bc204fec8" ], "markers": "python_version >= '3.6'", - "version": "==1.1.0" + "version": "==1.1.1" }, "typing-extensions": { "hashes": [ - "sha256:2cdf80e4e04866a9b3689a51869016d36db0814d84b8d8a568d22781d45d27ed", - "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9" + "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42", + "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2" ], "markers": "python_version >= '3.6'", - "version": "==4.0.0" + "version": "==4.1.1" }, "uvloop": { "hashes": [ @@ -664,11 +645,11 @@ }, "bandit": { "hashes": [ - "sha256:a81b00b5436e6880fa8ad6799bc830e02032047713cbb143a12939ac67eb756c", - "sha256:f5acd838e59c038a159b5c621cf0f8270b279e884eadd7b782d7491c02add0d4" + "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2", + "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a" ], "index": "pypi", - "version": "==1.7.1" + "version": "==1.7.4" }, "black": { "hashes": [ @@ -680,11 +661,11 @@ }, "click": { "hashes": [ - "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3", - "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b" + "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1", + "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb" ], "markers": "python_version >= '3.6'", - "version": "==8.0.3" + "version": "==8.0.4" }, "colorama": { "hashes": [ @@ -704,11 +685,11 @@ }, "gitpython": { "hashes": [ - "sha256:dc0a7f2f697657acc8d7f89033e8b1ea94dd90356b2983bca89dc8d2ab3cc647", - "sha256:df83fdf5e684fef7c6ee2c02fc68a5ceb7e7e759d08b694088d0cacb4eba59e5" + "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704", + "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d" ], "markers": "python_version >= '3.7'", - "version": "==3.1.24" + "version": "==3.1.27" }, "isort": { "hashes": [ @@ -720,31 +701,46 @@ }, "lazy-object-proxy": { "hashes": [ - "sha256:17e0967ba374fc24141738c69736da90e94419338fd4c7c7bef01ee26b339653", - "sha256:1fee665d2638491f4d6e55bd483e15ef21f6c8c2095f235fef72601021e64f61", - "sha256:22ddd618cefe54305df49e4c069fa65715be4ad0e78e8d252a33debf00f6ede2", - "sha256:24a5045889cc2729033b3e604d496c2b6f588c754f7a62027ad4437a7ecc4837", - "sha256:410283732af311b51b837894fa2f24f2c0039aa7f220135192b38fcc42bd43d3", - "sha256:4732c765372bd78a2d6b2150a6e99d00a78ec963375f236979c0626b97ed8e43", - "sha256:489000d368377571c6f982fba6497f2aa13c6d1facc40660963da62f5c379726", - "sha256:4f60460e9f1eb632584c9685bccea152f4ac2130e299784dbaf9fae9f49891b3", - "sha256:5743a5ab42ae40caa8421b320ebf3a998f89c85cdc8376d6b2e00bd12bd1b587", - "sha256:85fb7608121fd5621cc4377a8961d0b32ccf84a7285b4f1d21988b2eae2868e8", - "sha256:9698110e36e2df951c7c36b6729e96429c9c32b3331989ef19976592c5f3c77a", - "sha256:9d397bf41caad3f489e10774667310d73cb9c4258e9aed94b9ec734b34b495fd", - "sha256:b579f8acbf2bdd9ea200b1d5dea36abd93cabf56cf626ab9c744a432e15c815f", - "sha256:b865b01a2e7f96db0c5d12cfea590f98d8c5ba64ad222300d93ce6ff9138bcad", - "sha256:bf34e368e8dd976423396555078def5cfc3039ebc6fc06d1ae2c5a65eebbcde4", - "sha256:c6938967f8528b3668622a9ed3b31d145fab161a32f5891ea7b84f6b790be05b", - "sha256:d1c2676e3d840852a2de7c7d5d76407c772927addff8d742b9808fe0afccebdf", - "sha256:d7124f52f3bd259f510651450e18e0fd081ed82f3c08541dffc7b94b883aa981", - "sha256:d900d949b707778696fdf01036f58c9876a0d8bfe116e8d220cfd4b15f14e741", - "sha256:ebfd274dcd5133e0afae738e6d9da4323c3eb021b3e13052d8cbd0e457b1256e", - "sha256:ed361bb83436f117f9917d282a456f9e5009ea12fd6de8742d1a4752c3017e93", - "sha256:f5144c75445ae3ca2057faac03fda5a902eff196702b0a24daf1d6ce0650514b" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.6.0" + "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7", + "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a", + "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c", + "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc", + "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f", + "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09", + "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442", + "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e", + "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029", + "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61", + "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb", + "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0", + "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35", + "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42", + "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1", + "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad", + "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443", + "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd", + "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9", + "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148", + "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38", + "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55", + "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36", + "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a", + "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b", + "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44", + "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6", + "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69", + "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4", + "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84", + "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de", + "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28", + "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c", + "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1", + "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8", + "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b", + "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb" + ], + "markers": "python_version >= '3.6'", + "version": "==1.7.1" }, "mccabe": { "hashes": [ @@ -769,11 +765,11 @@ }, "pbr": { "hashes": [ - "sha256:176e8560eaf61e127817ef93d8a844803abb27a4d4637f0ff3bb783129be2e0a", - "sha256:672d8ebee84921862110f23fcec2acea191ef58543d34dfe9ef3d9f13c31cddf" + "sha256:27108648368782d07bbf1cb468ad2e2eeef29086affd14087a6d04b7de8af4ec", + "sha256:66bc5a34912f408bb3925bf21231cb6f59206267b7f63f3503ef865c1a292e25" ], "markers": "python_version >= '2.6'", - "version": "==5.8.0" + "version": "==5.8.1" }, "pylint": { "hashes": [ @@ -824,57 +820,91 @@ }, "regex": { "hashes": [ - "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f", - "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc", - "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4", - "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4", - "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8", - "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f", - "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a", - "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef", - "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f", - "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc", - "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50", - "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d", - "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d", - "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733", - "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36", - "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345", - "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0", - "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12", - "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646", - "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667", - "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244", - "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29", - "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec", - "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf", - "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4", - "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449", - "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a", - "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d", - "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb", - "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e", - "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83", - "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e", - "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a", - "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94", - "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc", - "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e", - "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965", - "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0", - "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36", - "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec", - "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23", - "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7", - "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe", - "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6", - "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b", - "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb", - "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b", - "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30", - "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e" - ], - "version": "==2021.11.10" + "sha256:0066a6631c92774391f2ea0f90268f0d82fffe39cb946f0f9c6b382a1c61a5e5", + "sha256:0100f0ded953b6b17f18207907159ba9be3159649ad2d9b15535a74de70359d3", + "sha256:01c913cf573d1da0b34c9001a94977273b5ee2fe4cb222a5d5b320f3a9d1a835", + "sha256:0214ff6dff1b5a4b4740cfe6e47f2c4c92ba2938fca7abbea1359036305c132f", + "sha256:029e9e7e0d4d7c3446aa92474cbb07dafb0b2ef1d5ca8365f059998c010600e6", + "sha256:0317eb6331146c524751354ebef76a7a531853d7207a4d760dfb5f553137a2a4", + "sha256:04b5ee2b6d29b4a99d38a6469aa1db65bb79d283186e8460542c517da195a8f6", + "sha256:04c09b9651fa814eeeb38e029dc1ae83149203e4eeb94e52bb868fadf64852bc", + "sha256:058054c7a54428d5c3e3739ac1e363dc9347d15e64833817797dc4f01fb94bb8", + "sha256:060f9066d2177905203516c62c8ea0066c16c7342971d54204d4e51b13dfbe2e", + "sha256:0a7b75cc7bb4cc0334380053e4671c560e31272c9d2d5a6c4b8e9ae2c9bd0f82", + "sha256:0e2630ae470d6a9f8e4967388c1eda4762706f5750ecf387785e0df63a4cc5af", + "sha256:174d964bc683b1e8b0970e1325f75e6242786a92a22cedb2a6ec3e4ae25358bd", + "sha256:25ecb1dffc5e409ca42f01a2b2437f93024ff1612c1e7983bad9ee191a5e8828", + "sha256:286908cbe86b1a0240a867aecfe26a439b16a1f585d2de133540549831f8e774", + "sha256:303b15a3d32bf5fe5a73288c316bac5807587f193ceee4eb6d96ee38663789fa", + "sha256:34bb30c095342797608727baf5c8aa122406aa5edfa12107b8e08eb432d4c5d7", + "sha256:3e265b388cc80c7c9c01bb4f26c9e536c40b2c05b7231fbb347381a2e1c8bf43", + "sha256:3e4d710ff6539026e49f15a3797c6b1053573c2b65210373ef0eec24480b900b", + "sha256:42eb13b93765c6698a5ab3bcd318d8c39bb42e5fa8a7fcf7d8d98923f3babdb1", + "sha256:48081b6bff550fe10bcc20c01cf6c83dbca2ccf74eeacbfac240264775fd7ecf", + "sha256:491fc754428514750ab21c2d294486223ce7385446f2c2f5df87ddbed32979ae", + "sha256:4d1445824944e642ffa54c4f512da17a953699c563a356d8b8cbdad26d3b7598", + "sha256:530a3a16e57bd3ea0dff5ec2695c09632c9d6c549f5869d6cf639f5f7153fb9c", + "sha256:591d4fba554f24bfa0421ba040cd199210a24301f923ed4b628e1e15a1001ff4", + "sha256:5a86cac984da35377ca9ac5e2e0589bd11b3aebb61801204bd99c41fac516f0d", + "sha256:5b1ceede92400b3acfebc1425937454aaf2c62cd5261a3fabd560c61e74f6da3", + "sha256:5b2e24f3ae03af3d8e8e6d824c891fea0ca9035c5d06ac194a2700373861a15c", + "sha256:6504c22c173bb74075d7479852356bb7ca80e28c8e548d4d630a104f231e04fb", + "sha256:673f5a393d603c34477dbad70db30025ccd23996a2d0916e942aac91cc42b31a", + "sha256:6ca6dcd17f537e9f3793cdde20ac6076af51b2bd8ad5fe69fa54373b17b48d3c", + "sha256:6e1d8ed9e61f37881c8db383a124829a6e8114a69bd3377a25aecaeb9b3538f8", + "sha256:75a5e6ce18982f0713c4bac0704bf3f65eed9b277edd3fb9d2b0ff1815943327", + "sha256:76435a92e444e5b8f346aed76801db1c1e5176c4c7e17daba074fbb46cb8d783", + "sha256:764e66a0e382829f6ad3bbce0987153080a511c19eb3d2f8ead3f766d14433ac", + "sha256:78ce90c50d0ec970bd0002462430e00d1ecfd1255218d52d08b3a143fe4bde18", + "sha256:794a6bc66c43db8ed06698fc32aaeaac5c4812d9f825e9589e56f311da7becd9", + "sha256:797437e6024dc1589163675ae82f303103063a0a580c6fd8d0b9a0a6708da29e", + "sha256:7b7494df3fdcc95a1f76cf134d00b54962dd83189520fd35b8fcd474c0aa616d", + "sha256:7d1a6e403ac8f1d91d8f51c441c3f99367488ed822bda2b40836690d5d0059f5", + "sha256:7f63877c87552992894ea1444378b9c3a1d80819880ae226bb30b04789c0828c", + "sha256:8923e1c5231549fee78ff9b2914fad25f2e3517572bb34bfaa3aea682a758683", + "sha256:8afcd1c2297bc989dceaa0379ba15a6df16da69493635e53431d2d0c30356086", + "sha256:8b1cc70e31aacc152a12b39245974c8fccf313187eead559ee5966d50e1b5817", + "sha256:8d1f3ea0d1924feb4cf6afb2699259f658a08ac6f8f3a4a806661c2dfcd66db1", + "sha256:940570c1a305bac10e8b2bc934b85a7709c649317dd16520471e85660275083a", + "sha256:947a8525c0a95ba8dc873191f9017d1b1e3024d4dc757f694e0af3026e34044a", + "sha256:9beb03ff6fe509d6455971c2489dceb31687b38781206bcec8e68bdfcf5f1db2", + "sha256:9c144405220c5ad3f5deab4c77f3e80d52e83804a6b48b6bed3d81a9a0238e4c", + "sha256:a98ae493e4e80b3ded6503ff087a8492db058e9c68de371ac3df78e88360b374", + "sha256:aa2ce79f3889720b46e0aaba338148a1069aea55fda2c29e0626b4db20d9fcb7", + "sha256:aa5eedfc2461c16a092a2fabc5895f159915f25731740c9152a1b00f4bcf629a", + "sha256:ab5d89cfaf71807da93c131bb7a19c3e19eaefd613d14f3bce4e97de830b15df", + "sha256:b4829db3737480a9d5bfb1c0320c4ee13736f555f53a056aacc874f140e98f64", + "sha256:b52771f05cff7517f7067fef19ffe545b1f05959e440d42247a17cd9bddae11b", + "sha256:b8248f19a878c72d8c0a785a2cd45d69432e443c9f10ab924c29adda77b324ae", + "sha256:b9809404528a999cf02a400ee5677c81959bc5cb938fdc696b62eb40214e3632", + "sha256:c155a1a80c5e7a8fa1d9bb1bf3c8a953532b53ab1196092749bafb9d3a7cbb60", + "sha256:c33ce0c665dd325200209340a88438ba7a470bd5f09f7424e520e1a3ff835b52", + "sha256:c5adc854764732dbd95a713f2e6c3e914e17f2ccdc331b9ecb777484c31f73b6", + "sha256:cb374a2a4dba7c4be0b19dc7b1adc50e6c2c26c3369ac629f50f3c198f3743a4", + "sha256:cd00859291658fe1fda48a99559fb34da891c50385b0bfb35b808f98956ef1e7", + "sha256:ce3057777a14a9a1399b81eca6a6bfc9612047811234398b84c54aeff6d536ea", + "sha256:d0a5a1fdc9f148a8827d55b05425801acebeeefc9e86065c7ac8b8cc740a91ff", + "sha256:dad3991f0678facca1a0831ec1ddece2eb4d1dd0f5150acb9440f73a3b863907", + "sha256:dc7b7c16a519d924c50876fb152af661a20749dcbf653c8759e715c1a7a95b18", + "sha256:dcbb7665a9db9f8d7642171152c45da60e16c4f706191d66a1dc47ec9f820aed", + "sha256:df037c01d68d1958dad3463e2881d3638a0d6693483f58ad41001aa53a83fcea", + "sha256:f08a7e4d62ea2a45557f561eea87c907222575ca2134180b6974f8ac81e24f06", + "sha256:f16cf7e4e1bf88fecf7f41da4061f181a6170e179d956420f84e700fb8a3fd6b", + "sha256:f2c53f3af011393ab5ed9ab640fa0876757498aac188f782a0c620e33faa2a3d", + "sha256:f320c070dea3f20c11213e56dbbd7294c05743417cde01392148964b7bc2d31a", + "sha256:f553a1190ae6cd26e553a79f6b6cfba7b8f304da2071052fa33469da075ea625", + "sha256:fc8c7958d14e8270171b3d72792b609c057ec0fa17d507729835b5cff6b7f69a" + ], + "markers": "python_version >= '3.6'", + "version": "==2022.3.15" + }, + "setuptools": { + "hashes": [ + "sha256:6599055eeb23bfef457d5605d33a4d68804266e6cb430b0fb12417c5efeae36c", + "sha256:782ef48d58982ddb49920c11a0c5c9c0b02e7d7d1c2ad0aa44e1a1e133051c96" + ], + "markers": "python_version >= '3.7'", + "version": "==60.10.0" }, "smmap": { "hashes": [ @@ -900,14 +930,6 @@ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, - "typing-extensions": { - "hashes": [ - "sha256:2cdf80e4e04866a9b3689a51869016d36db0814d84b8d8a568d22781d45d27ed", - "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9" - ], - "markers": "python_version >= '3.6'", - "version": "==4.0.0" - }, "wrapt": { "hashes": [ "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" diff --git a/bot.py b/bot.py index 3e3a6ec5cf..c691cea068 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev6" +__version__ = "4.0.0-dev7" import asyncio @@ -67,7 +67,7 @@ class ModmailBot(commands.Bot): def __init__(self): intents = discord.Intents.all() super().__init__(command_prefix=None, intents=intents) # implemented in `get_prefix` - self._session = None + self.session = None self._api = None self.formatter = SafeFormatter() self.loaded_cogs = ["cogs.modmail", "cogs.plugins", "cogs.utility"] @@ -131,10 +131,11 @@ def startup(self): logger.info("discord.py: v%s", discord.__version__) logger.line() + async def load_extensions(self): for cog in self.loaded_cogs: logger.debug("Loading %s.", cog) try: - self.load_extension(cog) + await self.load_extension(cog) logger.debug("Successfully loaded %s.", cog) except Exception: logger.exception("Failed to load %s.", cog) @@ -167,12 +168,6 @@ def _configure_logging(self): def version(self): return parse_version(__version__) - @property - def session(self) -> ClientSession: - if self._session is None: - self._session = ClientSession(loop=self.loop) - return self._session - @property def api(self) -> ApiClient: if self._api is None: @@ -192,102 +187,85 @@ async def get_prefix(self, message=None): return [self.prefix, f"<@{self.user.id}> ", f"<@!{self.user.id}> "] def run(self): - loop = self.loop - - try: - loop.add_signal_handler(signal.SIGINT, lambda: loop.stop()) - loop.add_signal_handler(signal.SIGTERM, lambda: loop.stop()) - except NotImplementedError: - pass - async def runner(): - try: - retry_intents = False + async with self: try: - await self.start(self.token) + retry_intents = False + try: + await self.start(self.token) + except discord.PrivilegedIntentsRequired: + retry_intents = True + if retry_intents: + await self.http.close() + if self.ws is not None and self.ws.open: + await self.ws.close(code=1000) + self._ready.clear() + + intents = discord.Intents.default() + intents.members = True + intents.message_content = True + # Try again with members intent + self._connection._intents = intents + logger.warning( + "Attempting to login with only the server members and message content privileged intent. Some plugins might not work correctly." + ) + await self.start(self.token) except discord.PrivilegedIntentsRequired: - retry_intents = True - if retry_intents: - await self.http.close() - if self.ws is not None and self.ws.open: - await self.ws.close(code=1000) - self._ready.clear() - intents = discord.Intents.default() - intents.members = True - # Try again with members intent - self._connection._intents = intents - logger.warning( - "Attempting to login with only the server members privileged intent. Some plugins might not work correctly." + logger.critical( + "Privileged intents are not explicitly granted in the discord developers dashboard." ) - await self.start(self.token) - except discord.PrivilegedIntentsRequired: - logger.critical( - "Privileged intents are not explicitly granted in the discord developers dashboard." - ) - except discord.LoginFailure: - logger.critical("Invalid token") - except Exception: - logger.critical("Fatal exception", exc_info=True) - finally: - if not self.is_closed(): - await self.close() - if self._session: - await self._session.close() - - # noinspection PyUnusedLocal - def stop_loop_on_completion(f): - loop.stop() - - def _cancel_tasks(): - task_retriever = asyncio.all_tasks - tasks = {t for t in task_retriever(loop=loop) if not t.done()} - - if not tasks: - return + except discord.LoginFailure: + logger.critical("Invalid token") + except Exception: + logger.critical("Fatal exception", exc_info=True) + finally: + if not self.is_closed(): + await self.close() + if self.session: + await self.session.close() + + async def _cancel_tasks(): + async with self: + task_retriever = asyncio.all_tasks + loop = self.loop + tasks = {t for t in task_retriever() if not t.done() and t.get_coro() != cancel_tasks_coro} + + if not tasks: + return - logger.info("Cleaning up after %d tasks.", len(tasks)) - for task in tasks: - task.cancel() - - loop.run_until_complete(asyncio.gather(*tasks, return_exceptions=True)) - logger.info("All tasks finished cancelling.") - - for task in tasks: - if task.cancelled(): - continue - if task.exception() is not None: - loop.call_exception_handler( - { - "message": "Unhandled exception during Client.run shutdown.", - "exception": task.exception(), - "task": task, - } - ) + logger.info("Cleaning up after %d tasks.", len(tasks)) + for task in tasks: + task.cancel() + + await asyncio.gather(*tasks, return_exceptions=True) + logger.info("All tasks finished cancelling.") + + for task in tasks: + try: + if task.exception() is not None: + loop.call_exception_handler( + { + "message": "Unhandled exception during Client.run shutdown.", + "exception": task.exception(), + "task": task, + } + ) + except (asyncio.InvalidStateError, asyncio.CancelledError): + pass - future = asyncio.ensure_future(runner(), loop=loop) - future.add_done_callback(stop_loop_on_completion) try: - loop.run_forever() - except KeyboardInterrupt: + asyncio.run(runner()) + except (KeyboardInterrupt, SystemExit): logger.info("Received signal to terminate bot and event loop.") finally: - future.remove_done_callback(stop_loop_on_completion) logger.info("Cleaning up tasks.") try: - _cancel_tasks() - if sys.version_info >= (3, 6): - loop.run_until_complete(loop.shutdown_asyncgens()) + cancel_tasks_coro = _cancel_tasks() + asyncio.run(cancel_tasks_coro) finally: logger.info("Closing the event loop.") - if not future.cancelled(): - try: - return future.result() - except KeyboardInterrupt: - # I am unsure why this gets raised here but suppress it anyway - return None - @property def bot_owner_ids(self): owner_ids = self.config["owners"] @@ -517,6 +495,8 @@ async def on_connect(self): logger.debug("Connected to gateway.") await self.config.refresh() await self.api.setup_indexes() + await self.load_extensions() + self.session = ClientSession(loop=self.loop) self._connected.set() async def on_ready(self): @@ -1421,7 +1401,7 @@ async def on_message_delete(self, message): if embed.footer.icon: icon_url = embed.footer.icon.url else: - icon_url = discord.Embed.Empty + icon_url = None embed.set_footer(text=f"{embed.footer.text} (deleted)", icon_url=icon_url) await message.edit(embed=embed) diff --git a/cogs/modmail.py b/cogs/modmail.py index 7900f0eeef..8ef853963c 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -2091,5 +2091,5 @@ async def isenable(self, ctx): return await ctx.send(embed=embed) -def setup(bot): - bot.add_cog(Modmail(bot)) +async def setup(bot): + await bot.add_cog(Modmail(bot)) diff --git a/cogs/plugins.py b/cogs/plugins.py index e9adf2a240..37e71a872b 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -123,10 +123,10 @@ def __init__(self, bot): self.loaded_plugins = set() self._ready_event = asyncio.Event() - self.bot.loop.create_task(self.populate_registry()) - + async def async_init(self): + await self.populate_registry() if self.bot.config.get("enable_plugins"): - self.bot.loop.create_task(self.initial_load_plugins()) + await self.initial_load_plugins() else: logger.info("Plugins not loaded since ENABLE_PLUGINS=false.") @@ -258,7 +258,7 @@ async def load_plugin(self, plugin): sys.path.insert(0, USER_SITE) try: - self.bot.load_extension(plugin.ext_string) + await self.bot.load_extension(plugin.ext_string) logger.info("Loaded plugin: %s", plugin.ext_string.split(".")[-1]) self.loaded_plugins.add(plugin) @@ -432,7 +432,7 @@ async def plugins_remove(self, ctx, *, plugin_name: str): if self.bot.config.get("enable_plugins"): try: - self.bot.unload_extension(plugin.ext_string) + await self.bot.unload_extension(plugin.ext_string) self.loaded_plugins.remove(plugin) except (commands.ExtensionNotLoaded, KeyError): logger.warning("Plugin was never loaded.") @@ -474,7 +474,7 @@ async def update_plugin(self, ctx, plugin_name): await self.download_plugin(plugin, force=True) if self.bot.config.get("enable_plugins"): try: - self.bot.unload_extension(plugin.ext_string) + await self.bot.unload_extension(plugin.ext_string) except commands.ExtensionError: logger.warning("Plugin unload fail.", exc_info=True) try: @@ -525,7 +525,7 @@ async def plugins_reset(self, ctx): continue try: logger.error("Unloading plugin: %s.", ext) - self.bot.unload_extension(ext) + await self.bot.unload_extension(ext) except Exception: logger.error("Failed to unload plugin: %s.", ext) else: @@ -737,5 +737,5 @@ async def plugins_registry_compact(self, ctx): await paginator.run() -def setup(bot): - bot.add_cog(Plugins(bot)) +async def setup(bot): + await bot.add_cog(Plugins(bot)) diff --git a/cogs/utility.py b/cogs/utility.py index 7278c350fc..aa8adaaf2d 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -256,11 +256,13 @@ def __init__(self, bot): }, ) self.bot.help_command.cog = self - self.loop_presence.start() # pylint: disable=no-member if not self.bot.config.get("enable_eval"): self.eval_.enabled = False logger.info("Eval disabled. enable_eval=False") + async def async_init(self): + self.loop_presence.start() # pylint: disable=no-member + def cog_unload(self): self.bot.help_command = self._original_help_command @@ -2099,5 +2101,5 @@ def paginate(text: str): await self.bot.add_reaction(ctx.message, "\u2705") -def setup(bot): - bot.add_cog(Utility(bot)) +async def setup(bot): + await bot.add_cog(Utility(bot)) diff --git a/core/paginator.py b/core/paginator.py index b9cd29a26b..39782817b5 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -308,7 +308,7 @@ def __init__(self, ctx: commands.Context, *embeds, **options): if embed.footer.icon: icon_url = embed.footer.icon.url else: - icon_url = Embed.Empty + icon_url = None embed.set_footer(text=footer_text, icon_url=icon_url) # select menu @@ -369,7 +369,7 @@ def _set_footer(self): if self.embed.footer.icon: icon_url = self.embed.footer.icon.url else: - icon_url = Embed.Empty + icon_url = None self.embed.set_footer(text=footer_text, icon_url=icon_url) diff --git a/core/thread.py b/core/thread.py index 87ffc45ee3..7edfbc1d39 100644 --- a/core/thread.py +++ b/core/thread.py @@ -75,7 +75,7 @@ def __eq__(self, other): async def wait_until_ready(self) -> None: """Blocks execution until the thread is fully set up.""" # timeout after 30 seconds - task = asyncio.create_task(asyncio.wait_for(self._ready_event.wait(), timeout=25)) + task = self.bot.loop.create_task(asyncio.wait_for(self._ready_event.wait(), timeout=25)) self.wait_tasks.append(task) try: await task @@ -367,7 +367,8 @@ def _format_info_embed(self, user, log_url, log_count, color): return embed - def _close_after(self, closer, silent, delete_channel, message): + async def _close_after(self, after, closer, silent, delete_channel, message): + await asyncio.sleep(after) return self.bot.loop.create_task(self._close(closer, silent, delete_channel, message, True)) async def close( @@ -401,7 +402,7 @@ async def close( self.bot.config["closures"][str(self.id)] = items await self.bot.config.update() - task = self.bot.loop.call_later(after, self._close_after, closer, silent, delete_channel, message) + task = asyncio.create_task(self._close_after(after, closer, silent, delete_channel, message)) if auto_close: self.auto_close_task = task @@ -1139,7 +1140,7 @@ def lottie_to_png(data): raise if not from_mod and not note: - mentions = self.get_notifications() + mentions = await self.get_notifications() else: mentions = None @@ -1176,7 +1177,7 @@ def lottie_to_png(data): return msg - def get_notifications(self) -> str: + async def get_notifications(self) -> str: key = str(self.id) mentions = [] diff --git a/pyproject.toml b/pyproject.toml index 031fc5073f..d552a33dee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev6' +version = '4.0.0-dev7' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From d9c884e55c8d65175ebfe604e25098add7bdaf55 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 19 Apr 2022 23:30:31 +0800 Subject: [PATCH 067/225] dpy-ecb2cf & Fix plugins not loading, resolve #3141 --- Pipfile | 2 +- bot.py | 4 ++-- cogs/plugins.py | 4 +--- cogs/utility.py | 2 +- pyproject.toml | 2 +- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Pipfile b/Pipfile index 04d998cbc8..1241feeb40 100644 --- a/Pipfile +++ b/Pipfile @@ -11,7 +11,7 @@ pylint = "~=2.9.3" [packages] aiohttp = "==3.7.4.post0" colorama = "~=0.4.4" # Doesn't officially support Python 3.9 yet, v0.4.5 will support 3.9 -"discord.py" = {ref = "97fe07edb2f3d0f5a980917fb6ee479bf396fd94", git = "https://github.com/Rapptz/discord.py.git"} +"discord.py" = {ref = "987235d5649e7c2b1a927637bab6547244ecb2cf", git = "https://github.com/Rapptz/discord.py.git"} emoji = "~=1.2.0" isodate = "~=0.6.0" motor = "~=2.4.0" diff --git a/bot.py b/bot.py index c691cea068..6c0719243b 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev7" +__version__ = "4.0.0-dev8" import asyncio @@ -189,6 +189,7 @@ async def get_prefix(self, message=None): def run(self): async def runner(): async with self: + self.session = ClientSession(loop=self.loop) try: retry_intents = False try: @@ -496,7 +497,6 @@ async def on_connect(self): await self.config.refresh() await self.api.setup_indexes() await self.load_extensions() - self.session = ClientSession(loop=self.loop) self._connected.set() async def on_ready(self): diff --git a/cogs/plugins.py b/cogs/plugins.py index 37e71a872b..2bfac509af 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -123,7 +123,7 @@ def __init__(self, bot): self.loaded_plugins = set() self._ready_event = asyncio.Event() - async def async_init(self): + async def cog_load(self): await self.populate_registry() if self.bot.config.get("enable_plugins"): await self.initial_load_plugins() @@ -136,8 +136,6 @@ async def populate_registry(self): self.registry = json.loads(await resp.text()) async def initial_load_plugins(self): - await self.bot.wait_for_connected() - for plugin_name in list(self.bot.config["plugins"]): try: plugin = Plugin.from_string(plugin_name, strict=True) diff --git a/cogs/utility.py b/cogs/utility.py index aa8adaaf2d..6d1ddd0f00 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -260,7 +260,7 @@ def __init__(self, bot): self.eval_.enabled = False logger.info("Eval disabled. enable_eval=False") - async def async_init(self): + async def cog_load(self): self.loop_presence.start() # pylint: disable=no-member def cog_unload(self): diff --git a/pyproject.toml b/pyproject.toml index d552a33dee..ad792dc399 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev7' +version = '4.0.0-dev8' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From f03e20318f52f3682c9173c0cade49ded9a44c88 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 19 Apr 2022 23:43:45 +0800 Subject: [PATCH 068/225] fix blocked, resolve #3131 --- CHANGELOG.md | 1 + bot.py | 1 - cogs/modmail.py | 4 +++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 209bbcfcea..fb025baca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Editing notes now work. ([GH #3094](https://github.com/kyb3r/modmail/issues/3094)) - Commands now work in threads. - Audit log searching now properly works. +- Old data causing `?blocked` to fail. ([GH #3131](https://github.com/kyb3r/modmail/issues/3131)) ### Internal diff --git a/bot.py b/bot.py index 6c0719243b..da1e7117a3 100644 --- a/bot.py +++ b/bot.py @@ -6,7 +6,6 @@ import logging import os import re -import signal import string import struct import sys diff --git a/cogs/modmail.py b/cogs/modmail.py index 8ef853963c..63997b2824 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1565,7 +1565,9 @@ async def blocked(self, ctx): ) if end_time is not None: - after = (datetime.fromisoformat(end_time.group(1)) - now).total_seconds() + after = ( + datetime.fromisoformat(end_time.group(1)).replace(tzinfo=timezone.utc) - now + ).total_seconds() if after <= 0: # No longer blocked self.bot.blocked_users.pop(str(id_)) From 71daedc219d07c797133adf77eff1f4918faf4b0 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 20 Apr 2022 21:02:32 +0800 Subject: [PATCH 069/225] update reqs.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index fb43d23e2b..f0e1933ce0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ chardet==4.0.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2 colorama==0.4.4 dnspython==2.1.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' emoji==1.2.0 -git+https://github.com/Rapptz/discord.py.git@45d498c1b76deaf3b394d17ccf56112fa691d160#egg=discord-py +git+https://github.com/Rapptz/discord.py.git@987235d5649e7c2b1a927637bab6547244ecb2cf#egg=discord-py idna==3.3; python_version >= '3.5' isodate==0.6.0 motor==2.4.0 From 0e05f440526c87f486c9ce53f41876dcfd6017f3 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 20 Apr 2022 22:29:13 +0800 Subject: [PATCH 070/225] Fix stop button in paginator --- core/paginator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/paginator.py b/core/paginator.py index 39782817b5..39d0c434a3 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -216,7 +216,7 @@ def __init__(self, handler: PaginatorSession, *args, **kwargs): self.fill_items() @discord.ui.button(label="Stop", style=ButtonStyle.danger) - async def stop_button(self, button: Button, interaction: Interaction): + async def stop_button(self, interaction: Interaction, button: Button): await self.handler.close(interaction=interaction) def fill_items(self): From c57e3421acc8c0aa0aa7120412e00c3f7b15c406 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 20 Apr 2022 22:49:33 +0800 Subject: [PATCH 071/225] Fix one-page paginator --- bot.py | 2 +- core/paginator.py | 34 +++++++++++++++++++++------------- pyproject.toml | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/bot.py b/bot.py index da1e7117a3..592dbcb3b9 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev8" +__version__ = "4.0.0-dev9" import asyncio diff --git a/core/paginator.py b/core/paginator.py index 39d0c434a3..5a6844f382 100644 --- a/core/paginator.py +++ b/core/paginator.py @@ -87,27 +87,31 @@ async def show_page(self, index: int) -> typing.Optional[typing.Dict]: def update_disabled_status(self): if self.current == self.first_page(): # disable << button - if self._buttons_map["<<"]: + if self._buttons_map["<<"] is not None: self._buttons_map["<<"].disabled = True - self._buttons_map["<"].disabled = True + if self._buttons_map["<"] is not None: + self._buttons_map["<"].disabled = True else: - if self._buttons_map["<<"]: + if self._buttons_map["<<"] is not None: self._buttons_map["<<"].disabled = False - self._buttons_map["<"].disabled = False + if self._buttons_map["<"] is not None: + self._buttons_map["<"].disabled = False if self.current == self.last_page(): # disable >> button if self._buttons_map[">>"] is not None: self._buttons_map[">>"].disabled = True - self._buttons_map[">"].disabled = True + if self._buttons_map[">"] is not None: + self._buttons_map[">"].disabled = True else: if self._buttons_map[">>"] is not None: self._buttons_map[">>"].disabled = False - self._buttons_map[">"].disabled = False + if self._buttons_map[">"] is not None: + self._buttons_map[">"].disabled = False async def create_base(self, item) -> None: """ @@ -151,7 +155,10 @@ async def run(self) -> typing.Optional[Message]: """ if not self.running: await self.show_page(self.current) - await self.view.wait() + + if self.view is not None: + await self.view.wait() + await self.close(delete=False) async def close( @@ -182,12 +189,13 @@ async def close( self.running = False - self.view.stop() - if delete: - await message.delete() - else: - self.view.clear_items() - await message.edit(view=self.view) + if self.view is not None: + self.view.stop() + if delete: + await message.delete() + else: + self.view.clear_items() + await message.edit(view=self.view) class PaginatorView(View): diff --git a/pyproject.toml b/pyproject.toml index ad792dc399..3b821dd6f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev8' +version = '4.0.0-dev9' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From d54b687bc69933f05f6056d1600331a051bfb65a Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 21:40:55 +0800 Subject: [PATCH 072/225] fix gh cmd, resolve #3149 --- core/clients.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/clients.py b/core/clients.py index 5caf58f4d2..a9722776f2 100644 --- a/core/clients.py +++ b/core/clients.py @@ -680,7 +680,7 @@ async def get_user_info(self) -> Optional[dict]: return { "user": { "username": user.username, - "avatar_url": user.display_avatar.url, + "avatar_url": user.avatar_url, "url": user.url, } } From 46f711af61962551cf8c8d03850528efa8b2bdb5 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 21:43:47 +0800 Subject: [PATCH 073/225] add title to ?logs, resolve #3142 --- cogs/modmail.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cogs/modmail.py b/cogs/modmail.py index 63997b2824..ea36bef7b9 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -656,6 +656,9 @@ def format_log_embeds(self, logs, avatar_url): if entry["recipient"]["id"] != entry["creator"]["id"]: embed.add_field(name="Created by", value=f"<@{entry['creator']['id']}>") + if entry["title"]: + embed.add_field(name="Title", value=entry["title"], inline=False) + embed.add_field(name="Preview", value=format_preview(entry["messages"]), inline=False) if closer is not None: From a11c0ed9525dee63522a393b49d30833b559e95a Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 21:47:56 +0800 Subject: [PATCH 074/225] fix delete channel autoclose functionality --- CHANGELOG.md | 2 ++ bot.py | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb025baca2..4b75c286aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `use_nickname_channel_name` config to use nicknames instead of usernames for channel names. ([GH #3112](https://github.com/kyb3r/modmail/issues/3112)) - `show_log_url_button` config to show Log URL button. ([GH #3122](https://github.com/kyb3r/modmail/issues/3122)) - Select menus for certain paginators. +- `Title` field in `?logs`. ([GH #3142](https://github.com/kyb3r/modmail/issues/3142)) ### Improved @@ -45,6 +46,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Commands now work in threads. - Audit log searching now properly works. - Old data causing `?blocked` to fail. ([GH #3131](https://github.com/kyb3r/modmail/issues/3131)) +- Delete channel auto close functionality now works. ### Internal diff --git a/bot.py b/bot.py index 592dbcb3b9..4ff3e69091 100644 --- a/bot.py +++ b/bot.py @@ -1336,9 +1336,13 @@ async def on_guild_channel_delete(self, channel): return audit_logs = self.modmail_guild.audit_logs(limit=10, action=discord.AuditLogAction.channel_delete) - entry = await audit_logs.find(lambda a: int(a.target.id) == channel.id) + found_entry = False + async for entry in audit_logs: + if int(entry.target.id) == channel.id: + found_entry = True + break - if entry is None: + if not found_entry: logger.debug("Cannot find the audit log entry for channel delete of %d.", channel.id) return From 4aed3b42d3d94161073d840941419444aac5eb5e Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 21:57:55 +0800 Subject: [PATCH 075/225] Update dpy@a14b43f2fda863ed6555374eb872bf014bdd1adf --- Pipfile | 2 +- Pipfile.lock | 260 ++++++++++++++++++++++++----------------------- bot.py | 2 +- pyproject.toml | 2 +- requirements.txt | 2 +- 5 files changed, 135 insertions(+), 133 deletions(-) diff --git a/Pipfile b/Pipfile index 1241feeb40..c74f6cb1a7 100644 --- a/Pipfile +++ b/Pipfile @@ -11,7 +11,7 @@ pylint = "~=2.9.3" [packages] aiohttp = "==3.7.4.post0" colorama = "~=0.4.4" # Doesn't officially support Python 3.9 yet, v0.4.5 will support 3.9 -"discord.py" = {ref = "987235d5649e7c2b1a927637bab6547244ecb2cf", git = "https://github.com/Rapptz/discord.py.git"} +"discord.py" = {git = "https://github.com/Rapptz/discord.py.git"} emoji = "~=1.2.0" isodate = "~=0.6.0" motor = "~=2.4.0" diff --git a/Pipfile.lock b/Pipfile.lock index 5cd3d63616..d163dd5ae1 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "5f3ca86a89bbc9bcda36bdb3503c91f81ff9c5e12409c3ad056524aa920f4fad" + "sha256": "c0006885019e90564b0907b571e5a7bcd5f8b47d1dc3c535959f2600d4d15ba6" }, "pipfile-spec": 6, "requires": { @@ -163,11 +163,11 @@ }, "cssselect2": { "hashes": [ - "sha256:8d4690bce5f25013262997e64cef3e7bade877d3ef126f9cc624e5b1f294d934", - "sha256:d98a7bbdd8ebc46093279195d669a3359bd5a23f90c19e82c19d9eeef333e617" + "sha256:3a83b2a68370c69c9cd3fcb88bbfaebe9d22edeef2c22d1ff3e1ed9c7fa45ed8", + "sha256:5b5d6dea81a5eb0c9ca39f116c8578dd413778060c94c1f51196371618909325" ], "markers": "python_version >= '3.7'", - "version": "==0.5.0" + "version": "==0.6.0" }, "defusedxml": { "hashes": [ @@ -179,11 +179,10 @@ }, "discord-py": { "git": "https://github.com/Rapptz/discord.py.git", - "ref": "97fe07edb2f3d0f5a980917fb6ee479bf396fd94" + "ref": "a14b43f2fda863ed6555374eb872bf014bdd1adf" }, "discord.py": { - "git": "https://github.com/Rapptz/discord.py.git", - "ref": "97fe07edb2f3d0f5a980917fb6ee479bf396fd94" + "git": "https://github.com/Rapptz/discord.py.git" }, "dnspython": { "hashes": [ @@ -317,44 +316,47 @@ }, "pillow": { "hashes": [ - "sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97", - "sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049", - "sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c", - "sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae", - "sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28", - "sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030", - "sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56", - "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976", - "sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e", - "sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e", - "sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f", - "sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b", - "sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a", - "sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e", - "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa", - "sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7", - "sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00", - "sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838", - "sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360", - "sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b", - "sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a", - "sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd", - "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4", - "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70", - "sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204", - "sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc", - "sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b", - "sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669", - "sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7", - "sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e", - "sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c", - "sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092", - "sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c", - "sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5", - "sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac" + "sha256:01ce45deec9df310cbbee11104bae1a2a43308dd9c317f99235b6d3080ddd66e", + "sha256:0c51cb9edac8a5abd069fd0758ac0a8bfe52c261ee0e330f363548aca6893595", + "sha256:17869489de2fce6c36690a0c721bd3db176194af5f39249c1ac56d0bb0fcc512", + "sha256:21dee8466b42912335151d24c1665fcf44dc2ee47e021d233a40c3ca5adae59c", + "sha256:25023a6209a4d7c42154073144608c9a71d3512b648a2f5d4465182cb93d3477", + "sha256:255c9d69754a4c90b0ee484967fc8818c7ff8311c6dddcc43a4340e10cd1636a", + "sha256:35be4a9f65441d9982240e6966c1eaa1c654c4e5e931eaf580130409e31804d4", + "sha256:3f42364485bfdab19c1373b5cd62f7c5ab7cc052e19644862ec8f15bb8af289e", + "sha256:3fddcdb619ba04491e8f771636583a7cc5a5051cd193ff1aa1ee8616d2a692c5", + "sha256:463acf531f5d0925ca55904fa668bb3461c3ef6bc779e1d6d8a488092bdee378", + "sha256:4fe29a070de394e449fd88ebe1624d1e2d7ddeed4c12e0b31624561b58948d9a", + "sha256:55dd1cf09a1fd7c7b78425967aacae9b0d70125f7d3ab973fadc7b5abc3de652", + "sha256:5a3ecc026ea0e14d0ad7cd990ea7f48bfcb3eb4271034657dc9d06933c6629a7", + "sha256:5cfca31ab4c13552a0f354c87fbd7f162a4fafd25e6b521bba93a57fe6a3700a", + "sha256:66822d01e82506a19407d1afc104c3fcea3b81d5eb11485e593ad6b8492f995a", + "sha256:69e5ddc609230d4408277af135c5b5c8fe7a54b2bdb8ad7c5100b86b3aab04c6", + "sha256:6b6d4050b208c8ff886fd3db6690bf04f9a48749d78b41b7a5bf24c236ab0165", + "sha256:7a053bd4d65a3294b153bdd7724dce864a1d548416a5ef61f6d03bf149205160", + "sha256:82283af99c1c3a5ba1da44c67296d5aad19f11c535b551a5ae55328a317ce331", + "sha256:8782189c796eff29dbb37dd87afa4ad4d40fc90b2742704f94812851b725964b", + "sha256:8d79c6f468215d1a8415aa53d9868a6b40c4682165b8cb62a221b1baa47db458", + "sha256:97bda660702a856c2c9e12ec26fc6d187631ddfd896ff685814ab21ef0597033", + "sha256:a325ac71914c5c043fa50441b36606e64a10cd262de12f7a179620f579752ff8", + "sha256:a336a4f74baf67e26f3acc4d61c913e378e931817cd1e2ef4dfb79d3e051b481", + "sha256:a598d8830f6ef5501002ae85c7dbfcd9c27cc4efc02a1989369303ba85573e58", + "sha256:a5eaf3b42df2bcda61c53a742ee2c6e63f777d0e085bbc6b2ab7ed57deb13db7", + "sha256:aea7ce61328e15943d7b9eaca87e81f7c62ff90f669116f857262e9da4057ba3", + "sha256:af79d3fde1fc2e33561166d62e3b63f0cc3e47b5a3a2e5fea40d4917754734ea", + "sha256:c24f718f9dd73bb2b31a6201e6db5ea4a61fdd1d1c200f43ee585fc6dcd21b34", + "sha256:c5b0ff59785d93b3437c3703e3c64c178aabada51dea2a7f2c5eccf1bcf565a3", + "sha256:c7110ec1701b0bf8df569a7592a196c9d07c764a0a74f65471ea56816f10e2c8", + "sha256:c870193cce4b76713a2b29be5d8327c8ccbe0d4a49bc22968aa1e680930f5581", + "sha256:c9efef876c21788366ea1f50ecb39d5d6f65febe25ad1d4c0b8dff98843ac244", + "sha256:de344bcf6e2463bb25179d74d6e7989e375f906bcec8cb86edb8b12acbc7dfef", + "sha256:eb1b89b11256b5b6cad5e7593f9061ac4624f7651f7a8eb4dfa37caa1dfaa4d0", + "sha256:ed742214068efa95e9844c2d9129e209ed63f61baa4d54dbf4cf8b5e2d30ccf2", + "sha256:f401ed2bbb155e1ade150ccc63db1a4f6c1909d3d378f7d1235a44e90d75fb97", + "sha256:fb89397013cf302f282f0fc998bb7abf11d49dcff72c8ecb320f76ea6e2c5717" ], "markers": "python_version >= '3.7'", - "version": "==9.0.1" + "version": "==9.1.0" }, "pycparser": { "hashes": [ @@ -513,11 +515,11 @@ }, "typing-extensions": { "hashes": [ - "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42", - "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2" + "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", + "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376" ], - "markers": "python_version >= '3.6'", - "version": "==4.1.1" + "markers": "python_version >= '3.7'", + "version": "==4.2.0" }, "uvloop": { "hashes": [ @@ -661,11 +663,11 @@ }, "click": { "hashes": [ - "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1", - "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb" + "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e", + "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72" ], - "markers": "python_version >= '3.6'", - "version": "==8.0.4" + "markers": "python_version >= '3.7'", + "version": "==8.1.2" }, "colorama": { "hashes": [ @@ -820,91 +822,91 @@ }, "regex": { "hashes": [ - "sha256:0066a6631c92774391f2ea0f90268f0d82fffe39cb946f0f9c6b382a1c61a5e5", - "sha256:0100f0ded953b6b17f18207907159ba9be3159649ad2d9b15535a74de70359d3", - "sha256:01c913cf573d1da0b34c9001a94977273b5ee2fe4cb222a5d5b320f3a9d1a835", - "sha256:0214ff6dff1b5a4b4740cfe6e47f2c4c92ba2938fca7abbea1359036305c132f", - "sha256:029e9e7e0d4d7c3446aa92474cbb07dafb0b2ef1d5ca8365f059998c010600e6", - "sha256:0317eb6331146c524751354ebef76a7a531853d7207a4d760dfb5f553137a2a4", - "sha256:04b5ee2b6d29b4a99d38a6469aa1db65bb79d283186e8460542c517da195a8f6", - "sha256:04c09b9651fa814eeeb38e029dc1ae83149203e4eeb94e52bb868fadf64852bc", - "sha256:058054c7a54428d5c3e3739ac1e363dc9347d15e64833817797dc4f01fb94bb8", - "sha256:060f9066d2177905203516c62c8ea0066c16c7342971d54204d4e51b13dfbe2e", - "sha256:0a7b75cc7bb4cc0334380053e4671c560e31272c9d2d5a6c4b8e9ae2c9bd0f82", - "sha256:0e2630ae470d6a9f8e4967388c1eda4762706f5750ecf387785e0df63a4cc5af", - "sha256:174d964bc683b1e8b0970e1325f75e6242786a92a22cedb2a6ec3e4ae25358bd", - "sha256:25ecb1dffc5e409ca42f01a2b2437f93024ff1612c1e7983bad9ee191a5e8828", - "sha256:286908cbe86b1a0240a867aecfe26a439b16a1f585d2de133540549831f8e774", - "sha256:303b15a3d32bf5fe5a73288c316bac5807587f193ceee4eb6d96ee38663789fa", - "sha256:34bb30c095342797608727baf5c8aa122406aa5edfa12107b8e08eb432d4c5d7", - "sha256:3e265b388cc80c7c9c01bb4f26c9e536c40b2c05b7231fbb347381a2e1c8bf43", - "sha256:3e4d710ff6539026e49f15a3797c6b1053573c2b65210373ef0eec24480b900b", - "sha256:42eb13b93765c6698a5ab3bcd318d8c39bb42e5fa8a7fcf7d8d98923f3babdb1", - "sha256:48081b6bff550fe10bcc20c01cf6c83dbca2ccf74eeacbfac240264775fd7ecf", - "sha256:491fc754428514750ab21c2d294486223ce7385446f2c2f5df87ddbed32979ae", - "sha256:4d1445824944e642ffa54c4f512da17a953699c563a356d8b8cbdad26d3b7598", - "sha256:530a3a16e57bd3ea0dff5ec2695c09632c9d6c549f5869d6cf639f5f7153fb9c", - "sha256:591d4fba554f24bfa0421ba040cd199210a24301f923ed4b628e1e15a1001ff4", - "sha256:5a86cac984da35377ca9ac5e2e0589bd11b3aebb61801204bd99c41fac516f0d", - "sha256:5b1ceede92400b3acfebc1425937454aaf2c62cd5261a3fabd560c61e74f6da3", - "sha256:5b2e24f3ae03af3d8e8e6d824c891fea0ca9035c5d06ac194a2700373861a15c", - "sha256:6504c22c173bb74075d7479852356bb7ca80e28c8e548d4d630a104f231e04fb", - "sha256:673f5a393d603c34477dbad70db30025ccd23996a2d0916e942aac91cc42b31a", - "sha256:6ca6dcd17f537e9f3793cdde20ac6076af51b2bd8ad5fe69fa54373b17b48d3c", - "sha256:6e1d8ed9e61f37881c8db383a124829a6e8114a69bd3377a25aecaeb9b3538f8", - "sha256:75a5e6ce18982f0713c4bac0704bf3f65eed9b277edd3fb9d2b0ff1815943327", - "sha256:76435a92e444e5b8f346aed76801db1c1e5176c4c7e17daba074fbb46cb8d783", - "sha256:764e66a0e382829f6ad3bbce0987153080a511c19eb3d2f8ead3f766d14433ac", - "sha256:78ce90c50d0ec970bd0002462430e00d1ecfd1255218d52d08b3a143fe4bde18", - "sha256:794a6bc66c43db8ed06698fc32aaeaac5c4812d9f825e9589e56f311da7becd9", - "sha256:797437e6024dc1589163675ae82f303103063a0a580c6fd8d0b9a0a6708da29e", - "sha256:7b7494df3fdcc95a1f76cf134d00b54962dd83189520fd35b8fcd474c0aa616d", - "sha256:7d1a6e403ac8f1d91d8f51c441c3f99367488ed822bda2b40836690d5d0059f5", - "sha256:7f63877c87552992894ea1444378b9c3a1d80819880ae226bb30b04789c0828c", - "sha256:8923e1c5231549fee78ff9b2914fad25f2e3517572bb34bfaa3aea682a758683", - "sha256:8afcd1c2297bc989dceaa0379ba15a6df16da69493635e53431d2d0c30356086", - "sha256:8b1cc70e31aacc152a12b39245974c8fccf313187eead559ee5966d50e1b5817", - "sha256:8d1f3ea0d1924feb4cf6afb2699259f658a08ac6f8f3a4a806661c2dfcd66db1", - "sha256:940570c1a305bac10e8b2bc934b85a7709c649317dd16520471e85660275083a", - "sha256:947a8525c0a95ba8dc873191f9017d1b1e3024d4dc757f694e0af3026e34044a", - "sha256:9beb03ff6fe509d6455971c2489dceb31687b38781206bcec8e68bdfcf5f1db2", - "sha256:9c144405220c5ad3f5deab4c77f3e80d52e83804a6b48b6bed3d81a9a0238e4c", - "sha256:a98ae493e4e80b3ded6503ff087a8492db058e9c68de371ac3df78e88360b374", - "sha256:aa2ce79f3889720b46e0aaba338148a1069aea55fda2c29e0626b4db20d9fcb7", - "sha256:aa5eedfc2461c16a092a2fabc5895f159915f25731740c9152a1b00f4bcf629a", - "sha256:ab5d89cfaf71807da93c131bb7a19c3e19eaefd613d14f3bce4e97de830b15df", - "sha256:b4829db3737480a9d5bfb1c0320c4ee13736f555f53a056aacc874f140e98f64", - "sha256:b52771f05cff7517f7067fef19ffe545b1f05959e440d42247a17cd9bddae11b", - "sha256:b8248f19a878c72d8c0a785a2cd45d69432e443c9f10ab924c29adda77b324ae", - "sha256:b9809404528a999cf02a400ee5677c81959bc5cb938fdc696b62eb40214e3632", - "sha256:c155a1a80c5e7a8fa1d9bb1bf3c8a953532b53ab1196092749bafb9d3a7cbb60", - "sha256:c33ce0c665dd325200209340a88438ba7a470bd5f09f7424e520e1a3ff835b52", - "sha256:c5adc854764732dbd95a713f2e6c3e914e17f2ccdc331b9ecb777484c31f73b6", - "sha256:cb374a2a4dba7c4be0b19dc7b1adc50e6c2c26c3369ac629f50f3c198f3743a4", - "sha256:cd00859291658fe1fda48a99559fb34da891c50385b0bfb35b808f98956ef1e7", - "sha256:ce3057777a14a9a1399b81eca6a6bfc9612047811234398b84c54aeff6d536ea", - "sha256:d0a5a1fdc9f148a8827d55b05425801acebeeefc9e86065c7ac8b8cc740a91ff", - "sha256:dad3991f0678facca1a0831ec1ddece2eb4d1dd0f5150acb9440f73a3b863907", - "sha256:dc7b7c16a519d924c50876fb152af661a20749dcbf653c8759e715c1a7a95b18", - "sha256:dcbb7665a9db9f8d7642171152c45da60e16c4f706191d66a1dc47ec9f820aed", - "sha256:df037c01d68d1958dad3463e2881d3638a0d6693483f58ad41001aa53a83fcea", - "sha256:f08a7e4d62ea2a45557f561eea87c907222575ca2134180b6974f8ac81e24f06", - "sha256:f16cf7e4e1bf88fecf7f41da4061f181a6170e179d956420f84e700fb8a3fd6b", - "sha256:f2c53f3af011393ab5ed9ab640fa0876757498aac188f782a0c620e33faa2a3d", - "sha256:f320c070dea3f20c11213e56dbbd7294c05743417cde01392148964b7bc2d31a", - "sha256:f553a1190ae6cd26e553a79f6b6cfba7b8f304da2071052fa33469da075ea625", - "sha256:fc8c7958d14e8270171b3d72792b609c057ec0fa17d507729835b5cff6b7f69a" + "sha256:02543d6d5c32d361b7cc468079ba4cddaaf4a6544f655901ba1ff9d8e3f18755", + "sha256:036d1c1fbe69eba3ee253c107e71749cdbb4776db93d674bc0d5e28f30300734", + "sha256:071bcb625e890f28b7c4573124a6512ea65107152b1d3ca101ce33a52dad4593", + "sha256:0f8da3145f4b72f7ce6181c804eaa44cdcea313c8998cdade3d9e20a8717a9cb", + "sha256:0fb6cb16518ac7eff29d1e0b0cce90275dfae0f17154165491058c31d58bdd1d", + "sha256:0fd464e547dbabf4652ca5fe9d88d75ec30182981e737c07b3410235a44b9939", + "sha256:12af15b6edb00e425f713160cfd361126e624ec0de86e74f7cad4b97b7f169b3", + "sha256:165cc75cfa5aa0f12adb2ac6286330e7229a06dc0e6c004ec35da682b5b89579", + "sha256:1a07e8366115069f26822c47732122ab61598830a69f5629a37ea8881487c107", + "sha256:1c2de7f32fa87d04d40f54bce3843af430697aba51c3a114aa62837a0772f219", + "sha256:253f858a0255cd91a0424a4b15c2eedb12f20274f85731b0d861c8137e843065", + "sha256:275afc7352982ee947fc88f67a034b52c78395977b5fc7c9be15f7dc95b76f06", + "sha256:2bde99f2cdfd6db1ec7e02d68cadd384ffe7413831373ea7cc68c5415a0cb577", + "sha256:3241db067a7f69da57fba8bca543ac8a7ca415d91e77315690202749b9fdaba1", + "sha256:37903d5ca11fa47577e8952d2e2c6de28553b11c70defee827afb941ab2c6729", + "sha256:3dfbadb7b74d95f72f9f9dbf9778f7de92722ab520a109ceaf7927461fa85b10", + "sha256:3e35c50b27f36176c792738cb9b858523053bc495044d2c2b44db24376b266f1", + "sha256:3e9e983fc8e0d4d5ded7caa5aed39ca2cf6026d7e39801ef6f0af0b1b6cd9276", + "sha256:3f6bd8178cce5bb56336722d5569d19c50bba5915a69a2050c497fb921e7cb0f", + "sha256:43ee0df35925ae4b0cc6ee3f60b73369e559dd2ac40945044da9394dd9d3a51d", + "sha256:45b761406777a681db0c24686178532134c937d24448d9e085279b69e9eb7da4", + "sha256:46cbc5b23f85e94161b093dba1b49035697cf44c7db3c930adabfc0e6d861b95", + "sha256:4f2e2cef324ca9355049ee1e712f68e2e92716eba24275e6767b9bfa15f1f478", + "sha256:50b77622016f03989cd06ecf6b602c7a6b4ed2e3ce04133876b041d109c934ee", + "sha256:582ea06079a03750b5f71e20a87cd99e646d796638b5894ff85987ebf5e04924", + "sha256:58521abdab76583bd41ef47e5e2ddd93b32501aee4ee8cee71dee10a45ba46b1", + "sha256:5b9c7b6895a01204296e9523b3e12b43e013835a9de035a783907c2c1bc447f0", + "sha256:6165e737acb3bea3271372e8aa5ebe7226c8a8e8da1b94af2d6547c5a09d689d", + "sha256:66fb765b2173d90389384708e3e1d3e4be1148bd8d4d50476b1469da5a2f0229", + "sha256:68aed3fb0c61296bd6d234f558f78c51671f79ccb069cbcd428c2eea6fee7a5b", + "sha256:6a0ef57cccd8089b4249eebad95065390e56c04d4a92c51316eab4131bca96a9", + "sha256:709396c0c95b95045fac89b94f997410ff39b81a09863fe21002f390d48cc7d3", + "sha256:73ed1b06abadbf6b61f6033a07c06f36ec0ddca117e41ef2ac37056705e46458", + "sha256:7a608022f4593fc67518c6c599ae5abdb03bb8acd75993c82cd7a4c8100eff81", + "sha256:7c4d9770e579eb11b582b2e2fd19fa204a15cb1589ae73cd4dcbb63b64f3e828", + "sha256:7dbc96419ef0fb6ac56626014e6d3a345aeb8b17a3df8830235a88626ffc8d84", + "sha256:7f271d0831d8ebc56e17b37f9fa1824b0379221d1238ae77c18a6e8c47f1fdce", + "sha256:82b7fc67e49fdce671bdbec1127189fc979badf062ce6e79dc95ef5e07a8bf92", + "sha256:85b7ee4d0c7a46296d884f6b489af8b960c4291d76aea4b22fd4fbe05e6ec08e", + "sha256:8b747cef8e5dcdaf394192d43a0c02f5825aeb0ecd3d43e63ae500332ab830b0", + "sha256:8bf867ba71856414a482e4b683500f946c300c4896e472e51d3db8dfa8dc8f32", + "sha256:8e0da7ef160d4f3eb3d4d3e39a02c3c42f7dbcfce62c81f784cc99fc7059765f", + "sha256:8e7d33f93cdd01868327d834d0f5bb029241cd293b47d51b96814dec27fc9b4b", + "sha256:92183e9180c392371079262879c6532ccf55f808e6900df5d9f03c9ca8807255", + "sha256:92ad03f928675ca05b79d3b1d3dfc149e2226d57ed9d57808f82105d511d0212", + "sha256:97af238389cb029d63d5f2d931a7e8f5954ad96e812de5faaed373b68e74df86", + "sha256:9913bcf730eb6e9b441fb176832eea9acbebab6035542c7c89d90c803f5cd3be", + "sha256:9dae5affbb66178dad6c6fd5b02221ca9917e016c75ee3945e9a9563eb1fbb6f", + "sha256:a850f5f369f1e3b6239da7fb43d1d029c1e178263df671819889c47caf7e4ff3", + "sha256:aa6daa189db9104787ff1fd7a7623ce017077aa59eaac609d0d25ba95ed251a0", + "sha256:aabc28f7599f781ddaeac168d0b566d0db82182cc3dcf62129f0a4fc2927b811", + "sha256:af1e687ffab18a75409e5e5d6215b6ccd41a5a1a0ea6ce9665e01253f737a0d3", + "sha256:b1d53835922cd0f9b74b2742453a444865a70abae38d12eb41c59271da66f38d", + "sha256:b2df3ede85d778c949d9bd2a50237072cee3df0a423c91f5514f78f8035bde87", + "sha256:b415b82e5be7389ec5ee7ee35431e4a549ea327caacf73b697c6b3538cb5c87f", + "sha256:b7ba3c304a4a5d8112dbd30df8b3e4ef59b4b07807957d3c410d9713abaee9a8", + "sha256:bcc6f7a3a95119c3568c572ca167ada75f8319890706283b9ba59b3489c9bcb3", + "sha256:be392d9cd5309509175a9d7660dc17bf57084501108dbff0c5a8bfc3646048c3", + "sha256:bea61de0c688198e3d9479344228c7accaa22a78b58ec408e41750ebafee6c08", + "sha256:bedb3d01ad35ea1745bdb1d57f3ee0f996f988c98f5bbae9d068c3bb3065d210", + "sha256:c36906a7855ec33a9083608e6cd595e4729dab18aeb9aad0dd0b039240266239", + "sha256:c4fdf837666f7793a5c3cfa2f2f39f03eb6c7e92e831bc64486c2f547580c2b3", + "sha256:cfad3a770839aa456ff9a9aa0e253d98b628d005a3ccb37da1ff9be7c84fee16", + "sha256:d128e278e5e554c5c022c7bed410ca851e00bacebbb4460de546a73bc53f8de4", + "sha256:dffd9114ade73137ab2b79a8faf864683dbd2dbbb6b23a305fbbd4cbaeeb2187", + "sha256:e2acf5c66fbb62b5fe4c40978ddebafa50818f00bf79d60569d9762f6356336e", + "sha256:e65580ae3137bce712f505ec7c2d700aef0014a3878c4767b74aff5895fc454f", + "sha256:e944268445b5694f5d41292c9228f0ca46d5a32a67f195d5f8547c1f1d91f4bc", + "sha256:ed26c3d2d62c6588e0dad175b8d8cc0942a638f32d07b80f92043e5d73b7db67", + "sha256:ed625205f5f26984382b68e4cbcbc08e6603c9e84c14b38457170b0cc71c823b", + "sha256:f2a5d9f612091812dee18375a45d046526452142e7b78c4e21ab192db15453d5", + "sha256:f86aef546add4ff1202e1f31e9bb54f9268f17d996b2428877283146bf9bc013", + "sha256:f89d26e50a4c7453cb8c415acd09e72fbade2610606a9c500a1e48c43210a42d", + "sha256:fb7107faf0168de087f62a2f2ed00f9e9da12e0b801582b516ddac236b871cda" ], "markers": "python_version >= '3.6'", - "version": "==2022.3.15" + "version": "==2022.4.24" }, "setuptools": { "hashes": [ - "sha256:6599055eeb23bfef457d5605d33a4d68804266e6cb430b0fb12417c5efeae36c", - "sha256:782ef48d58982ddb49920c11a0c5c9c0b02e7d7d1c2ad0aa44e1a1e133051c96" + "sha256:26ead7d1f93efc0f8c804d9fafafbe4a44b179580a7105754b245155f9af05a8", + "sha256:47c7b0c0f8fc10eec4cf1e71c6fdadf8decaa74ffa087e68cd1c20db7ad6a592" ], "markers": "python_version >= '3.7'", - "version": "==60.10.0" + "version": "==62.1.0" }, "smmap": { "hashes": [ diff --git a/bot.py b/bot.py index 4ff3e69091..2887fd79dc 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev9" +__version__ = "4.0.0-dev10" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 3b821dd6f8..9d08c1d2b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev9' +version = '4.0.0-dev10' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ diff --git a/requirements.txt b/requirements.txt index f0e1933ce0..5a595bb521 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,7 @@ chardet==4.0.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2 colorama==0.4.4 dnspython==2.1.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' emoji==1.2.0 -git+https://github.com/Rapptz/discord.py.git@987235d5649e7c2b1a927637bab6547244ecb2cf#egg=discord-py +git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord-py idna==3.3; python_version >= '3.5' isodate==0.6.0 motor==2.4.0 From 16816f32158b8b1819ab645b52b3dda7d0cc47a8 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 22:01:35 +0800 Subject: [PATCH 076/225] formatting --- cogs/utility.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cogs/utility.py b/cogs/utility.py index 7facfbf1d2..df904cd331 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -914,9 +914,7 @@ def fmt(val): for i, (current_key, info) in enumerate(config_help.items()): if current_key == key: index = i - embed = discord.Embed( - title=f"{current_key}", color=self.bot.main_color - ) + embed = discord.Embed(title=f"{current_key}", color=self.bot.main_color) embed.add_field(name="Default:", value=fmt(info["default"]), inline=False) embed.add_field(name="Information:", value=fmt(info["description"]), inline=False) if info["examples"]: From 4f15cf6666f59f915d9ed6eeab03fe1154151203 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 22:06:27 +0800 Subject: [PATCH 077/225] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4696b7067c..55a23a8db3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,13 +25,13 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `show_log_url_button` config to show Log URL button. ([GH #3122](https://github.com/kyb3r/modmail/issues/3122)) - Select menus for certain paginators. - `Title` field in `?logs`. ([GH #3142](https://github.com/kyb3r/modmail/issues/3142)) +- Snippets can be used in aliases. ([GH #3108](https://github.com/kyb3r/modmail/issues/3108), [PR #3124](https://github.com/kyb3r/modmail/pull/3124)) ### Improved - Modmail now uses per-server avatars if applicable. ([GH #3048](https://github.com/kyb3r/modmail/issues/3048)) - Use discord relative timedeltas. ([GH #3046](https://github.com/kyb3r/modmail/issues/3046)) - Use discord native buttons for all paginator sessions. -- Snippets can be used in aliases. ([GH #3108](https://github.com/kyb3r/modmail/issues/3108), [PR #3124](https://github.com/kyb3r/modmail/pull/3124)) ### Fixed From 70decd82e835e942be08e8552567e3f97e830763 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 22:16:59 +0800 Subject: [PATCH 078/225] Fix reqs --- Pipfile | 5 +-- Pipfile.lock | 9 +++--- requirements.txt | 79 ++++++++++++++++++++++++------------------------ 3 files changed, 45 insertions(+), 48 deletions(-) diff --git a/Pipfile b/Pipfile index c74f6cb1a7..9c537d8bd2 100644 --- a/Pipfile +++ b/Pipfile @@ -11,7 +11,7 @@ pylint = "~=2.9.3" [packages] aiohttp = "==3.7.4.post0" colorama = "~=0.4.4" # Doesn't officially support Python 3.9 yet, v0.4.5 will support 3.9 -"discord.py" = {git = "https://github.com/Rapptz/discord.py.git"} +"discord.py" = {ref = "a14b43f2fda863ed6555374eb872bf014bdd1adf", git = "https://github.com/Rapptz/discord.py.git"} emoji = "~=1.2.0" isodate = "~=0.6.0" motor = "~=2.4.0" @@ -25,6 +25,3 @@ lottie = {version = "==0.6.10", extras = ["pdf"]} [scripts] bot = "python bot.py" - -[requires] -python_version = "3.9" diff --git a/Pipfile.lock b/Pipfile.lock index d163dd5ae1..ec6f1fc5c6 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,12 +1,10 @@ { "_meta": { "hash": { - "sha256": "c0006885019e90564b0907b571e5a7bcd5f8b47d1dc3c535959f2600d4d15ba6" + "sha256": "5280f0d7e4c267e164f83139d89bec37c4691a5815b831b871a3091db1af56eb" }, "pipfile-spec": 6, - "requires": { - "python_version": "3.9" - }, + "requires": {}, "sources": [ { "name": "pypi", @@ -182,7 +180,8 @@ "ref": "a14b43f2fda863ed6555374eb872bf014bdd1adf" }, "discord.py": { - "git": "https://github.com/Rapptz/discord.py.git" + "git": "https://github.com/Rapptz/discord.py.git", + "ref": "a14b43f2fda863ed6555374eb872bf014bdd1adf" }, "dnspython": { "hashes": [ diff --git a/requirements.txt b/requirements.txt index 8b6e2499cc..34852a4e37 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,39 +1,40 @@ -# -# These requirements were autogenerated by pipenv -# To regenerate from the project's Pipfile, run: -# -# pipenv lock --requirements -# - --i https://pypi.org/simple -aiohttp==3.7.4.post0 -async-timeout==3.0.1; python_full_version >= '3.5.3' -attrs==21.2.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -cairocffi==1.3.0; python_version >= '3.7' -cairosvg==2.5.2; python_version >= '3.5' -cffi==1.15.0 -chardet==4.0.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -colorama==0.4.4 -cssselect2==0.4.1; python_version >= '3.6' -defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -dnspython==2.1.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -emoji==1.2.0 -git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord-py -idna==3.3; python_version >= '3.5' -isodate==0.6.0 -lottie[pdf]==0.6.10 -motor==2.4.0 -multidict==5.2.0; python_version >= '3.6' -natural==0.2.0 -parsedatetime==2.6 -pillow==8.4.0; python_version >= '3.6' -pycparser==2.21 -pymongo[srv]==3.12.1 -python-dateutil==2.8.2 -python-dotenv==0.18.0 -six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -tinycss2==1.1.0; python_version >= '3.6' -typing-extensions==4.0.0; python_version >= '3.6' -uvloop==0.16.0; sys_platform != 'win32' -webencodings==0.5.1 -yarl==1.7.2; python_version >= '3.6' \ No newline at end of file +# +# These requirements were autogenerated by pipenv +# To regenerate from the project's Pipfile, run: +# +# pipenv lock --requirements +# + +-i https://pypi.org/simple +aiohttp==3.7.4.post0 +async-timeout==3.0.1; python_full_version >= '3.5.3' +attrs==21.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +cairocffi==1.3.0; python_version >= '3.7' +cairosvg==2.5.2; python_version >= '3.5' +cffi==1.15.0 +chardet==4.0.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +colorama==0.4.4 +cssselect2==0.6.0; python_version >= '3.7' +defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +dnspython==2.2.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +emoji==1.2.0 +git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord-py +git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord.py +idna==3.3; python_version >= '3.5' +isodate==0.6.1 +lottie[pdf]==0.6.10 +motor==2.4.0 +multidict==6.0.2; python_version >= '3.7' +natural==0.2.0 +parsedatetime==2.6 +pillow==9.1.0; python_version >= '3.7' +pycparser==2.21 +pymongo[srv]==3.12.3 +python-dateutil==2.8.2 +python-dotenv==0.18.0 +six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +tinycss2==1.1.1; python_version >= '3.6' +typing-extensions==4.2.0; python_version >= '3.7' +uvloop==0.16.0; sys_platform != 'win32' +webencodings==0.5.1 +yarl==1.7.2; python_version >= '3.6' From ef100c283fdb84da6b4c6e52f21f9b2440036719 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 22:19:59 +0800 Subject: [PATCH 079/225] another attempt to fix reqs --- .github/workflows/lints.yml | 2 +- requirements.txt | 80 ++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 091e012dd9..8498875fd3 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -21,7 +21,7 @@ jobs: python-version: 3.9 - name: Install dependencies run: | - python -m pip install --upgrade pip pipenv + python -m pip install --upgrade pip pipenv click==8.1.2 pipenv install --dev --system # - name: Bandit syntax check # run: bandit -r . -b .bandit_baseline.json diff --git a/requirements.txt b/requirements.txt index 34852a4e37..ecff8c80c8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,40 +1,40 @@ -# -# These requirements were autogenerated by pipenv -# To regenerate from the project's Pipfile, run: -# -# pipenv lock --requirements -# - --i https://pypi.org/simple -aiohttp==3.7.4.post0 -async-timeout==3.0.1; python_full_version >= '3.5.3' -attrs==21.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -cairocffi==1.3.0; python_version >= '3.7' -cairosvg==2.5.2; python_version >= '3.5' -cffi==1.15.0 -chardet==4.0.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -colorama==0.4.4 -cssselect2==0.6.0; python_version >= '3.7' -defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -dnspython==2.2.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -emoji==1.2.0 -git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord-py -git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord.py -idna==3.3; python_version >= '3.5' -isodate==0.6.1 -lottie[pdf]==0.6.10 -motor==2.4.0 -multidict==6.0.2; python_version >= '3.7' -natural==0.2.0 -parsedatetime==2.6 -pillow==9.1.0; python_version >= '3.7' -pycparser==2.21 -pymongo[srv]==3.12.3 -python-dateutil==2.8.2 -python-dotenv==0.18.0 -six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -tinycss2==1.1.1; python_version >= '3.6' -typing-extensions==4.2.0; python_version >= '3.7' -uvloop==0.16.0; sys_platform != 'win32' -webencodings==0.5.1 -yarl==1.7.2; python_version >= '3.6' +# +# These requirements were autogenerated by pipenv +# To regenerate from the project's Pipfile, run: +# +# pipenv lock --requirements +# + +-i https://pypi.org/simple + +aiohttp==3.7.4.post0 +async-timeout==3.0.1; python_full_version >= '3.5.3' +attrs==21.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +cairocffi==1.3.0; python_version >= '3.7' +cairosvg==2.5.2; python_version >= '3.5' +cffi==1.15.0 +chardet==4.0.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +colorama==0.4.4 +cssselect2==0.6.0; python_version >= '3.7' +defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +dnspython==2.2.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +emoji==1.2.0 +git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord.py +idna==3.3; python_version >= '3.5' +isodate==0.6.1 +lottie[pdf]==0.6.10 +motor==2.4.0 +multidict==6.0.2; python_version >= '3.7' +natural==0.2.0 +parsedatetime==2.6 +pillow==9.1.0; python_version >= '3.7' +pycparser==2.21 +pymongo[srv]==3.12.3 +python-dateutil==2.8.2 +python-dotenv==0.18.0 +six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +tinycss2==1.1.1; python_version >= '3.6' +typing-extensions==4.2.0; python_version >= '3.7' +uvloop==0.16.0; sys_platform != 'win32' +webencodings==0.5.1 +yarl==1.7.2; python_version >= '3.6' From c8b1a78caa12dee7239c1d7bda92e7ad1c6dbc91 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 22:31:01 +0800 Subject: [PATCH 080/225] bump black https://github.com/psf/black/issues/2964 --- .github/workflows/lints.yml | 2 +- Pipfile | 2 +- Pipfile.lock | 132 +++++++++++------------------------- 3 files changed, 43 insertions(+), 93 deletions(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 8498875fd3..091e012dd9 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -21,7 +21,7 @@ jobs: python-version: 3.9 - name: Install dependencies run: | - python -m pip install --upgrade pip pipenv click==8.1.2 + python -m pip install --upgrade pip pipenv pipenv install --dev --system # - name: Bandit syntax check # run: bandit -r . -b .bandit_baseline.json diff --git a/Pipfile b/Pipfile index 9c537d8bd2..268523dd92 100644 --- a/Pipfile +++ b/Pipfile @@ -5,7 +5,7 @@ verify_ssl = true [dev-packages] bandit = "~=1.7.0" -black = "==21.6b0" +black = "==22.3.0" pylint = "~=2.9.3" [packages] diff --git a/Pipfile.lock b/Pipfile.lock index ec6f1fc5c6..f60ea59424 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "5280f0d7e4c267e164f83139d89bec37c4691a5815b831b871a3091db1af56eb" + "sha256": "d7f737bdd78a969ba477bc9d9b334a1429a70cb78fec53d8b95c5732bbb6a3bd" }, "pipfile-spec": 6, "requires": {}, @@ -629,13 +629,6 @@ } }, "develop": { - "appdirs": { - "hashes": [ - "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", - "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128" - ], - "version": "==1.4.4" - }, "astroid": { "hashes": [ "sha256:3975a0bd5373bdce166e60c851cfcbaf21ee96de80ec518c1f4cb3e94c3fb334", @@ -654,11 +647,32 @@ }, "black": { "hashes": [ - "sha256:dc132348a88d103016726fe360cb9ede02cecf99b76e3660ce6c596be132ce04", - "sha256:dfb8c5a069012b2ab1e972e7b908f5fb42b6bbabcba0a788b86dc05067c7d9c7" + "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b", + "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176", + "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09", + "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a", + "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015", + "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79", + "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb", + "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20", + "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464", + "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968", + "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82", + "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21", + "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0", + "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265", + "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b", + "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a", + "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72", + "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce", + "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0", + "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a", + "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163", + "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad", + "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d" ], "index": "pypi", - "version": "==21.6b0" + "version": "==22.3.0" }, "click": { "hashes": [ @@ -772,6 +786,14 @@ "markers": "python_version >= '2.6'", "version": "==5.8.1" }, + "platformdirs": { + "hashes": [ + "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788", + "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19" + ], + "markers": "python_version >= '3.7'", + "version": "==2.5.2" + }, "pylint": { "hashes": [ "sha256:2e1a0eb2e8ab41d6b5dbada87f066492bb1557b12b76c47c2ee8aa8a11186594", @@ -819,86 +841,6 @@ "markers": "python_version >= '3.6'", "version": "==6.0" }, - "regex": { - "hashes": [ - "sha256:02543d6d5c32d361b7cc468079ba4cddaaf4a6544f655901ba1ff9d8e3f18755", - "sha256:036d1c1fbe69eba3ee253c107e71749cdbb4776db93d674bc0d5e28f30300734", - "sha256:071bcb625e890f28b7c4573124a6512ea65107152b1d3ca101ce33a52dad4593", - "sha256:0f8da3145f4b72f7ce6181c804eaa44cdcea313c8998cdade3d9e20a8717a9cb", - "sha256:0fb6cb16518ac7eff29d1e0b0cce90275dfae0f17154165491058c31d58bdd1d", - "sha256:0fd464e547dbabf4652ca5fe9d88d75ec30182981e737c07b3410235a44b9939", - "sha256:12af15b6edb00e425f713160cfd361126e624ec0de86e74f7cad4b97b7f169b3", - "sha256:165cc75cfa5aa0f12adb2ac6286330e7229a06dc0e6c004ec35da682b5b89579", - "sha256:1a07e8366115069f26822c47732122ab61598830a69f5629a37ea8881487c107", - "sha256:1c2de7f32fa87d04d40f54bce3843af430697aba51c3a114aa62837a0772f219", - "sha256:253f858a0255cd91a0424a4b15c2eedb12f20274f85731b0d861c8137e843065", - "sha256:275afc7352982ee947fc88f67a034b52c78395977b5fc7c9be15f7dc95b76f06", - "sha256:2bde99f2cdfd6db1ec7e02d68cadd384ffe7413831373ea7cc68c5415a0cb577", - "sha256:3241db067a7f69da57fba8bca543ac8a7ca415d91e77315690202749b9fdaba1", - "sha256:37903d5ca11fa47577e8952d2e2c6de28553b11c70defee827afb941ab2c6729", - "sha256:3dfbadb7b74d95f72f9f9dbf9778f7de92722ab520a109ceaf7927461fa85b10", - "sha256:3e35c50b27f36176c792738cb9b858523053bc495044d2c2b44db24376b266f1", - "sha256:3e9e983fc8e0d4d5ded7caa5aed39ca2cf6026d7e39801ef6f0af0b1b6cd9276", - "sha256:3f6bd8178cce5bb56336722d5569d19c50bba5915a69a2050c497fb921e7cb0f", - "sha256:43ee0df35925ae4b0cc6ee3f60b73369e559dd2ac40945044da9394dd9d3a51d", - "sha256:45b761406777a681db0c24686178532134c937d24448d9e085279b69e9eb7da4", - "sha256:46cbc5b23f85e94161b093dba1b49035697cf44c7db3c930adabfc0e6d861b95", - "sha256:4f2e2cef324ca9355049ee1e712f68e2e92716eba24275e6767b9bfa15f1f478", - "sha256:50b77622016f03989cd06ecf6b602c7a6b4ed2e3ce04133876b041d109c934ee", - "sha256:582ea06079a03750b5f71e20a87cd99e646d796638b5894ff85987ebf5e04924", - "sha256:58521abdab76583bd41ef47e5e2ddd93b32501aee4ee8cee71dee10a45ba46b1", - "sha256:5b9c7b6895a01204296e9523b3e12b43e013835a9de035a783907c2c1bc447f0", - "sha256:6165e737acb3bea3271372e8aa5ebe7226c8a8e8da1b94af2d6547c5a09d689d", - "sha256:66fb765b2173d90389384708e3e1d3e4be1148bd8d4d50476b1469da5a2f0229", - "sha256:68aed3fb0c61296bd6d234f558f78c51671f79ccb069cbcd428c2eea6fee7a5b", - "sha256:6a0ef57cccd8089b4249eebad95065390e56c04d4a92c51316eab4131bca96a9", - "sha256:709396c0c95b95045fac89b94f997410ff39b81a09863fe21002f390d48cc7d3", - "sha256:73ed1b06abadbf6b61f6033a07c06f36ec0ddca117e41ef2ac37056705e46458", - "sha256:7a608022f4593fc67518c6c599ae5abdb03bb8acd75993c82cd7a4c8100eff81", - "sha256:7c4d9770e579eb11b582b2e2fd19fa204a15cb1589ae73cd4dcbb63b64f3e828", - "sha256:7dbc96419ef0fb6ac56626014e6d3a345aeb8b17a3df8830235a88626ffc8d84", - "sha256:7f271d0831d8ebc56e17b37f9fa1824b0379221d1238ae77c18a6e8c47f1fdce", - "sha256:82b7fc67e49fdce671bdbec1127189fc979badf062ce6e79dc95ef5e07a8bf92", - "sha256:85b7ee4d0c7a46296d884f6b489af8b960c4291d76aea4b22fd4fbe05e6ec08e", - "sha256:8b747cef8e5dcdaf394192d43a0c02f5825aeb0ecd3d43e63ae500332ab830b0", - "sha256:8bf867ba71856414a482e4b683500f946c300c4896e472e51d3db8dfa8dc8f32", - "sha256:8e0da7ef160d4f3eb3d4d3e39a02c3c42f7dbcfce62c81f784cc99fc7059765f", - "sha256:8e7d33f93cdd01868327d834d0f5bb029241cd293b47d51b96814dec27fc9b4b", - "sha256:92183e9180c392371079262879c6532ccf55f808e6900df5d9f03c9ca8807255", - "sha256:92ad03f928675ca05b79d3b1d3dfc149e2226d57ed9d57808f82105d511d0212", - "sha256:97af238389cb029d63d5f2d931a7e8f5954ad96e812de5faaed373b68e74df86", - "sha256:9913bcf730eb6e9b441fb176832eea9acbebab6035542c7c89d90c803f5cd3be", - "sha256:9dae5affbb66178dad6c6fd5b02221ca9917e016c75ee3945e9a9563eb1fbb6f", - "sha256:a850f5f369f1e3b6239da7fb43d1d029c1e178263df671819889c47caf7e4ff3", - "sha256:aa6daa189db9104787ff1fd7a7623ce017077aa59eaac609d0d25ba95ed251a0", - "sha256:aabc28f7599f781ddaeac168d0b566d0db82182cc3dcf62129f0a4fc2927b811", - "sha256:af1e687ffab18a75409e5e5d6215b6ccd41a5a1a0ea6ce9665e01253f737a0d3", - "sha256:b1d53835922cd0f9b74b2742453a444865a70abae38d12eb41c59271da66f38d", - "sha256:b2df3ede85d778c949d9bd2a50237072cee3df0a423c91f5514f78f8035bde87", - "sha256:b415b82e5be7389ec5ee7ee35431e4a549ea327caacf73b697c6b3538cb5c87f", - "sha256:b7ba3c304a4a5d8112dbd30df8b3e4ef59b4b07807957d3c410d9713abaee9a8", - "sha256:bcc6f7a3a95119c3568c572ca167ada75f8319890706283b9ba59b3489c9bcb3", - "sha256:be392d9cd5309509175a9d7660dc17bf57084501108dbff0c5a8bfc3646048c3", - "sha256:bea61de0c688198e3d9479344228c7accaa22a78b58ec408e41750ebafee6c08", - "sha256:bedb3d01ad35ea1745bdb1d57f3ee0f996f988c98f5bbae9d068c3bb3065d210", - "sha256:c36906a7855ec33a9083608e6cd595e4729dab18aeb9aad0dd0b039240266239", - "sha256:c4fdf837666f7793a5c3cfa2f2f39f03eb6c7e92e831bc64486c2f547580c2b3", - "sha256:cfad3a770839aa456ff9a9aa0e253d98b628d005a3ccb37da1ff9be7c84fee16", - "sha256:d128e278e5e554c5c022c7bed410ca851e00bacebbb4460de546a73bc53f8de4", - "sha256:dffd9114ade73137ab2b79a8faf864683dbd2dbbb6b23a305fbbd4cbaeeb2187", - "sha256:e2acf5c66fbb62b5fe4c40978ddebafa50818f00bf79d60569d9762f6356336e", - "sha256:e65580ae3137bce712f505ec7c2d700aef0014a3878c4767b74aff5895fc454f", - "sha256:e944268445b5694f5d41292c9228f0ca46d5a32a67f195d5f8547c1f1d91f4bc", - "sha256:ed26c3d2d62c6588e0dad175b8d8cc0942a638f32d07b80f92043e5d73b7db67", - "sha256:ed625205f5f26984382b68e4cbcbc08e6603c9e84c14b38457170b0cc71c823b", - "sha256:f2a5d9f612091812dee18375a45d046526452142e7b78c4e21ab192db15453d5", - "sha256:f86aef546add4ff1202e1f31e9bb54f9268f17d996b2428877283146bf9bc013", - "sha256:f89d26e50a4c7453cb8c415acd09e72fbade2610606a9c500a1e48c43210a42d", - "sha256:fb7107faf0168de087f62a2f2ed00f9e9da12e0b801582b516ddac236b871cda" - ], - "markers": "python_version >= '3.6'", - "version": "==2022.4.24" - }, "setuptools": { "hashes": [ "sha256:26ead7d1f93efc0f8c804d9fafafbe4a44b179580a7105754b245155f9af05a8", @@ -931,6 +873,14 @@ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, + "tomli": { + "hashes": [ + "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" + ], + "markers": "python_version < '3.11'", + "version": "==2.0.1" + }, "wrapt": { "hashes": [ "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" From fe074f1d86f206e6ad7f457cc79a4d9ae099ee12 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 22:54:43 +0800 Subject: [PATCH 081/225] bump range of dependencies, resolve #3126 --- CHANGELOG.md | 5 + Pipfile | 10 +- Pipfile.lock | 391 ++++++++++++++++++++++----------------------------- 3 files changed, 177 insertions(+), 229 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55a23a8db3..e97b127b95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,11 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Improve regex parsing of channel topics. ([GH #3114](https://github.com/kyb3r/modmail/issues/3114), [PR #3111](https://github.com/kyb3r/modmail/pull/3111)) - Add warning if deploying on a developmental version. - Extensions are now loaded `on_connect`. +- MongoDB v5.0 clients are now supported. ([GH #3126](https://github.com/kyb3r/modmail/issues/3126)) +- Bump python-dotenv to v0.20.0, support for python 3.10 +- Bump emoji to v1.7.0 +- Bump aiohttp to v3.8.1 +- Bump lottie to v0.6.11 # v3.10.3 diff --git a/Pipfile b/Pipfile index 268523dd92..99d50e47e4 100644 --- a/Pipfile +++ b/Pipfile @@ -9,19 +9,19 @@ black = "==22.3.0" pylint = "~=2.9.3" [packages] -aiohttp = "==3.7.4.post0" +aiohttp = "==3.8.1" colorama = "~=0.4.4" # Doesn't officially support Python 3.9 yet, v0.4.5 will support 3.9 "discord.py" = {ref = "a14b43f2fda863ed6555374eb872bf014bdd1adf", git = "https://github.com/Rapptz/discord.py.git"} -emoji = "~=1.2.0" +emoji = "==1.7.0" isodate = "~=0.6.0" -motor = "~=2.4.0" +motor = "==2.5.1" natural = "~=0.2.0" parsedatetime = "~=2.6" pymongo = {extras = ["srv"], version = "*"} # Required by motor python-dateutil = "~=2.8.1" -python-dotenv = "~=0.18.0" +python-dotenv = "==0.20.0" uvloop = {version = ">=0.15.2", markers = "sys_platform != 'win32'"} -lottie = {version = "==0.6.10", extras = ["pdf"]} +lottie = "==0.6.11" [scripts] bot = "python bot.py" diff --git a/Pipfile.lock b/Pipfile.lock index f60ea59424..3ce9602d5e 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "d7f737bdd78a969ba477bc9d9b334a1429a70cb78fec53d8b95c5732bbb6a3bd" + "sha256": "dea4d7675ab1e4a2c4d3f4f8ddcff27db7c0b3851a37e598b10dc429c2eaa5df" }, "pipfile-spec": 6, "requires": {}, @@ -16,54 +16,97 @@ "default": { "aiohttp": { "hashes": [ - "sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe", - "sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe", - "sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5", - "sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8", - "sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd", - "sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb", - "sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c", - "sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87", - "sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0", - "sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290", - "sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5", - "sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287", - "sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde", - "sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf", - "sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8", - "sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16", - "sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf", - "sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809", - "sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213", - "sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f", - "sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013", - "sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b", - "sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9", - "sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5", - "sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb", - "sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df", - "sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4", - "sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439", - "sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f", - "sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22", - "sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f", - "sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5", - "sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970", - "sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009", - "sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc", - "sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a", - "sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95" + "sha256:01d7bdb774a9acc838e6b8f1d114f45303841b89b95984cbb7d80ea41172a9e3", + "sha256:03a6d5349c9ee8f79ab3ff3694d6ce1cfc3ced1c9d36200cb8f08ba06bd3b782", + "sha256:04d48b8ce6ab3cf2097b1855e1505181bdd05586ca275f2505514a6e274e8e75", + "sha256:0770e2806a30e744b4e21c9d73b7bee18a1cfa3c47991ee2e5a65b887c49d5cf", + "sha256:07b05cd3305e8a73112103c834e91cd27ce5b4bd07850c4b4dbd1877d3f45be7", + "sha256:086f92daf51a032d062ec5f58af5ca6a44d082c35299c96376a41cbb33034675", + "sha256:099ebd2c37ac74cce10a3527d2b49af80243e2a4fa39e7bce41617fbc35fa3c1", + "sha256:0c7ebbbde809ff4e970824b2b6cb7e4222be6b95a296e46c03cf050878fc1785", + "sha256:102e487eeb82afac440581e5d7f8f44560b36cf0bdd11abc51a46c1cd88914d4", + "sha256:11691cf4dc5b94236ccc609b70fec991234e7ef8d4c02dd0c9668d1e486f5abf", + "sha256:11a67c0d562e07067c4e86bffc1553f2cf5b664d6111c894671b2b8712f3aba5", + "sha256:12de6add4038df8f72fac606dff775791a60f113a725c960f2bab01d8b8e6b15", + "sha256:13487abd2f761d4be7c8ff9080de2671e53fff69711d46de703c310c4c9317ca", + "sha256:15b09b06dae900777833fe7fc4b4aa426556ce95847a3e8d7548e2d19e34edb8", + "sha256:1c182cb873bc91b411e184dab7a2b664d4fea2743df0e4d57402f7f3fa644bac", + "sha256:1ed0b6477896559f17b9eaeb6d38e07f7f9ffe40b9f0f9627ae8b9926ae260a8", + "sha256:28d490af82bc6b7ce53ff31337a18a10498303fe66f701ab65ef27e143c3b0ef", + "sha256:2e5d962cf7e1d426aa0e528a7e198658cdc8aa4fe87f781d039ad75dcd52c516", + "sha256:2ed076098b171573161eb146afcb9129b5ff63308960aeca4b676d9d3c35e700", + "sha256:2f2f69dca064926e79997f45b2f34e202b320fd3782f17a91941f7eb85502ee2", + "sha256:31560d268ff62143e92423ef183680b9829b1b482c011713ae941997921eebc8", + "sha256:31d1e1c0dbf19ebccbfd62eff461518dcb1e307b195e93bba60c965a4dcf1ba0", + "sha256:37951ad2f4a6df6506750a23f7cbabad24c73c65f23f72e95897bb2cecbae676", + "sha256:3af642b43ce56c24d063325dd2cf20ee012d2b9ba4c3c008755a301aaea720ad", + "sha256:44db35a9e15d6fe5c40d74952e803b1d96e964f683b5a78c3cc64eb177878155", + "sha256:473d93d4450880fe278696549f2e7aed8cd23708c3c1997981464475f32137db", + "sha256:477c3ea0ba410b2b56b7efb072c36fa91b1e6fc331761798fa3f28bb224830dd", + "sha256:4a4a4e30bf1edcad13fb0804300557aedd07a92cabc74382fdd0ba6ca2661091", + "sha256:4aed991a28ea3ce320dc8ce655875e1e00a11bdd29fe9444dd4f88c30d558602", + "sha256:51467000f3647d519272392f484126aa716f747859794ac9924a7aafa86cd411", + "sha256:55c3d1072704d27401c92339144d199d9de7b52627f724a949fc7d5fc56d8b93", + "sha256:589c72667a5febd36f1315aa6e5f56dd4aa4862df295cb51c769d16142ddd7cd", + "sha256:5bfde62d1d2641a1f5173b8c8c2d96ceb4854f54a44c23102e2ccc7e02f003ec", + "sha256:5c23b1ad869653bc818e972b7a3a79852d0e494e9ab7e1a701a3decc49c20d51", + "sha256:61bfc23df345d8c9716d03717c2ed5e27374e0fe6f659ea64edcd27b4b044cf7", + "sha256:6ae828d3a003f03ae31915c31fa684b9890ea44c9c989056fea96e3d12a9fa17", + "sha256:6c7cefb4b0640703eb1069835c02486669312bf2f12b48a748e0a7756d0de33d", + "sha256:6d69f36d445c45cda7b3b26afef2fc34ef5ac0cdc75584a87ef307ee3c8c6d00", + "sha256:6f0d5f33feb5f69ddd57a4a4bd3d56c719a141080b445cbf18f238973c5c9923", + "sha256:6f8b01295e26c68b3a1b90efb7a89029110d3a4139270b24fda961893216c440", + "sha256:713ac174a629d39b7c6a3aa757b337599798da4c1157114a314e4e391cd28e32", + "sha256:718626a174e7e467f0558954f94af117b7d4695d48eb980146016afa4b580b2e", + "sha256:7187a76598bdb895af0adbd2fb7474d7f6025d170bc0a1130242da817ce9e7d1", + "sha256:71927042ed6365a09a98a6377501af5c9f0a4d38083652bcd2281a06a5976724", + "sha256:7d08744e9bae2ca9c382581f7dce1273fe3c9bae94ff572c3626e8da5b193c6a", + "sha256:7dadf3c307b31e0e61689cbf9e06be7a867c563d5a63ce9dca578f956609abf8", + "sha256:81e3d8c34c623ca4e36c46524a3530e99c0bc95ed068fd6e9b55cb721d408fb2", + "sha256:844a9b460871ee0a0b0b68a64890dae9c415e513db0f4a7e3cab41a0f2fedf33", + "sha256:8b7ef7cbd4fec9a1e811a5de813311ed4f7ac7d93e0fda233c9b3e1428f7dd7b", + "sha256:97ef77eb6b044134c0b3a96e16abcb05ecce892965a2124c566af0fd60f717e2", + "sha256:99b5eeae8e019e7aad8af8bb314fb908dd2e028b3cdaad87ec05095394cce632", + "sha256:a25fa703a527158aaf10dafd956f7d42ac6d30ec80e9a70846253dd13e2f067b", + "sha256:a2f635ce61a89c5732537a7896b6319a8fcfa23ba09bec36e1b1ac0ab31270d2", + "sha256:a79004bb58748f31ae1cbe9fa891054baaa46fb106c2dc7af9f8e3304dc30316", + "sha256:a996d01ca39b8dfe77440f3cd600825d05841088fd6bc0144cc6c2ec14cc5f74", + "sha256:b0e20cddbd676ab8a64c774fefa0ad787cc506afd844de95da56060348021e96", + "sha256:b6613280ccedf24354406caf785db748bebbddcf31408b20c0b48cb86af76866", + "sha256:b9d00268fcb9f66fbcc7cd9fe423741d90c75ee029a1d15c09b22d23253c0a44", + "sha256:bb01ba6b0d3f6c68b89fce7305080145d4877ad3acaed424bae4d4ee75faa950", + "sha256:c2aef4703f1f2ddc6df17519885dbfa3514929149d3ff900b73f45998f2532fa", + "sha256:c34dc4958b232ef6188c4318cb7b2c2d80521c9a56c52449f8f93ab7bc2a8a1c", + "sha256:c3630c3ef435c0a7c549ba170a0633a56e92629aeed0e707fec832dee313fb7a", + "sha256:c3d6a4d0619e09dcd61021debf7059955c2004fa29f48788a3dfaf9c9901a7cd", + "sha256:d15367ce87c8e9e09b0f989bfd72dc641bcd04ba091c68cd305312d00962addd", + "sha256:d2f9b69293c33aaa53d923032fe227feac867f81682f002ce33ffae978f0a9a9", + "sha256:e999f2d0e12eea01caeecb17b653f3713d758f6dcc770417cf29ef08d3931421", + "sha256:ea302f34477fda3f85560a06d9ebdc7fa41e82420e892fc50b577e35fc6a50b2", + "sha256:eaba923151d9deea315be1f3e2b31cc39a6d1d2f682f942905951f4e40200922", + "sha256:ef9612483cb35171d51d9173647eed5d0069eaa2ee812793a75373447d487aa4", + "sha256:f5315a2eb0239185af1bddb1abf472d877fede3cc8d143c6cddad37678293237", + "sha256:fa0ffcace9b3aa34d205d8130f7873fcfefcb6a4dd3dd705b0dab69af6712642", + "sha256:fc5471e1a54de15ef71c1bc6ebe80d4dc681ea600e68bfd1cbce40427f0b7578" ], "index": "pypi", - "version": "==3.7.4.post0" + "version": "==3.8.1" + }, + "aiosignal": { + "hashes": [ + "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a", + "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2" + ], + "markers": "python_version >= '3.6'", + "version": "==1.2.0" }, "async-timeout": { "hashes": [ - "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f", - "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3" + "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15", + "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c" ], - "markers": "python_full_version >= '3.5.3'", - "version": "==3.0.1" + "markers": "python_version >= '3.6'", + "version": "==4.0.2" }, "attrs": { "hashes": [ @@ -73,83 +116,13 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==21.4.0" }, - "cairocffi": { + "charset-normalizer": { "hashes": [ - "sha256:108a3a7cb09e203bdd8501d9baad91d786d204561bd71e9364e8b34897c47b91" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.0" - }, - "cairosvg": { - "hashes": [ - "sha256:98c276b7e4f0caf01e5c7176765c104ffa1aa1461d63b2053b04ab663cf7052b", - "sha256:b0b9929cf5dba005178d746a8036fcf0025550f498ca54db61873322384783bc" + "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", + "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df" ], "markers": "python_version >= '3.5'", - "version": "==2.5.2" - }, - "cffi": { - "hashes": [ - "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3", - "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2", - "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636", - "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20", - "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728", - "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27", - "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66", - "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443", - "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0", - "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7", - "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39", - "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605", - "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a", - "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37", - "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029", - "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139", - "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc", - "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df", - "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14", - "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880", - "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2", - "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a", - "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e", - "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474", - "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024", - "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8", - "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0", - "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e", - "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a", - "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e", - "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032", - "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6", - "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e", - "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b", - "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e", - "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954", - "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962", - "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c", - "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4", - "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55", - "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962", - "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023", - "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c", - "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6", - "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8", - "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382", - "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7", - "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc", - "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997", - "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796" - ], - "version": "==1.15.0" - }, - "chardet": { - "hashes": [ - "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", - "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==4.0.0" + "version": "==2.0.12" }, "colorama": { "hashes": [ @@ -159,22 +132,6 @@ "index": "pypi", "version": "==0.4.4" }, - "cssselect2": { - "hashes": [ - "sha256:3a83b2a68370c69c9cd3fcb88bbfaebe9d22edeef2c22d1ff3e1ed9c7fa45ed8", - "sha256:5b5d6dea81a5eb0c9ca39f116c8578dd413778060c94c1f51196371618909325" - ], - "markers": "python_version >= '3.7'", - "version": "==0.6.0" - }, - "defusedxml": { - "hashes": [ - "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", - "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.7.1" - }, "discord-py": { "git": "https://github.com/Rapptz/discord.py.git", "ref": "a14b43f2fda863ed6555374eb872bf014bdd1adf" @@ -193,11 +150,75 @@ }, "emoji": { "hashes": [ - "sha256:496f432058567985838c13d67dde84ca081614a8286c0b9cdc7d63dfa89d51a3", - "sha256:6b19b65da8d6f30551eead1705539cc0eadcd9e33a6ecbc421a29b87f96287eb" + "sha256:65c54533ea3c78f30d0729288998715f418d7467de89ec258a31c0ce8660a1d1" ], "index": "pypi", - "version": "==1.2.0" + "version": "==1.7.0" + }, + "frozenlist": { + "hashes": [ + "sha256:006d3595e7d4108a12025ddf415ae0f6c9e736e726a5db0183326fd191b14c5e", + "sha256:01a73627448b1f2145bddb6e6c2259988bb8aee0fb361776ff8604b99616cd08", + "sha256:03a7dd1bfce30216a3f51a84e6dd0e4a573d23ca50f0346634916ff105ba6e6b", + "sha256:0437fe763fb5d4adad1756050cbf855bbb2bf0d9385c7bb13d7a10b0dd550486", + "sha256:04cb491c4b1c051734d41ea2552fde292f5f3a9c911363f74f39c23659c4af78", + "sha256:0c36e78b9509e97042ef869c0e1e6ef6429e55817c12d78245eb915e1cca7468", + "sha256:25af28b560e0c76fa41f550eacb389905633e7ac02d6eb3c09017fa1c8cdfde1", + "sha256:2fdc3cd845e5a1f71a0c3518528bfdbfe2efaf9886d6f49eacc5ee4fd9a10953", + "sha256:30530930410855c451bea83f7b272fb1c495ed9d5cc72895ac29e91279401db3", + "sha256:31977f84828b5bb856ca1eb07bf7e3a34f33a5cddce981d880240ba06639b94d", + "sha256:3c62964192a1c0c30b49f403495911298810bada64e4f03249ca35a33ca0417a", + "sha256:3f7c935c7b58b0d78c0beea0c7358e165f95f1fd8a7e98baa40d22a05b4a8141", + "sha256:40dff8962b8eba91fd3848d857203f0bd704b5f1fa2b3fc9af64901a190bba08", + "sha256:40ec383bc194accba825fbb7d0ef3dda5736ceab2375462f1d8672d9f6b68d07", + "sha256:436496321dad302b8b27ca955364a439ed1f0999311c393dccb243e451ff66aa", + "sha256:4406cfabef8f07b3b3af0f50f70938ec06d9f0fc26cbdeaab431cbc3ca3caeaa", + "sha256:45334234ec30fc4ea677f43171b18a27505bfb2dba9aca4398a62692c0ea8868", + "sha256:47be22dc27ed933d55ee55845d34a3e4e9f6fee93039e7f8ebadb0c2f60d403f", + "sha256:4a44ebbf601d7bac77976d429e9bdb5a4614f9f4027777f9e54fd765196e9d3b", + "sha256:4eda49bea3602812518765810af732229b4291d2695ed24a0a20e098c45a707b", + "sha256:57f4d3f03a18facacb2a6bcd21bccd011e3b75d463dc49f838fd699d074fabd1", + "sha256:603b9091bd70fae7be28bdb8aa5c9990f4241aa33abb673390a7f7329296695f", + "sha256:65bc6e2fece04e2145ab6e3c47428d1bbc05aede61ae365b2c1bddd94906e478", + "sha256:691ddf6dc50480ce49f68441f1d16a4c3325887453837036e0fb94736eae1e58", + "sha256:6983a31698490825171be44ffbafeaa930ddf590d3f051e397143a5045513b01", + "sha256:6a202458d1298ced3768f5a7d44301e7c86defac162ace0ab7434c2e961166e8", + "sha256:6eb275c6385dd72594758cbe96c07cdb9bd6becf84235f4a594bdf21e3596c9d", + "sha256:754728d65f1acc61e0f4df784456106e35afb7bf39cfe37227ab00436fb38676", + "sha256:768efd082074bb203c934e83a61654ed4931ef02412c2fbdecea0cff7ecd0274", + "sha256:772965f773757a6026dea111a15e6e2678fbd6216180f82a48a40b27de1ee2ab", + "sha256:871d42623ae15eb0b0e9df65baeee6976b2e161d0ba93155411d58ff27483ad8", + "sha256:88aafd445a233dbbf8a65a62bc3249a0acd0d81ab18f6feb461cc5a938610d24", + "sha256:8c905a5186d77111f02144fab5b849ab524f1e876a1e75205cd1386a9be4b00a", + "sha256:8cf829bd2e2956066dd4de43fd8ec881d87842a06708c035b37ef632930505a2", + "sha256:92e650bd09b5dda929523b9f8e7f99b24deac61240ecc1a32aeba487afcd970f", + "sha256:93641a51f89473837333b2f8100f3f89795295b858cd4c7d4a1f18e299dc0a4f", + "sha256:94c7a8a9fc9383b52c410a2ec952521906d355d18fccc927fca52ab575ee8b93", + "sha256:9f892d6a94ec5c7b785e548e42722e6f3a52f5f32a8461e82ac3e67a3bd073f1", + "sha256:acb267b09a509c1df5a4ca04140da96016f40d2ed183cdc356d237286c971b51", + "sha256:adac9700675cf99e3615eb6a0eb5e9f5a4143c7d42c05cea2e7f71c27a3d0846", + "sha256:aff388be97ef2677ae185e72dc500d19ecaf31b698986800d3fc4f399a5e30a5", + "sha256:b5009062d78a8c6890d50b4e53b0ddda31841b3935c1937e2ed8c1bda1c7fb9d", + "sha256:b684c68077b84522b5c7eafc1dc735bfa5b341fb011d5552ebe0968e22ed641c", + "sha256:b9e3e9e365991f8cc5f5edc1fd65b58b41d0514a6a7ad95ef5c7f34eb49b3d3e", + "sha256:bd89acd1b8bb4f31b47072615d72e7f53a948d302b7c1d1455e42622de180eae", + "sha256:bde99812f237f79eaf3f04ebffd74f6718bbd216101b35ac7955c2d47c17da02", + "sha256:c6c321dd013e8fc20735b92cb4892c115f5cdb82c817b1e5b07f6b95d952b2f0", + "sha256:ce6f2ba0edb7b0c1d8976565298ad2deba6f8064d2bebb6ffce2ca896eb35b0b", + "sha256:d2257aaba9660f78c7b1d8fea963b68f3feffb1a9d5d05a18401ca9eb3e8d0a3", + "sha256:d26b650b71fdc88065b7a21f8ace70175bcf3b5bdba5ea22df4bfd893e795a3b", + "sha256:d6d32ff213aef0fd0bcf803bffe15cfa2d4fde237d1d4838e62aec242a8362fa", + "sha256:e1e26ac0a253a2907d654a37e390904426d5ae5483150ce3adedb35c8c06614a", + "sha256:e30b2f9683812eb30cf3f0a8e9f79f8d590a7999f731cf39f9105a7c4a39489d", + "sha256:e84cb61b0ac40a0c3e0e8b79c575161c5300d1d89e13c0e02f76193982f066ed", + "sha256:e982878792c971cbd60ee510c4ee5bf089a8246226dea1f2138aa0bb67aff148", + "sha256:f20baa05eaa2bcd5404c445ec51aed1c268d62600362dc6cfe04fae34a424bd9", + "sha256:f7353ba3367473d1d616ee727945f439e027f0bb16ac1a750219a8344d1d5d3c", + "sha256:f96293d6f982c58ebebb428c50163d010c2f05de0cde99fd681bfdc18d4b2dc2", + "sha256:ff9310f05b9d9c5c4dd472983dc956901ee6cb2c3ec1ab116ecdde25f3ce4951" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0" }, "idna": { "hashes": [ @@ -216,22 +237,20 @@ "version": "==0.6.1" }, "lottie": { - "extras": [ - "pdf" - ], + "extras": [], "hashes": [ - "sha256:d3281d09a8db94da49f60267123b9e0473e3a51c282da2d5e61908d33843f1cc" + "sha256:d53e96265887aa9187c7c707fd612b3d52f38da64c81ea82297783efb47f7e3f" ], "index": "pypi", - "version": "==0.6.10" + "version": "==0.6.11" }, "motor": { "hashes": [ - "sha256:1196db507142ef8f00d953efa2f37b39335ef2d72af6ce4fbccfd870b65c5e9f", - "sha256:839c11a43897dbec8e5ba0e87a9c9b877239803126877b2efa5cef89aa6b687a" + "sha256:663473f4498f955d35db7b6f25651cb165514c247136f368b84419cb7635f6b8", + "sha256:961fdceacaae2c7236c939166f66415be81be8bbb762da528386738de3a0f509" ], "index": "pypi", - "version": "==2.4.0" + "version": "==2.5.1" }, "multidict": { "hashes": [ @@ -313,61 +332,8 @@ "index": "pypi", "version": "==2.6" }, - "pillow": { - "hashes": [ - "sha256:01ce45deec9df310cbbee11104bae1a2a43308dd9c317f99235b6d3080ddd66e", - "sha256:0c51cb9edac8a5abd069fd0758ac0a8bfe52c261ee0e330f363548aca6893595", - "sha256:17869489de2fce6c36690a0c721bd3db176194af5f39249c1ac56d0bb0fcc512", - "sha256:21dee8466b42912335151d24c1665fcf44dc2ee47e021d233a40c3ca5adae59c", - "sha256:25023a6209a4d7c42154073144608c9a71d3512b648a2f5d4465182cb93d3477", - "sha256:255c9d69754a4c90b0ee484967fc8818c7ff8311c6dddcc43a4340e10cd1636a", - "sha256:35be4a9f65441d9982240e6966c1eaa1c654c4e5e931eaf580130409e31804d4", - "sha256:3f42364485bfdab19c1373b5cd62f7c5ab7cc052e19644862ec8f15bb8af289e", - "sha256:3fddcdb619ba04491e8f771636583a7cc5a5051cd193ff1aa1ee8616d2a692c5", - "sha256:463acf531f5d0925ca55904fa668bb3461c3ef6bc779e1d6d8a488092bdee378", - "sha256:4fe29a070de394e449fd88ebe1624d1e2d7ddeed4c12e0b31624561b58948d9a", - "sha256:55dd1cf09a1fd7c7b78425967aacae9b0d70125f7d3ab973fadc7b5abc3de652", - "sha256:5a3ecc026ea0e14d0ad7cd990ea7f48bfcb3eb4271034657dc9d06933c6629a7", - "sha256:5cfca31ab4c13552a0f354c87fbd7f162a4fafd25e6b521bba93a57fe6a3700a", - "sha256:66822d01e82506a19407d1afc104c3fcea3b81d5eb11485e593ad6b8492f995a", - "sha256:69e5ddc609230d4408277af135c5b5c8fe7a54b2bdb8ad7c5100b86b3aab04c6", - "sha256:6b6d4050b208c8ff886fd3db6690bf04f9a48749d78b41b7a5bf24c236ab0165", - "sha256:7a053bd4d65a3294b153bdd7724dce864a1d548416a5ef61f6d03bf149205160", - "sha256:82283af99c1c3a5ba1da44c67296d5aad19f11c535b551a5ae55328a317ce331", - "sha256:8782189c796eff29dbb37dd87afa4ad4d40fc90b2742704f94812851b725964b", - "sha256:8d79c6f468215d1a8415aa53d9868a6b40c4682165b8cb62a221b1baa47db458", - "sha256:97bda660702a856c2c9e12ec26fc6d187631ddfd896ff685814ab21ef0597033", - "sha256:a325ac71914c5c043fa50441b36606e64a10cd262de12f7a179620f579752ff8", - "sha256:a336a4f74baf67e26f3acc4d61c913e378e931817cd1e2ef4dfb79d3e051b481", - "sha256:a598d8830f6ef5501002ae85c7dbfcd9c27cc4efc02a1989369303ba85573e58", - "sha256:a5eaf3b42df2bcda61c53a742ee2c6e63f777d0e085bbc6b2ab7ed57deb13db7", - "sha256:aea7ce61328e15943d7b9eaca87e81f7c62ff90f669116f857262e9da4057ba3", - "sha256:af79d3fde1fc2e33561166d62e3b63f0cc3e47b5a3a2e5fea40d4917754734ea", - "sha256:c24f718f9dd73bb2b31a6201e6db5ea4a61fdd1d1c200f43ee585fc6dcd21b34", - "sha256:c5b0ff59785d93b3437c3703e3c64c178aabada51dea2a7f2c5eccf1bcf565a3", - "sha256:c7110ec1701b0bf8df569a7592a196c9d07c764a0a74f65471ea56816f10e2c8", - "sha256:c870193cce4b76713a2b29be5d8327c8ccbe0d4a49bc22968aa1e680930f5581", - "sha256:c9efef876c21788366ea1f50ecb39d5d6f65febe25ad1d4c0b8dff98843ac244", - "sha256:de344bcf6e2463bb25179d74d6e7989e375f906bcec8cb86edb8b12acbc7dfef", - "sha256:eb1b89b11256b5b6cad5e7593f9061ac4624f7651f7a8eb4dfa37caa1dfaa4d0", - "sha256:ed742214068efa95e9844c2d9129e209ed63f61baa4d54dbf4cf8b5e2d30ccf2", - "sha256:f401ed2bbb155e1ade150ccc63db1a4f6c1909d3d378f7d1235a44e90d75fb97", - "sha256:fb89397013cf302f282f0fc998bb7abf11d49dcff72c8ecb320f76ea6e2c5717" - ], - "markers": "python_version >= '3.7'", - "version": "==9.1.0" - }, - "pycparser": { - "hashes": [ - "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", - "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" - ], - "version": "==2.21" - }, "pymongo": { - "extras": [ - "srv" - ], + "extras": [], "hashes": [ "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", @@ -490,11 +456,11 @@ }, "python-dotenv": { "hashes": [ - "sha256:dd8fe852847f4fbfadabf6183ddd4c824a9651f02d51714fa075c95561959c7d", - "sha256:effaac3c1e58d89b3ccb4d04a40dc7ad6e0275fda25fd75ae9d323e2465e202d" + "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f", + "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938" ], "index": "pypi", - "version": "==0.18.0" + "version": "==0.20.0" }, "six": { "hashes": [ @@ -504,22 +470,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, - "tinycss2": { - "hashes": [ - "sha256:b2e44dd8883c360c35dd0d1b5aad0b610e5156c2cb3b33434634e539ead9d8bf", - "sha256:fe794ceaadfe3cf3e686b22155d0da5780dd0e273471a51846d0a02bc204fec8" - ], - "markers": "python_version >= '3.6'", - "version": "==1.1.1" - }, - "typing-extensions": { - "hashes": [ - "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", - "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376" - ], - "markers": "python_version >= '3.7'", - "version": "==4.2.0" - }, "uvloop": { "hashes": [ "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450", @@ -542,13 +492,6 @@ "markers": "sys_platform != 'win32'", "version": "==0.16.0" }, - "webencodings": { - "hashes": [ - "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", - "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" - ], - "version": "==0.5.1" - }, "yarl": { "hashes": [ "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac", From ab8662b9b5625f2fbc1792252dc7c2851deb6ae3 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 23:02:29 +0800 Subject: [PATCH 082/225] complete deps --- Pipfile | 1 + Pipfile.lock | 15 ++++++++++++--- requirements.txt | 28 ++++++++++------------------ 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Pipfile b/Pipfile index 99d50e47e4..15e7bec22a 100644 --- a/Pipfile +++ b/Pipfile @@ -22,6 +22,7 @@ python-dateutil = "~=2.8.1" python-dotenv = "==0.20.0" uvloop = {version = ">=0.15.2", markers = "sys_platform != 'win32'"} lottie = "==0.6.11" +typing-extensions = "==4.2.0" [scripts] bot = "python bot.py" diff --git a/Pipfile.lock b/Pipfile.lock index 3ce9602d5e..5b55df924e 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "dea4d7675ab1e4a2c4d3f4f8ddcff27db7c0b3851a37e598b10dc429c2eaa5df" + "sha256": "8fca2257520573284e4ecaa536309d9e21bee280144e019b7ed97eae0160deee" }, "pipfile-spec": 6, "requires": {}, @@ -237,7 +237,6 @@ "version": "==0.6.1" }, "lottie": { - "extras": [], "hashes": [ "sha256:d53e96265887aa9187c7c707fd612b3d52f38da64c81ea82297783efb47f7e3f" ], @@ -333,7 +332,9 @@ "version": "==2.6" }, "pymongo": { - "extras": [], + "extras": [ + "srv" + ], "hashes": [ "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", @@ -470,6 +471,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, + "typing-extensions": { + "hashes": [ + "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", + "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376" + ], + "index": "pypi", + "version": "==4.2.0" + }, "uvloop": { "hashes": [ "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450", diff --git a/requirements.txt b/requirements.txt index ecff8c80c8..f17ff47f04 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,35 +6,27 @@ # -i https://pypi.org/simple - -aiohttp==3.7.4.post0 -async-timeout==3.0.1; python_full_version >= '3.5.3' +aiohttp==3.8.1 +aiosignal==1.2.0; python_version >= '3.6' +async-timeout==4.0.2; python_version >= '3.6' attrs==21.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -cairocffi==1.3.0; python_version >= '3.7' -cairosvg==2.5.2; python_version >= '3.5' -cffi==1.15.0 -chardet==4.0.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +charset-normalizer==2.0.12; python_version >= '3.5' colorama==0.4.4 -cssselect2==0.6.0; python_version >= '3.7' -defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' dnspython==2.2.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -emoji==1.2.0 +emoji==1.7.0 +frozenlist==1.3.0; python_version >= '3.7' git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord.py idna==3.3; python_version >= '3.5' isodate==0.6.1 -lottie[pdf]==0.6.10 -motor==2.4.0 +lottie==0.6.11 +motor==2.5.1 multidict==6.0.2; python_version >= '3.7' natural==0.2.0 parsedatetime==2.6 -pillow==9.1.0; python_version >= '3.7' -pycparser==2.21 pymongo[srv]==3.12.3 python-dateutil==2.8.2 -python-dotenv==0.18.0 +python-dotenv==0.20.0 six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -tinycss2==1.1.1; python_version >= '3.6' -typing-extensions==4.2.0; python_version >= '3.7' +typing-extensions==4.2.0 uvloop==0.16.0; sys_platform != 'win32' -webencodings==0.5.1 yarl==1.7.2; python_version >= '3.6' From 99a6a5ed917ccc11d6cd3e04db2c5c3f55e42925 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 23:06:37 +0800 Subject: [PATCH 083/225] Fix lottie req & bump ver --- Pipfile | 2 +- Pipfile.lock | 160 +++++++++++++++++++++++++++++++++++++++++++++-- bot.py | 2 +- pyproject.toml | 2 +- requirements.txt | 16 ++++- 5 files changed, 172 insertions(+), 10 deletions(-) diff --git a/Pipfile b/Pipfile index 15e7bec22a..6d1693e1a4 100644 --- a/Pipfile +++ b/Pipfile @@ -21,7 +21,7 @@ pymongo = {extras = ["srv"], version = "*"} # Required by motor python-dateutil = "~=2.8.1" python-dotenv = "==0.20.0" uvloop = {version = ">=0.15.2", markers = "sys_platform != 'win32'"} -lottie = "==0.6.11" +lottie = {version = "==0.6.11", extras = ["pdf"]} typing-extensions = "==4.2.0" [scripts] diff --git a/Pipfile.lock b/Pipfile.lock index 5b55df924e..c0ceed0b44 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "8fca2257520573284e4ecaa536309d9e21bee280144e019b7ed97eae0160deee" + "sha256": "2d6a4df6161cc1c6fb1c60ceb7bc39d5c4d5a7371564b1b8c2a517c22685d56c" }, "pipfile-spec": 6, "requires": {}, @@ -116,6 +116,75 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==21.4.0" }, + "cairocffi": { + "hashes": [ + "sha256:108a3a7cb09e203bdd8501d9baad91d786d204561bd71e9364e8b34897c47b91" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0" + }, + "cairosvg": { + "hashes": [ + "sha256:98c276b7e4f0caf01e5c7176765c104ffa1aa1461d63b2053b04ab663cf7052b", + "sha256:b0b9929cf5dba005178d746a8036fcf0025550f498ca54db61873322384783bc" + ], + "version": "==2.5.2" + }, + "cffi": { + "hashes": [ + "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3", + "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2", + "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636", + "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20", + "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728", + "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27", + "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66", + "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443", + "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0", + "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7", + "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39", + "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605", + "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a", + "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37", + "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029", + "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139", + "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc", + "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df", + "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14", + "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880", + "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2", + "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a", + "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e", + "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474", + "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024", + "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8", + "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0", + "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e", + "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a", + "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e", + "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032", + "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6", + "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e", + "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b", + "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e", + "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954", + "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962", + "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c", + "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4", + "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55", + "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962", + "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023", + "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c", + "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6", + "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8", + "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382", + "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7", + "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc", + "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997", + "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796" + ], + "version": "==1.15.0" + }, "charset-normalizer": { "hashes": [ "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", @@ -132,6 +201,22 @@ "index": "pypi", "version": "==0.4.4" }, + "cssselect2": { + "hashes": [ + "sha256:3a83b2a68370c69c9cd3fcb88bbfaebe9d22edeef2c22d1ff3e1ed9c7fa45ed8", + "sha256:5b5d6dea81a5eb0c9ca39f116c8578dd413778060c94c1f51196371618909325" + ], + "markers": "python_version >= '3.7'", + "version": "==0.6.0" + }, + "defusedxml": { + "hashes": [ + "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", + "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.7.1" + }, "discord-py": { "git": "https://github.com/Rapptz/discord.py.git", "ref": "a14b43f2fda863ed6555374eb872bf014bdd1adf" @@ -237,6 +322,9 @@ "version": "==0.6.1" }, "lottie": { + "extras": [ + "pdf" + ], "hashes": [ "sha256:d53e96265887aa9187c7c707fd612b3d52f38da64c81ea82297783efb47f7e3f" ], @@ -331,10 +419,59 @@ "index": "pypi", "version": "==2.6" }, - "pymongo": { - "extras": [ - "srv" + "pillow": { + "hashes": [ + "sha256:01ce45deec9df310cbbee11104bae1a2a43308dd9c317f99235b6d3080ddd66e", + "sha256:0c51cb9edac8a5abd069fd0758ac0a8bfe52c261ee0e330f363548aca6893595", + "sha256:17869489de2fce6c36690a0c721bd3db176194af5f39249c1ac56d0bb0fcc512", + "sha256:21dee8466b42912335151d24c1665fcf44dc2ee47e021d233a40c3ca5adae59c", + "sha256:25023a6209a4d7c42154073144608c9a71d3512b648a2f5d4465182cb93d3477", + "sha256:255c9d69754a4c90b0ee484967fc8818c7ff8311c6dddcc43a4340e10cd1636a", + "sha256:35be4a9f65441d9982240e6966c1eaa1c654c4e5e931eaf580130409e31804d4", + "sha256:3f42364485bfdab19c1373b5cd62f7c5ab7cc052e19644862ec8f15bb8af289e", + "sha256:3fddcdb619ba04491e8f771636583a7cc5a5051cd193ff1aa1ee8616d2a692c5", + "sha256:463acf531f5d0925ca55904fa668bb3461c3ef6bc779e1d6d8a488092bdee378", + "sha256:4fe29a070de394e449fd88ebe1624d1e2d7ddeed4c12e0b31624561b58948d9a", + "sha256:55dd1cf09a1fd7c7b78425967aacae9b0d70125f7d3ab973fadc7b5abc3de652", + "sha256:5a3ecc026ea0e14d0ad7cd990ea7f48bfcb3eb4271034657dc9d06933c6629a7", + "sha256:5cfca31ab4c13552a0f354c87fbd7f162a4fafd25e6b521bba93a57fe6a3700a", + "sha256:66822d01e82506a19407d1afc104c3fcea3b81d5eb11485e593ad6b8492f995a", + "sha256:69e5ddc609230d4408277af135c5b5c8fe7a54b2bdb8ad7c5100b86b3aab04c6", + "sha256:6b6d4050b208c8ff886fd3db6690bf04f9a48749d78b41b7a5bf24c236ab0165", + "sha256:7a053bd4d65a3294b153bdd7724dce864a1d548416a5ef61f6d03bf149205160", + "sha256:82283af99c1c3a5ba1da44c67296d5aad19f11c535b551a5ae55328a317ce331", + "sha256:8782189c796eff29dbb37dd87afa4ad4d40fc90b2742704f94812851b725964b", + "sha256:8d79c6f468215d1a8415aa53d9868a6b40c4682165b8cb62a221b1baa47db458", + "sha256:97bda660702a856c2c9e12ec26fc6d187631ddfd896ff685814ab21ef0597033", + "sha256:a325ac71914c5c043fa50441b36606e64a10cd262de12f7a179620f579752ff8", + "sha256:a336a4f74baf67e26f3acc4d61c913e378e931817cd1e2ef4dfb79d3e051b481", + "sha256:a598d8830f6ef5501002ae85c7dbfcd9c27cc4efc02a1989369303ba85573e58", + "sha256:a5eaf3b42df2bcda61c53a742ee2c6e63f777d0e085bbc6b2ab7ed57deb13db7", + "sha256:aea7ce61328e15943d7b9eaca87e81f7c62ff90f669116f857262e9da4057ba3", + "sha256:af79d3fde1fc2e33561166d62e3b63f0cc3e47b5a3a2e5fea40d4917754734ea", + "sha256:c24f718f9dd73bb2b31a6201e6db5ea4a61fdd1d1c200f43ee585fc6dcd21b34", + "sha256:c5b0ff59785d93b3437c3703e3c64c178aabada51dea2a7f2c5eccf1bcf565a3", + "sha256:c7110ec1701b0bf8df569a7592a196c9d07c764a0a74f65471ea56816f10e2c8", + "sha256:c870193cce4b76713a2b29be5d8327c8ccbe0d4a49bc22968aa1e680930f5581", + "sha256:c9efef876c21788366ea1f50ecb39d5d6f65febe25ad1d4c0b8dff98843ac244", + "sha256:de344bcf6e2463bb25179d74d6e7989e375f906bcec8cb86edb8b12acbc7dfef", + "sha256:eb1b89b11256b5b6cad5e7593f9061ac4624f7651f7a8eb4dfa37caa1dfaa4d0", + "sha256:ed742214068efa95e9844c2d9129e209ed63f61baa4d54dbf4cf8b5e2d30ccf2", + "sha256:f401ed2bbb155e1ade150ccc63db1a4f6c1909d3d378f7d1235a44e90d75fb97", + "sha256:fb89397013cf302f282f0fc998bb7abf11d49dcff72c8ecb320f76ea6e2c5717" ], + "markers": "python_version >= '3.7'", + "version": "==9.1.0" + }, + "pycparser": { + "hashes": [ + "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", + "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" + ], + "version": "==2.21" + }, + "pymongo": { + "extras": [], "hashes": [ "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", @@ -471,6 +608,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, + "tinycss2": { + "hashes": [ + "sha256:b2e44dd8883c360c35dd0d1b5aad0b610e5156c2cb3b33434634e539ead9d8bf", + "sha256:fe794ceaadfe3cf3e686b22155d0da5780dd0e273471a51846d0a02bc204fec8" + ], + "markers": "python_version >= '3.6'", + "version": "==1.1.1" + }, "typing-extensions": { "hashes": [ "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", @@ -501,6 +646,13 @@ "markers": "sys_platform != 'win32'", "version": "==0.16.0" }, + "webencodings": { + "hashes": [ + "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", + "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" + ], + "version": "==0.5.1" + }, "yarl": { "hashes": [ "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac", diff --git a/bot.py b/bot.py index 4fb57f1886..55670607fe 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev10" +__version__ = "4.0.0-dev11" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 9d08c1d2b2..80217af8fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev10' +version = '4.0.0-dev11' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ diff --git a/requirements.txt b/requirements.txt index f17ff47f04..541a8411c2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,23 +10,33 @@ aiohttp==3.8.1 aiosignal==1.2.0; python_version >= '3.6' async-timeout==4.0.2; python_version >= '3.6' attrs==21.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -charset-normalizer==2.0.12; python_version >= '3.5' +cairocffi==1.3.0; python_version >= '3.7' +cairosvg==2.5.2 +cffi==1.15.0 +charset-normalizer==2.0.12; python_version >= '3.5' colorama==0.4.4 +cssselect2==0.6.0; python_version >= '3.7' +defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' dnspython==2.2.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' emoji==1.7.0 frozenlist==1.3.0; python_version >= '3.7' +git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord-py git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord.py idna==3.3; python_version >= '3.5' isodate==0.6.1 -lottie==0.6.11 +lottie[pdf]==0.6.11 motor==2.5.1 multidict==6.0.2; python_version >= '3.7' natural==0.2.0 parsedatetime==2.6 -pymongo[srv]==3.12.3 +pillow==9.1.0; python_version >= '3.7' +pycparser==2.21 +pymongo==3.12.3 python-dateutil==2.8.2 python-dotenv==0.20.0 six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +tinycss2==1.1.1; python_version >= '3.6' typing-extensions==4.2.0 uvloop==0.16.0; sys_platform != 'win32' +webencodings==0.5.1 yarl==1.7.2; python_version >= '3.6' From c6ed564db714c3296a74046ac98df2ef27bcc2c8 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 23:17:51 +0800 Subject: [PATCH 084/225] shift to devpkgs --- Pipfile | 2 +- Pipfile.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Pipfile b/Pipfile index 6d1693e1a4..e9b1e58f76 100644 --- a/Pipfile +++ b/Pipfile @@ -7,6 +7,7 @@ verify_ssl = true bandit = "~=1.7.0" black = "==22.3.0" pylint = "~=2.9.3" +typing-extensions = "==4.2.0" [packages] aiohttp = "==3.8.1" @@ -22,7 +23,6 @@ python-dateutil = "~=2.8.1" python-dotenv = "==0.20.0" uvloop = {version = ">=0.15.2", markers = "sys_platform != 'win32'"} lottie = {version = "==0.6.11", extras = ["pdf"]} -typing-extensions = "==4.2.0" [scripts] bot = "python bot.py" diff --git a/Pipfile.lock b/Pipfile.lock index c0ceed0b44..8dff48027a 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2d6a4df6161cc1c6fb1c60ceb7bc39d5c4d5a7371564b1b8c2a517c22685d56c" + "sha256": "b6bc030eedf7606f6ceeda324e896c29d5771108afa224c712d4c92d81875899" }, "pipfile-spec": 6, "requires": {}, @@ -616,14 +616,6 @@ "markers": "python_version >= '3.6'", "version": "==1.1.1" }, - "typing-extensions": { - "hashes": [ - "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", - "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376" - ], - "index": "pypi", - "version": "==4.2.0" - }, "uvloop": { "hashes": [ "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450", @@ -985,6 +977,14 @@ "markers": "python_version < '3.11'", "version": "==2.0.1" }, + "typing-extensions": { + "hashes": [ + "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", + "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376" + ], + "index": "pypi", + "version": "==4.2.0" + }, "wrapt": { "hashes": [ "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" From fff100dd11ee259f1897d2864e8ad03bac58ca97 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Thu, 28 Apr 2022 23:19:11 +0800 Subject: [PATCH 085/225] update reqs.txt --- requirements.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 541a8411c2..e7223057ad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,7 +20,6 @@ defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, dnspython==2.2.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' emoji==1.7.0 frozenlist==1.3.0; python_version >= '3.7' -git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord-py git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord.py idna==3.3; python_version >= '3.5' isodate==0.6.1 @@ -36,7 +35,6 @@ python-dateutil==2.8.2 python-dotenv==0.20.0 six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' tinycss2==1.1.1; python_version >= '3.6' -typing-extensions==4.2.0 uvloop==0.16.0; sys_platform != 'win32' webencodings==0.5.1 yarl==1.7.2; python_version >= '3.6' From 17b2f89e9ae402b27516c86562a7d67c0008ed7f Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 22:23:47 +0800 Subject: [PATCH 086/225] add use_random_channel_name, resolve #3143 --- CHANGELOG.md | 1 + bot.py | 9 +++++++-- core/config.py | 2 ++ core/config_help.json | 25 +++++++++++++++++++------ pyproject.toml | 2 +- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e97b127b95..fa5d0ad75a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `plain_snippets` config to force all snippets to be plain. ([GH #3083](https://github.com/kyb3r/modmail/issues/3083)) - `?fpareply` and `?fpreply` to reply to messages with variables plainly. - `use_nickname_channel_name` config to use nicknames instead of usernames for channel names. ([GH #3112](https://github.com/kyb3r/modmail/issues/3112)) +- `use_random_channel_name` config to use random nicknames vaguely tied to user ID. It is unable to be computed in reverse. ([GH #3143](https://github.com/kyb3r/modmail/issues/3143) - `show_log_url_button` config to show Log URL button. ([GH #3122](https://github.com/kyb3r/modmail/issues/3122)) - Select menus for certain paginators. - `Title` field in `?logs`. ([GH #3142](https://github.com/kyb3r/modmail/issues/3142)) diff --git a/bot.py b/bot.py index 55670607fe..bcd6acfee9 100644 --- a/bot.py +++ b/bot.py @@ -1,8 +1,9 @@ -__version__ = "4.0.0-dev11" +__version__ = "4.0.0-dev12" import asyncio import copy +import hashlib import logging import os import re @@ -1690,7 +1691,11 @@ def format_channel_name(self, author, exclude_channel=None, force_null=False): if force_null: name = new_name = "null" else: - if self.config["use_user_id_channel_name"]: + if self.config["use_random_channel_name"]: + to_hash = self.token.split(".")[-1] + str(author.id) + digest = hashlib.md5(to_hash.encode("utf8")) + name = new_name = digest.hexdigest()[-8:] + elif self.config["use_user_id_channel_name"]: name = new_name = str(author.id) elif self.config["use_timestamp_channel_name"]: name = new_name = author.created_at.isoformat(sep="-", timespec="minutes") diff --git a/core/config.py b/core/config.py index 14f86ecd2e..6cff7f0bd7 100644 --- a/core/config.py +++ b/core/config.py @@ -53,6 +53,7 @@ class ConfigManager: "use_user_id_channel_name": False, "use_timestamp_channel_name": False, "use_nickname_channel_name": False, + "use_random_channel_name": False, "recipient_thread_close": False, "thread_show_roles": True, "thread_show_account_age": True, @@ -187,6 +188,7 @@ class ConfigManager: "use_user_id_channel_name", "use_timestamp_channel_name", "use_nickname_channel_name", + "use_random_channel_name", "user_typing", "mod_typing", "reply_without_command", diff --git a/core/config_help.json b/core/config_help.json index 342652456d..e7ebb9590d 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -106,8 +106,8 @@ ], "notes": [ "This config is suitable for servers in Server Discovery to comply with channel name restrictions.", - "This cannot be applied with `use_timestamp_channel_name` or `use_nickname_channel_name`.", - "See also: `use_timestamp_channel_name`, `use_nickname_channel_name`." + "This cannot be applied with `use_timestamp_channel_name`, `use_random_channel_name` or `use_nickname_channel_name`.", + "See also: `use_timestamp_channel_name`, `use_nickname_channel_name`, `use_random_channel_name`." ] }, "use_timestamp_channel_name": { @@ -119,8 +119,8 @@ ], "notes": [ "This config is suitable for servers in Server Discovery to comply with channel name restrictions.", - "This cannot be applied with `use_user_id_channel_name` or `use_nickname_channel_name`.", - "See also: `use_user_id_channel_name`, `use_nickname_channel_name`." + "This cannot be applied with `use_user_id_channel_name`, `use_random_channel_name` or `use_nickname_channel_name`.", + "See also: `use_user_id_channel_name`, `use_nickname_channel_name`, `use_random_channel_name`." ] }, "use_nickname_channel_name": { @@ -132,8 +132,21 @@ ], "notes": [ "This config is suitable for servers in Server Discovery to comply with channel name restrictions.", - "This cannot be applied with `use_timestamp_channel_name` or `use_user_id_channel_name`.", - "See also: `use_timestamp_channel_name`, `use_user_id_channel_name`." + "This cannot be applied with `use_timestamp_channel_name`, `use_random_channel_name` or `use_user_id_channel_name`.", + "See also: `use_timestamp_channel_name`, `use_user_id_channel_name`, `use_random_channel_name`." + ] + }, + "use_random_channel_name": { + "default": "No", + "description": "When this is set to `yes`, new thread channels will be named with random characters tied to their user ID.", + "examples": [ + "`{prefix}config set use_random_channel_name yes`", + "`{prefix}config set use_random_channel_name no`" + ], + "notes": [ + "This config is suitable for servers in Server Discovery to comply with channel name restrictions.", + "This cannot be applied with `use_timestamp_channel_name`, `use_nickname_channel_name`, or `use_user_id_channel_name`.", + "See also: `use_timestamp_channel_name`, `use_user_id_channel_name`, `use_nickname_channel_name`." ] }, "mod_typing": { diff --git a/pyproject.toml b/pyproject.toml index 80217af8fb..aafdcd0d49 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev11' +version = '4.0.0-dev12' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 2214cbe1b7a79895367292b43d27965ed9d3242c Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 22:33:41 +0800 Subject: [PATCH 087/225] bump dpy@e9c7c09ebfe780d8f9de1e9e4d3c2dddf85eccfd --- Pipfile | 2 +- Pipfile.lock | 20 +++++++++++--------- requirements.txt | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Pipfile b/Pipfile index e9b1e58f76..88d49f59fd 100644 --- a/Pipfile +++ b/Pipfile @@ -12,7 +12,7 @@ typing-extensions = "==4.2.0" [packages] aiohttp = "==3.8.1" colorama = "~=0.4.4" # Doesn't officially support Python 3.9 yet, v0.4.5 will support 3.9 -"discord.py" = {ref = "a14b43f2fda863ed6555374eb872bf014bdd1adf", git = "https://github.com/Rapptz/discord.py.git"} +"discord.py" = {ref = "e9c7c09ebfe780d8f9de1e9e4d3c2dddf85eccfd", git = "https://github.com/Rapptz/discord.py.git"} emoji = "==1.7.0" isodate = "~=0.6.0" motor = "==2.5.1" diff --git a/Pipfile.lock b/Pipfile.lock index 8dff48027a..163d09bdcd 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b6bc030eedf7606f6ceeda324e896c29d5771108afa224c712d4c92d81875899" + "sha256": "4035fc1c98c21d437f41fcd2f32ca38089131e4a60ef0f4453caf4019dae7bd3" }, "pipfile-spec": 6, "requires": {}, @@ -190,7 +190,7 @@ "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df" ], - "markers": "python_version >= '3.5'", + "markers": "python_full_version >= '3.5.0'", "version": "==2.0.12" }, "colorama": { @@ -219,11 +219,11 @@ }, "discord-py": { "git": "https://github.com/Rapptz/discord.py.git", - "ref": "a14b43f2fda863ed6555374eb872bf014bdd1adf" + "ref": "e9c7c09ebfe780d8f9de1e9e4d3c2dddf85eccfd" }, "discord.py": { "git": "https://github.com/Rapptz/discord.py.git", - "ref": "a14b43f2fda863ed6555374eb872bf014bdd1adf" + "ref": "e9c7c09ebfe780d8f9de1e9e4d3c2dddf85eccfd" }, "dnspython": { "hashes": [ @@ -310,7 +310,7 @@ "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], - "markers": "python_version >= '3.5'", + "markers": "python_full_version >= '3.5.0'", "version": "==3.3" }, "isodate": { @@ -471,7 +471,9 @@ "version": "==2.21" }, "pymongo": { - "extras": [], + "extras": [ + "srv" + ], "hashes": [ "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", @@ -772,11 +774,11 @@ }, "click": { "hashes": [ - "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e", - "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72" + "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", + "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" ], "markers": "python_version >= '3.7'", - "version": "==8.1.2" + "version": "==8.1.3" }, "colorama": { "hashes": [ diff --git a/requirements.txt b/requirements.txt index e7223057ad..edc784029b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,7 +20,7 @@ defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, dnspython==2.2.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' emoji==1.7.0 frozenlist==1.3.0; python_version >= '3.7' -git+https://github.com/Rapptz/discord.py.git@a14b43f2fda863ed6555374eb872bf014bdd1adf#egg=discord.py +git+https://github.com/Rapptz/discord.py.git@e9c7c09ebfe780d8f9de1e9e4d3c2dddf85eccfd#egg=discord.py idna==3.3; python_version >= '3.5' isodate==0.6.1 lottie[pdf]==0.6.11 From 97c70bfb475cccd2453d8e73486e377f26706920 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 22:40:00 +0800 Subject: [PATCH 088/225] fix typing --- bot.py | 6 +++--- cogs/modmail.py | 4 ++-- core/thread.py | 2 +- core/utils.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bot.py b/bot.py index bcd6acfee9..c8eb75512c 100644 --- a/bot.py +++ b/bot.py @@ -1227,7 +1227,7 @@ async def on_typing(self, channel, user, _): thread = await self.threads.find(recipient=user) if thread: - await thread.channel.trigger_typing() + await thread.channel.typing() else: if not self.config.get("mod_typing"): return @@ -1237,7 +1237,7 @@ async def on_typing(self, channel, user, _): for user in thread.recipients: if await self.is_blocked(user): continue - await user.trigger_typing() + await user.typing() async def handle_reaction_events(self, payload): user = self.get_user(payload.user_id) @@ -1508,7 +1508,7 @@ async def on_error(self, event_method, *args, **kwargs): async def on_command_error(self, context, exception): if isinstance(exception, (commands.BadArgument, commands.BadUnionArgument)): - await context.trigger_typing() + await context.typing() await context.send(embed=discord.Embed(color=self.error_color, description=str(exception))) elif isinstance(exception, commands.CommandNotFound): logger.warning("CommandNotFound: %s", exception) diff --git a/cogs/modmail.py b/cogs/modmail.py index bb8c90e29e..f1c6c20ee8 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1158,7 +1158,7 @@ async def logs(self, ctx, *, user: User = None): `user` may be a user ID, mention, or name. """ - await ctx.trigger_typing() + await ctx.typing() if not user: thread = ctx.thread @@ -1268,7 +1268,7 @@ async def logs_search(self, ctx, limit: Optional[int] = None, *, query): Provide a `limit` to specify the maximum number of logs the bot should find. """ - await ctx.trigger_typing() + await ctx.typing() entries = await self.bot.api.search_by_text(query, limit) diff --git a/core/thread.py b/core/thread.py index 7edfbc1d39..e39076d702 100644 --- a/core/thread.py +++ b/core/thread.py @@ -1134,7 +1134,7 @@ def lottie_to_png(data): logger.info("Sending a message to %s when DM disabled is set.", self.recipient) try: - await destination.trigger_typing() + await destination.typing() except discord.NotFound: logger.warning("Channel not found.") raise diff --git a/core/utils.py b/core/utils.py index 9b56cbe31d..425b245511 100644 --- a/core/utils.py +++ b/core/utils.py @@ -397,8 +397,8 @@ def format_description(i, names): def trigger_typing(func): @functools.wraps(func) async def wrapper(self, ctx: commands.Context, *args, **kwargs): - await ctx.trigger_typing() - return await func(self, ctx, *args, **kwargs) + async with ctx.typing(): + return await func(self, ctx, *args, **kwargs) return wrapper From afb9e3a935c5fe6c11911d2c4a7f1202be6e0a19 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 22:40:42 +0800 Subject: [PATCH 089/225] remove deprecated decorators.py --- core/decorators.py | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 core/decorators.py diff --git a/core/decorators.py b/core/decorators.py deleted file mode 100644 index 0107a6b2d6..0000000000 --- a/core/decorators.py +++ /dev/null @@ -1,12 +0,0 @@ -import warnings - -from core.utils import trigger_typing as _trigger_typing - - -def trigger_typing(func): - warnings.warn( - "trigger_typing has been moved to core.utils.trigger_typing, this will be removed.", - DeprecationWarning, - stacklevel=2, - ) - return _trigger_typing(func) From 8d1e4f70fed97f9f49526d24290c3481597a76e7 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 22:41:30 +0800 Subject: [PATCH 090/225] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa5d0ad75a..f592f3278c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Bump emoji to v1.7.0 - Bump aiohttp to v3.8.1 - Bump lottie to v0.6.11 +- Remove deprecated `core/decorators.py` from v3.3.0 # v3.10.3 From ecc92e4bbf44d0f44d2df902e16a30734320070e Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 22:48:20 +0800 Subject: [PATCH 091/225] fix <3.9 features --- bot.py | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index c8eb75512c..f1dc8b6b59 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev12" +__version__ = "4.0.0-dev13" import asyncio @@ -995,7 +995,7 @@ async def get_contexts(self, message, *, cls=commands.Context): # This needs to be done before checking for aliases since # snippets can have multiple words. try: - snippet_text = self.snippets[message.content.removeprefix(invoked_prefix)] + snippet_text = self.snippets[message.content.strip(invoked_prefix)] except KeyError: snippet_text = None diff --git a/pyproject.toml b/pyproject.toml index aafdcd0d49..c69f704341 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev12' +version = '4.0.0-dev13' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From e1efa8c2f65ba3c09a594604dba0c98eed942321 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 22:53:33 +0800 Subject: [PATCH 092/225] update jobs to cover 3.7-3.10 and all platforms --- .github/workflows/lints.yml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 091e012dd9..1be351818e 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -5,20 +5,21 @@ on: [push, pull_request] jobs: code-style: -# runs-on: ${{ matrix.os }} -# strategy: -# fail-fast: false -# matrix: -# os: [ubuntu-latest, windows-latest, macOS-latest] -# python-version: [3.6, 3.7] + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + python-version: [3.7, 3.8, 3.9, 3.10] + + name: Python ${{ matrix.python-version }} Test - runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.9 - uses: actions/setup-python@v2 + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 with: - python-version: 3.9 + python-version: ${{ matrix.python-version }} + architecture: x64 - name: Install dependencies run: | python -m pip install --upgrade pip pipenv From 927fd37b0e4b8d6c76ed233968e38f0a8c860d70 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 22:56:04 +0800 Subject: [PATCH 093/225] fix linting file --- .github/workflows/lints.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 1be351818e..3ededb294a 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -4,12 +4,11 @@ on: [push, pull_request] jobs: code-style: - - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] - python-version: [3.7, 3.8, 3.9, 3.10] + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + python-version: [3.7, 3.8, 3.9, 3.10] name: Python ${{ matrix.python-version }} Test From 0a7f86281aa327767d5168cb9b0ce541c4577343 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 22:57:27 +0800 Subject: [PATCH 094/225] fix lint gh-action --- .github/workflows/lints.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 3ededb294a..fddccac8f1 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -8,9 +8,9 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - python-version: [3.7, 3.8, 3.9, 3.10] + python-version: ['3.7', '3.8', '3.9', '3.10'] - name: Python ${{ matrix.python-version }} Test + name: Python ${{ matrix.python-version }} on ${{ matrix.os }} steps: - uses: actions/checkout@v3 From daa4ce7e357163c270c1f10ed5478b25e2f5b0a4 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 23:00:40 +0800 Subject: [PATCH 095/225] only formally support Python 3.8+ --- .github/workflows/lints.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index fddccac8f1..a7418930be 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - python-version: ['3.7', '3.8', '3.9', '3.10'] + python-version: ['3.8', '3.9', '3.10'] name: Python ${{ matrix.python-version }} on ${{ matrix.os }} diff --git a/README.md b/README.md index 4487438a5c..1558a04755 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ If you don't want to go through the trouble of setting up your very own Modmail ### Locally -Local hosting of Modmail is also possible. First, you will need [`Python 3.8`](https://www.python.org/downloads/release/python-376/). +Local hosting of Modmail is also possible. First, you will need at least [`Python 3.8`](https://www.python.org/downloads/release/python-376/). Follow the [**installation guide**](https://github.com/kyb3r/modmail/wiki/Installation) and disregard deploying the Heroku bot application. If you run into any problems, join our [Modmail Discord Server](https://discord.gg/etJNHCQ) for help and support. From 5a32966c10b96c31febcdacfddbe851aed7f40b4 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 23:02:45 +0800 Subject: [PATCH 096/225] fix type annotation for PY3.8 --- cogs/modmail.py | 4 ++-- runtime.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 runtime.txt diff --git a/cogs/modmail.py b/cogs/modmail.py index f1c6c20ee8..a45b44e573 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -2,7 +2,7 @@ import re from datetime import datetime, timezone from itertools import zip_longest -from typing import Optional, Union +from typing import Optional, Union, List, Tuple from types import SimpleNamespace import discord @@ -249,7 +249,7 @@ async def snippet_add(self, ctx, name: str.lower, *, value: commands.clean_conte ) return await ctx.send(embed=embed) - def _fix_aliases(self, snippet_being_deleted: str) -> tuple[list[str]]: + def _fix_aliases(self, snippet_being_deleted: str) -> Tuple[List[str]]: """ Remove references to the snippet being deleted from aliases. diff --git a/runtime.txt b/runtime.txt new file mode 100644 index 0000000000..30e81e3130 --- /dev/null +++ b/runtime.txt @@ -0,0 +1 @@ +python-3.10.3 From b8df285b6826d4f3d4dd59f3415ab0e228c564be Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 23:16:18 +0800 Subject: [PATCH 097/225] improve multi-page pagination dropdown and titles --- cogs/modmail.py | 33 +++++++++++++++++++++------------ cogs/utility.py | 8 ++++++-- core/utils.py | 4 ++-- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index a45b44e573..19a6842dc7 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1637,8 +1637,6 @@ async def contact( async def blocked(self, ctx): """Retrieve a list of blocked users.""" - embeds = [discord.Embed(title="Blocked Users", color=self.bot.main_color, description="")] - roles = [] users = [] now = ctx.message.created_at @@ -1700,43 +1698,54 @@ async def blocked(self, ctx): if role: roles.append((role.mention, reason)) + user_embeds = [discord.Embed(title="Blocked Users", color=self.bot.main_color, description="")] + if users: - embed = embeds[0] + embed = user_embeds[0] for mention, reason in users: line = mention + f" - {reason or 'No Reason Provided'}\n" if len(embed.description) + len(line) > 2048: embed = discord.Embed( - title="Blocked Users (Continued)", + title="Blocked Users", color=self.bot.main_color, description=line, ) - embeds.append(embed) + user_embeds.append(embed) else: embed.description += line else: - embeds[0].description = "Currently there are no blocked users." + user_embeds[0].description = "Currently there are no blocked users." + + if len(user_embeds) > 1: + for n, em in enumerate(user_embeds): + em.title = f'{em.title} [{n + 1}]' - embeds.append(discord.Embed(title="Blocked Roles", color=self.bot.main_color, description="")) + role_embeds = [discord.Embed(title="Blocked Roles", color=self.bot.main_color, description="")] if roles: - embed = embeds[-1] + embed = role_embeds[-1] for mention, reason in roles: line = mention + f" - {reason or 'No Reason Provided'}\n" if len(embed.description) + len(line) > 2048: + role_embeds[-1].set_author() embed = discord.Embed( - title="Blocked Roles (Continued)", + title="Blocked Roles", color=self.bot.main_color, description=line, ) - embeds.append(embed) + role_embeds.append(embed) else: embed.description += line else: - embeds[-1].description = "Currently there are no blocked roles." + role_embeds[-1].description = "Currently there are no blocked roles." - session = EmbedPaginatorSession(ctx, *embeds) + if len(role_embeds) > 1: + for n, em in enumerate(role_embeds): + em.title = f'{em.title} [{n + 1}]' + + session = EmbedPaginatorSession(ctx, *user_embeds, *role_embeds) await session.run() diff --git a/cogs/utility.py b/cogs/utility.py index 23827aa0c4..538ddc18e1 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -89,15 +89,19 @@ async def format_cog_help(self, cog, *, no_cog=False): embed.add_field(name="Commands", value=format_ or "No commands.") - continued = " (Continued)" if embeds else "" name = cog.qualified_name + " - Help" if not no_cog else "Miscellaneous Commands" - embed.set_author(name=name + continued, icon_url=bot.user.display_avatar.url) + embed.set_author(name=name, icon_url=bot.user.display_avatar.url) embed.set_footer( text=f'Type "{prefix}{self.command_attrs["name"]} command" ' "for more info on a specific command." ) embeds.append(embed) + + if len(embeds) > 1: + for n, em in enumerate(embeds): + em.set_author(name=f'{em.author.name} [{n + 1}]', icon_url=em.author.icon_url) + return embeds def process_help_msg(self, help_: str): diff --git a/core/utils.py b/core/utils.py index 425b245511..32f12c72e8 100644 --- a/core/utils.py +++ b/core/utils.py @@ -397,8 +397,8 @@ def format_description(i, names): def trigger_typing(func): @functools.wraps(func) async def wrapper(self, ctx: commands.Context, *args, **kwargs): - async with ctx.typing(): - return await func(self, ctx, *args, **kwargs) + await ctx.typing() + return await func(self, ctx, *args, **kwargs) return wrapper From 77489be6a21cf4befeab1dc7fa2c2d2098104cbc Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 23:16:44 +0800 Subject: [PATCH 098/225] bump version --- bot.py | 2 +- cogs/modmail.py | 4 ++-- cogs/utility.py | 2 +- pyproject.toml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bot.py b/bot.py index f1dc8b6b59..a506addfd9 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev13" +__version__ = "4.0.0-dev14" import asyncio diff --git a/cogs/modmail.py b/cogs/modmail.py index 19a6842dc7..deb29d160d 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1719,7 +1719,7 @@ async def blocked(self, ctx): if len(user_embeds) > 1: for n, em in enumerate(user_embeds): - em.title = f'{em.title} [{n + 1}]' + em.title = f"{em.title} [{n + 1}]" role_embeds = [discord.Embed(title="Blocked Roles", color=self.bot.main_color, description="")] @@ -1743,7 +1743,7 @@ async def blocked(self, ctx): if len(role_embeds) > 1: for n, em in enumerate(role_embeds): - em.title = f'{em.title} [{n + 1}]' + em.title = f"{em.title} [{n + 1}]" session = EmbedPaginatorSession(ctx, *user_embeds, *role_embeds) diff --git a/cogs/utility.py b/cogs/utility.py index 538ddc18e1..0e86934af2 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -100,7 +100,7 @@ async def format_cog_help(self, cog, *, no_cog=False): if len(embeds) > 1: for n, em in enumerate(embeds): - em.set_author(name=f'{em.author.name} [{n + 1}]', icon_url=em.author.icon_url) + em.set_author(name=f"{em.author.name} [{n + 1}]", icon_url=em.author.icon_url) return embeds diff --git a/pyproject.toml b/pyproject.toml index c69f704341..56f30163c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev13' +version = '4.0.0-dev14' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 454bdae898da6e431783b1f14d2ae8b51cdf2580 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 3 May 2022 23:31:10 +0800 Subject: [PATCH 099/225] fix typos --- CHANGELOG.md | 3 ++- cogs/utility.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f592f3278c..c096d05d7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `plain_snippets` config to force all snippets to be plain. ([GH #3083](https://github.com/kyb3r/modmail/issues/3083)) - `?fpareply` and `?fpreply` to reply to messages with variables plainly. - `use_nickname_channel_name` config to use nicknames instead of usernames for channel names. ([GH #3112](https://github.com/kyb3r/modmail/issues/3112)) -- `use_random_channel_name` config to use random nicknames vaguely tied to user ID. It is unable to be computed in reverse. ([GH #3143](https://github.com/kyb3r/modmail/issues/3143) +- `use_random_channel_name` config to use random nicknames vaguely tied to user ID. It is unable to be computed in reverse. ([GH #3143](https://github.com/kyb3r/modmail/issues/3143)) - `show_log_url_button` config to show Log URL button. ([GH #3122](https://github.com/kyb3r/modmail/issues/3122)) - Select menus for certain paginators. - `Title` field in `?logs`. ([GH #3142](https://github.com/kyb3r/modmail/issues/3142)) @@ -33,6 +33,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Modmail now uses per-server avatars if applicable. ([GH #3048](https://github.com/kyb3r/modmail/issues/3048)) - Use discord relative timedeltas. ([GH #3046](https://github.com/kyb3r/modmail/issues/3046)) - Use discord native buttons for all paginator sessions. +- `?help` and `?blocked` paginator sessions now have better multi-page UI. ### Fixed diff --git a/cogs/utility.py b/cogs/utility.py index 0e86934af2..0baa82cfcd 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -39,7 +39,7 @@ class ModmailHelpCommand(commands.HelpCommand): async def command_callback(self, ctx, *, command=None): - """Ovrwrites original command_callback to ensure `help` without any arguments + """Overwrites original command_callback to ensure `help` without any arguments returns with checks, `help all` returns without checks""" if command is None: self.verify_checks = True From e3571cdb3a75a27898c1622a3d78a8285f4cc90a Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 4 May 2022 00:33:27 +0800 Subject: [PATCH 100/225] update gtk message --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index a506addfd9..14ac7b4d8f 100644 --- a/bot.py +++ b/bot.py @@ -1742,7 +1742,7 @@ def main(): ) else: logger.error( - "Unable to import cairosvg, install GTK Installer for Windows: https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer/releases/latest" + "Unable to import cairosvg, install GTK Installer for Windows and restart your system (https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer/releases/latest)" ) else: logger.error( From fa135eb53b278148fb411a2b1282c2fb28efad10 Mon Sep 17 00:00:00 2001 From: Jerrie-Aries <hidzrie@gmail.com> Date: Tue, 7 Jun 2022 00:52:22 +0000 Subject: [PATCH 101/225] Improve and error handling for update and autoupdate features. --- bot.py | 65 ++++++++++++++++++--------------- cogs/utility.py | 38 +++++++++++++------- core/clients.py | 96 +++++++++++++++++++++++++++++++++++++------------ 3 files changed, 136 insertions(+), 63 deletions(-) diff --git a/bot.py b/bot.py index a506addfd9..5db1aab550 100644 --- a/bot.py +++ b/bot.py @@ -17,7 +17,7 @@ import discord import isodate -from aiohttp import ClientSession +from aiohttp import ClientSession, ClientResponseError from discord.ext import commands, tasks from discord.ext.commands.view import StringView from emoji import UNICODE_EMOJI @@ -630,6 +630,8 @@ async def on_ready(self): ) logger.warning("If the external servers are valid, you may ignore this message.") + self.post_metadata.start() + self.autoupdate.start() self._started = True async def convert_emoji(self, name: str) -> str: @@ -1581,6 +1583,7 @@ async def before_post_metadata(self): await self.wait_for_connected() if not self.config.get("data_collection") or not self.guild: self.post_metadata.cancel() + return logger.debug("Starting metadata loop.") logger.line("debug") @@ -1591,44 +1594,50 @@ async def autoupdate(self): latest = changelog.latest_version if self.version < parse_version(latest.version): - if self.hosting_method == HostingMethod.HEROKU: + try: + # update fork if gh_token exists data = await self.api.update_repository() + except InvalidConfigError: + data = {} + except ClientResponseError as exc: + logger.error(f"Autoupdate failed! Status {exc.status}.") + logger.error(f"Message: {exc.message}") + self.autoupdate.cancel() + return + if self.hosting_method == HostingMethod.HEROKU: + commit_data = data.get("data") + if not commit_data: + return - embed = discord.Embed(color=self.main_color) + logger.info("Bot has been updated.") + + if not self.config["update_notifications"]: + return - commit_data = data["data"] + embed = discord.Embed(color=self.main_color) + message = commit_data["commit"]["message"] + html_url = commit_data["html_url"] + short_sha = commit_data["sha"][:6] user = data["user"] + embed.add_field( + name="Merge Commit", + value=f"[`{short_sha}`]({html_url}) " f"{message} - {user['username']}", + ) embed.set_author( name=user["username"] + " - Updating Bot", icon_url=user["avatar_url"], url=user["url"], ) - embed.set_footer(text=f"Updating Modmail v{self.version} " f"-> v{latest.version}") + embed.set_footer(text=f"Updating Modmail v{self.version} -> v{latest.version}") embed.description = latest.description for name, value in latest.fields.items(): embed.add_field(name=name, value=value) - if commit_data: - message = commit_data["commit"]["message"] - html_url = commit_data["html_url"] - short_sha = commit_data["sha"][:6] - embed.add_field( - name="Merge Commit", - value=f"[`{short_sha}`]({html_url}) " f"{message} - {user['username']}", - ) - logger.info("Bot has been updated.") - channel = self.log_channel - if self.config["update_notifications"]: - await channel.send(embed=embed) + channel = self.update_channel + await channel.send(embed=embed) else: - try: - # update fork if gh_token exists - await self.api.update_repository() - except InvalidConfigError: - pass - command = "git pull" proc = await asyncio.create_subprocess_shell( command, @@ -1642,7 +1651,7 @@ async def autoupdate(self): if err and not res: logger.warning(f"Autoupdate failed: {err}") - self.autoupdate_loop.cancel() + self.autoupdate.cancel() return elif res != "Already up to date.": @@ -1659,7 +1668,7 @@ async def autoupdate(self): description="If you do not have an auto-restart setup, please manually start the bot.", color=self.main_color, ) - embed.set_footer(text=f"Updating Modmail v{self.version} " f"-> v{latest.version}") + embed.set_footer(text=f"Updating Modmail v{self.version} -> v{latest.version}") if self.config["update_notifications"]: await channel.send(embed=embed) return await self.close() @@ -1671,16 +1680,16 @@ async def before_autoupdate(self): if self.config.get("disable_autoupdates"): logger.warning("Autoupdates disabled.") - self.autoupdate_loop.cancel() + self.autoupdate.cancel() if self.hosting_method == HostingMethod.DOCKER: logger.warning("Autoupdates disabled as using Docker.") - self.autoupdate_loop.cancel() + self.autoupdate.cancel() if not self.config.get("github_token") and self.hosting_method == HostingMethod.HEROKU: logger.warning("GitHub access token not found.") logger.warning("Autoupdates disabled.") - self.autoupdate_loop.cancel() + self.autoupdate.cancel() def format_channel_name(self, author, exclude_channel=None, force_null=False): """Sanitises a username for use with text channel names diff --git a/cogs/utility.py b/cogs/utility.py index 0e86934af2..5d35a20211 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -1931,7 +1931,7 @@ async def github(self, ctx): async def update(self, ctx, *, flag: str = ""): """ Update Modmail. - To stay up-to-date with the latest commit rom GitHub, specify "force" as the flag. + To stay up-to-date with the latest commit from GitHub, specify "force" as the flag. """ changelog = await Changelog.from_url(self.bot) @@ -1939,7 +1939,7 @@ async def update(self, ctx, *, flag: str = ""): desc = ( f"The latest version is [`{self.bot.version}`]" - "(https://github.com/kyb3r/modmail/blob/master/bot.py#L25)" + "(https://github.com/kyb3r/modmail/blob/master/bot.py#L1)" ) if self.bot.version >= parse_version(latest.version) and flag.lower() != "force": @@ -1951,16 +1951,35 @@ async def update(self, ctx, *, flag: str = ""): embed.set_author(name=user["username"], icon_url=user["avatar_url"], url=user["url"]) await ctx.send(embed=embed) else: - if self.bot.hosting_method == HostingMethod.HEROKU: + try: + # update fork if gh_token exists data = await self.bot.api.update_repository() + except InvalidConfigError: + data = {} + except ClientResponseError as exc: + embed = discord.Embed( + title="Update failed", + description=f"Error status {exc.status}. {exc.message}", + color=self.bot.error_color, + ) + return await ctx.send(embed=embed) + + if self.bot.hosting_method == HostingMethod.HEROKU: + if not data: + # invalid gh_token + embed = discord.Embed( + title="Update failed", + description="Invalid Github token.", + color=self.bot.error_color, + ) + return await ctx.send(embed=embed) commit_data = data["data"] user = data["user"] - if commit_data and commit_data.get("html_url"): embed = discord.Embed(color=self.bot.main_color) - embed.set_footer(text=f"Updating Modmail v{self.bot.version} " f"-> v{latest.version}") + embed.set_footer(text=f"Updating Modmail v{self.bot.version} -> v{latest.version}") embed.set_author( name=user["username"] + " - Updating bot", @@ -1978,21 +1997,14 @@ async def update(self, ctx, *, flag: str = ""): else: embed = discord.Embed( title="Already up to date", - description="No further updates required", + description="No further updates required.", color=self.bot.main_color, ) embed.set_footer(text="Force update") embed.set_author(name=user["username"], icon_url=user["avatar_url"], url=user["url"]) await ctx.send(embed=embed) else: - # update fork if gh_token exists - try: - await self.bot.api.update_repository() - except InvalidConfigError: - pass - command = "git pull" - proc = await asyncio.create_subprocess_shell( command, stderr=PIPE, diff --git a/core/clients.py b/core/clients.py index a9722776f2..862c665310 100644 --- a/core/clients.py +++ b/core/clients.py @@ -1,7 +1,7 @@ import secrets import sys from json import JSONDecodeError -from typing import Union, Optional +from typing import Any, Dict, Union, Optional import discord from discord import Member, DMChannel, TextChannel, Message @@ -19,6 +19,7 @@ class GitHub: """ The client for interacting with GitHub API. + Parameters ---------- bot : Bot @@ -31,6 +32,7 @@ class GitHub: URL to the avatar in GitHub. url : str, optional URL to the GitHub profile. + Attributes ---------- bot : Bot @@ -43,6 +45,7 @@ class GitHub: URL to the avatar in GitHub. url : str URL to the GitHub profile. + Class Attributes ---------------- BASE : str @@ -77,7 +80,7 @@ def __init__(self, bot, access_token: str = "", username: str = "", **kwargs): self.headers = {"Authorization": "token " + str(access_token)} @property - def BRANCH(self): + def BRANCH(self) -> str: return "master" if not self.bot.version.is_prerelease else "development" async def request( @@ -85,11 +88,13 @@ async def request( url: str, method: str = "GET", payload: dict = None, - return_response: bool = False, headers: dict = None, - ) -> Union[ClientResponse, dict, str]: + return_response: bool = False, + read_before_return: bool = True, + ) -> Union[ClientResponse, Dict[str, Any], str]: """ Makes a HTTP request. + Parameters ---------- url : str @@ -98,16 +103,20 @@ async def request( The HTTP method (POST, GET, PUT, DELETE, FETCH, etc.). payload : Dict[str, Any] The json payload to be sent along the request. - return_response : bool - Whether the `ClientResponse` object should be returned. headers : Dict[str, str] Additional headers to `headers`. + return_response : bool + Whether the `ClientResponse` object should be returned. + read_before_return : bool + Whether to perform `.read()` method before returning the `ClientResponse` object. + Only valid if `return_response` is set to `True`. + Returns ------- ClientResponse or Dict[str, Any] or List[Any] or str `ClientResponse` if `return_response` is `True`. - `dict` if the returned data is a json object. - `list` if the returned data is a json list. + `Dict[str, Any]` if the returned data is a json object. + `List[Any]` if the returned data is a json list. `str` if the returned data is not a valid json data, the raw response. """ @@ -117,19 +126,24 @@ async def request( headers = self.headers async with self.session.request(method, url, headers=headers, json=payload) as resp: if return_response: + if read_before_return: + await resp.read() return resp + try: return await resp.json() except (JSONDecodeError, ClientResponseError): return await resp.text() - def filter_valid(self, data): + def filter_valid(self, data) -> Dict[str, Any]: """ Filters configuration keys that are accepted. + Parameters ---------- data : Dict[str, Any] The data that needs to be cleaned. + Returns ------- Dict[str, Any] @@ -138,42 +152,73 @@ def filter_valid(self, data): valid_keys = self.bot.config.valid_keys.difference(self.bot.config.protected_keys) return {k: v for k, v in data.items() if k in valid_keys} - async def update_repository(self, sha: str = None) -> Optional[dict]: + async def update_repository(self, sha: str = None) -> Dict[str, Any]: """ Update the repository from Modmail main repo. + Parameters ---------- - sha : Optional[str], optional - The commit SHA to update the repository. + sha : Optional[str] + The commit SHA to update the repository. If `None`, the latest + commit SHA will be fetched. + Returns ------- - Optional[dict] - If the response is a dict. + Dict[str, Any] + A dictionary that contains response data. """ if not self.username: raise commands.CommandInvokeError("Username not found.") if sha is None: - resp: dict = await self.request(self.REPO + "/git/refs/heads/" + self.BRANCH) + resp = await self.request(self.REPO + "/git/refs/heads/" + self.BRANCH) sha = resp["object"]["sha"] payload = {"base": self.BRANCH, "head": sha, "commit_message": "Updating bot"} merge_url = self.MERGE_URL.format(username=self.username) - resp = await self.request(merge_url, method="POST", payload=payload) - if isinstance(resp, dict): - return resp + resp = await self.request( + merge_url, + method="POST", + payload=payload, + return_response=True, + read_before_return=True, + ) + + repo_url = self.BASE + f"/repos/{self.username}/modmail" + status_map = { + 201: "Successful response.", + 204: "Already merged.", + 403: "Forbidden.", + 404: f"Repository '{repo_url}' not found.", + 409: "There is a merge conflict.", + 422: "Validation failed.", + } + # source https://docs.github.com/en/rest/branches/branches#merge-a-branch + + status = resp.status + if status in (201, 204): + try: + return await resp.json() + except (JSONDecodeError, ClientResponseError): + return await resp.text() + + args = (resp.request_info, resp.history) + kwargs = {"status": status, "message": status_map.get(status)} + # just raise + raise ClientResponseError(*args, **kwargs) async def fork_repository(self) -> None: """ Forks Modmail's repository. """ - await self.request(self.FORK_URL, method="POST") + await self.request(self.FORK_URL, method="POST", return_response=True) async def has_starred(self) -> bool: """ Checks if shared Modmail. + Returns ------- bool @@ -187,23 +232,30 @@ async def star_repository(self) -> None: """ Stars Modmail's repository. """ - await self.request(self.STAR_URL, method="PUT", headers={"Content-Length": "0"}) + await self.request( + self.STAR_URL, + method="PUT", + headers={"Content-Length": "0"}, + return_response=True, + ) @classmethod async def login(cls, bot) -> "GitHub": """ Logs in to GitHub with configuration variable information. + Parameters ---------- bot : Bot The Modmail bot. + Returns ------- GitHub The newly created `GitHub` object. """ self = cls(bot, bot.config.get("github_token")) - resp: dict = await self.request("https://api.github.com/user") + resp: Dict[str, Any] = await self.request(self.BASE + "/user") if resp.get("login"): self.username = resp["login"] self.avatar_url = resp["avatar_url"] @@ -666,7 +718,7 @@ async def update_repository(self) -> dict: "data": data, "user": { "username": user.username, - "avatar_url": user.display_avatar.url, + "avatar_url": user.avatar_url, "url": user.url, }, } From 23221a2fd691733ede405a44b9da5f593e2d74c7 Mon Sep 17 00:00:00 2001 From: Jerrie-Aries <hidzrie@gmail.com> Date: Tue, 7 Jun 2022 14:36:09 +0000 Subject: [PATCH 102/225] Fix previous commit. - Return only if hosting method is HEROKU. - Try to get the response error message first if any. --- bot.py | 18 +++++++++++++----- cogs/utility.py | 18 +++++++++++------- core/clients.py | 32 +++++++++++++++++++++++--------- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/bot.py b/bot.py index 5db1aab550..f3dc071fab 100644 --- a/bot.py +++ b/bot.py @@ -1594,17 +1594,22 @@ async def autoupdate(self): latest = changelog.latest_version if self.version < parse_version(latest.version): + error = None + data = {} try: # update fork if gh_token exists data = await self.api.update_repository() except InvalidConfigError: - data = {} + pass except ClientResponseError as exc: - logger.error(f"Autoupdate failed! Status {exc.status}.") - logger.error(f"Message: {exc.message}") - self.autoupdate.cancel() - return + error = exc if self.hosting_method == HostingMethod.HEROKU: + if error is not None: + logger.error(f"Autoupdate failed! Status: {error.status}.") + logger.error(f"Error message: {error.message}") + self.autoupdate.cancel() + return + commit_data = data.get("data") if not commit_data: return @@ -1681,15 +1686,18 @@ async def before_autoupdate(self): if self.config.get("disable_autoupdates"): logger.warning("Autoupdates disabled.") self.autoupdate.cancel() + return if self.hosting_method == HostingMethod.DOCKER: logger.warning("Autoupdates disabled as using Docker.") self.autoupdate.cancel() + return if not self.config.get("github_token") and self.hosting_method == HostingMethod.HEROKU: logger.warning("GitHub access token not found.") logger.warning("Autoupdates disabled.") self.autoupdate.cancel() + return def format_channel_name(self, author, exclude_channel=None, force_null=False): """Sanitises a username for use with text channel names diff --git a/cogs/utility.py b/cogs/utility.py index 5d35a20211..ba60253370 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -1951,20 +1951,24 @@ async def update(self, ctx, *, flag: str = ""): embed.set_author(name=user["username"], icon_url=user["avatar_url"], url=user["url"]) await ctx.send(embed=embed) else: + error = None + data = {} try: # update fork if gh_token exists data = await self.bot.api.update_repository() except InvalidConfigError: - data = {} + pass except ClientResponseError as exc: - embed = discord.Embed( - title="Update failed", - description=f"Error status {exc.status}. {exc.message}", - color=self.bot.error_color, - ) - return await ctx.send(embed=embed) + error = exc if self.bot.hosting_method == HostingMethod.HEROKU: + if error is not None: + embed = discord.Embed( + title="Update failed", + description=f"Error status: {error.status}.\nError message: {error.message}", + color=self.bot.error_color, + ) + return await ctx.send(embed=embed) if not data: # invalid gh_token embed = discord.Embed( diff --git a/core/clients.py b/core/clients.py index 862c665310..df7e1b7b56 100644 --- a/core/clients.py +++ b/core/clients.py @@ -130,10 +130,18 @@ async def request( await resp.read() return resp - try: - return await resp.json() - except (JSONDecodeError, ClientResponseError): - return await resp.text() + return await self._get_response_data(resp) + + @staticmethod + async def _get_response_data(response: ClientResponse) -> Union[Dict[str, Any], str]: + """ + Internal method to convert the response data to `dict` if the data is a + json object, or to `str` (raw response) if the data is not a valid json. + """ + try: + return await response.json() + except (JSONDecodeError, ClientResponseError): + return await response.text() def filter_valid(self, data) -> Dict[str, Any]: """ @@ -198,14 +206,20 @@ async def update_repository(self, sha: str = None) -> Dict[str, Any]: # source https://docs.github.com/en/rest/branches/branches#merge-a-branch status = resp.status + data = await self._get_response_data(resp) if status in (201, 204): - try: - return await resp.json() - except (JSONDecodeError, ClientResponseError): - return await resp.text() + return data args = (resp.request_info, resp.history) - kwargs = {"status": status, "message": status_map.get(status)} + try: + # try to get the response error message if any + message = data.get("message") + except AttributeError: + message = None + kwargs = { + "status": status, + "message": message if message else status_map.get(status), + } # just raise raise ClientResponseError(*args, **kwargs) From f2865d22d489334893a679312cd5451203243e19 Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Sat, 25 Jun 2022 09:06:34 +0530 Subject: [PATCH 103/225] Remove the set title after creating thread --- core/thread.py | 1 - 1 file changed, 1 deletion(-) diff --git a/core/thread.py b/core/thread.py index e39076d702..606a204b37 100644 --- a/core/thread.py +++ b/core/thread.py @@ -196,7 +196,6 @@ async def setup(self, *, creator=None, category=None, initial_message=None): log_url = log_count = None # ensure core functionality still works - await channel.edit(topic=f"User ID: {recipient.id}") self.ready = True if creator is not None and creator != recipient: From 80fe41e3d6468eb7da440b3671ff1455bf919cc0 Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Sat, 25 Jun 2022 09:07:26 +0530 Subject: [PATCH 104/225] Add the set title during creating the thread --- core/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/core/utils.py b/core/utils.py index 32f12c72e8..30efb05e75 100644 --- a/core/utils.py +++ b/core/utils.py @@ -432,6 +432,7 @@ async def create_thread_channel(bot, recipient, category, overwrites, *, name=No name=name, category=category, overwrites=overwrites, + topic=f"User ID: {recipient.id}", reason="Creating a thread channel.", ) except discord.HTTPException as e: From c05725dcf251871910a691d535352a6464e2f977 Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Sat, 25 Jun 2022 10:09:31 +0530 Subject: [PATCH 105/225] Update bot.py --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index a506addfd9..e234eace55 100644 --- a/bot.py +++ b/bot.py @@ -1099,7 +1099,7 @@ async def get_context(self, message, *, cls=commands.Context): view = StringView(message.content) ctx = cls(prefix=self.prefix, view=view, bot=self, message=message) - if self._skip_check(message.author.id, self.user.id): + if message.author.id == self.user.id: return ctx ctx.thread = await self.threads.find(channel=ctx.channel) From 19b42f03f1c63c05e7c17f376b3ffee6e587eae1 Mon Sep 17 00:00:00 2001 From: Jerrie-Aries <hidzrie@gmail.com> Date: Sat, 25 Jun 2022 08:24:35 +0000 Subject: [PATCH 106/225] Fix Future attached to different loop, issue #3165 --- bot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index a506addfd9..8b912f4286 100644 --- a/bot.py +++ b/bot.py @@ -71,7 +71,7 @@ def __init__(self): self._api = None self.formatter = SafeFormatter() self.loaded_cogs = ["cogs.modmail", "cogs.plugins", "cogs.utility"] - self._connected = asyncio.Event() + self._connected = None self.start_time = discord.utils.utcnow() self._started = False @@ -213,6 +213,7 @@ async def get_prefix(self, message=None): def run(self): async def runner(): async with self: + self._connected = asyncio.Event() self.session = ClientSession(loop=self.loop) try: retry_intents = False From 30a0daa356b220181babad3b0d92e5acd6801b2b Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 3 Jul 2022 21:50:56 +0800 Subject: [PATCH 107/225] update changelog w new PRs --- CHANGELOG.md | 1 + bot.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c096d05d7f..054f126f7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Audit log searching now properly works. - Old data causing `?blocked` to fail. ([GH #3131](https://github.com/kyb3r/modmail/issues/3131)) - Delete channel auto close functionality now works. +- Improved error handling for autoupdate. ([PR #3161](https://github.com/kyb3r/modmail/pull/3161)) ### Internal diff --git a/bot.py b/bot.py index 788ba64604..3723e94325 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev14" +__version__ = "4.0.0-dev15" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 56f30163c2..8b306b2d18 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev14' +version = '4.0.0-dev15' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 109197d9f509eb4ae5b1c8e7c0d59e79a222ea0b Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Sun, 3 Jul 2022 21:54:30 +0800 Subject: [PATCH 108/225] update contributing.md --- .github/CONTRIBUTING.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 568e5f2175..b1309b6402 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -33,6 +33,17 @@ In short, when you submit code changes, your submissions are understood to be un ## Report bugs using [Github Issues](https://github.com/kyb3r/modmail/issues) We use GitHub issues to track public bugs. Report a bug by [opening a new Issue](https://github.com/kyb3r/modmail/issues/new); it's that easy! +## Find pre-existing issues to tackle +Check out our [unstaged issue tracker](https://github.com/kyb3r/modmail/issues?q=is%3Aissue+is%3Aopen+-label%3Astaged) and start helping out! + +Ways to help out: +- Help out new members +- Highlight invalid bugs/unsupported use cases +- Code review of pull requests +- Add on new use cases or reproduction steps +- Point out duplicate issues and guide them to the right direction +- Create a pull request to resolve the issue! + ## Write bug reports with detail, background, and sample code **Great Bug Reports** tend to have: @@ -43,7 +54,6 @@ We use GitHub issues to track public bugs. Report a bug by [opening a new Issue] - What *actually* happens - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) - ## Use a Consistent Coding Style We use [black](https://github.com/python/black) for a unified code style. From 3fe1ce8d5e495c06d814ed718ec40e7e2aa8e79a Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 6 Jul 2022 01:18:32 +0800 Subject: [PATCH 109/225] update dpy@37c9ab7 and colorama --- Pipfile | 4 +- Pipfile.lock | 260 +++++++++++++++++++++++++++++---------------------- 2 files changed, 148 insertions(+), 116 deletions(-) diff --git a/Pipfile b/Pipfile index 88d49f59fd..82ec35158d 100644 --- a/Pipfile +++ b/Pipfile @@ -11,8 +11,8 @@ typing-extensions = "==4.2.0" [packages] aiohttp = "==3.8.1" -colorama = "~=0.4.4" # Doesn't officially support Python 3.9 yet, v0.4.5 will support 3.9 -"discord.py" = {ref = "e9c7c09ebfe780d8f9de1e9e4d3c2dddf85eccfd", git = "https://github.com/Rapptz/discord.py.git"} +colorama = "~=0.4.5" +"discord.py" = {ref = "9fe19dcc6923e4b6133bdedafb33658bf37c9ab7", git = "https://github.com/Rapptz/discord.py.git"} emoji = "==1.7.0" isodate = "~=0.6.0" motor = "==2.5.1" diff --git a/Pipfile.lock b/Pipfile.lock index 163d09bdcd..87a2f247fc 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "4035fc1c98c21d437f41fcd2f32ca38089131e4a60ef0f4453caf4019dae7bd3" + "sha256": "89578b9ae8a9a0b580e0af21767bd2f062388ad43c9bdc6e5d113de91361bea3" }, "pipfile-spec": 6, "requires": {}, @@ -132,74 +132,88 @@ }, "cffi": { "hashes": [ - "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3", - "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2", - "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636", - "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20", - "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728", - "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27", - "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66", - "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443", - "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0", - "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7", - "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39", - "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605", - "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a", - "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37", - "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029", - "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139", - "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc", - "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df", - "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14", - "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880", - "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2", - "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a", - "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e", - "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474", - "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024", - "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8", - "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0", - "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e", - "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a", - "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e", - "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032", - "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6", - "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e", - "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b", - "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e", - "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954", - "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962", - "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c", - "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4", - "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55", - "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962", - "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023", - "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c", - "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6", - "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8", - "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382", - "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7", - "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc", - "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997", - "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796" - ], - "version": "==1.15.0" + "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", + "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef", + "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104", + "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426", + "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405", + "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375", + "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a", + "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e", + "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc", + "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf", + "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185", + "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497", + "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3", + "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35", + "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c", + "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83", + "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21", + "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca", + "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984", + "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac", + "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd", + "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee", + "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a", + "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2", + "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192", + "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7", + "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585", + "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f", + "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e", + "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27", + "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b", + "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e", + "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e", + "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d", + "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c", + "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415", + "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82", + "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02", + "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314", + "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325", + "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c", + "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3", + "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914", + "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045", + "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d", + "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9", + "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5", + "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2", + "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c", + "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3", + "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2", + "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8", + "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d", + "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d", + "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9", + "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162", + "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76", + "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4", + "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e", + "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9", + "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6", + "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b", + "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", + "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0" + ], + "version": "==1.15.1" }, "charset-normalizer": { "hashes": [ - "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", - "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df" + "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", + "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" ], - "markers": "python_full_version >= '3.5.0'", - "version": "==2.0.12" + "markers": "python_version >= '3.6'", + "version": "==2.1.0" }, "colorama": { "hashes": [ - "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b", - "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2" + "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da", + "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4" ], "index": "pypi", - "version": "==0.4.4" + "version": "==0.4.5" }, "cssselect2": { "hashes": [ @@ -219,11 +233,11 @@ }, "discord-py": { "git": "https://github.com/Rapptz/discord.py.git", - "ref": "e9c7c09ebfe780d8f9de1e9e4d3c2dddf85eccfd" + "ref": "9fe19dcc6923e4b6133bdedafb33658bf37c9ab7" }, "discord.py": { "git": "https://github.com/Rapptz/discord.py.git", - "ref": "e9c7c09ebfe780d8f9de1e9e4d3c2dddf85eccfd" + "ref": "9fe19dcc6923e4b6133bdedafb33658bf37c9ab7" }, "dnspython": { "hashes": [ @@ -310,7 +324,7 @@ "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], - "markers": "python_full_version >= '3.5.0'", + "markers": "python_version >= '3.5'", "version": "==3.3" }, "isodate": { @@ -421,47 +435,67 @@ }, "pillow": { "hashes": [ - "sha256:01ce45deec9df310cbbee11104bae1a2a43308dd9c317f99235b6d3080ddd66e", - "sha256:0c51cb9edac8a5abd069fd0758ac0a8bfe52c261ee0e330f363548aca6893595", - "sha256:17869489de2fce6c36690a0c721bd3db176194af5f39249c1ac56d0bb0fcc512", - "sha256:21dee8466b42912335151d24c1665fcf44dc2ee47e021d233a40c3ca5adae59c", - "sha256:25023a6209a4d7c42154073144608c9a71d3512b648a2f5d4465182cb93d3477", - "sha256:255c9d69754a4c90b0ee484967fc8818c7ff8311c6dddcc43a4340e10cd1636a", - "sha256:35be4a9f65441d9982240e6966c1eaa1c654c4e5e931eaf580130409e31804d4", - "sha256:3f42364485bfdab19c1373b5cd62f7c5ab7cc052e19644862ec8f15bb8af289e", - "sha256:3fddcdb619ba04491e8f771636583a7cc5a5051cd193ff1aa1ee8616d2a692c5", - "sha256:463acf531f5d0925ca55904fa668bb3461c3ef6bc779e1d6d8a488092bdee378", - "sha256:4fe29a070de394e449fd88ebe1624d1e2d7ddeed4c12e0b31624561b58948d9a", - "sha256:55dd1cf09a1fd7c7b78425967aacae9b0d70125f7d3ab973fadc7b5abc3de652", - "sha256:5a3ecc026ea0e14d0ad7cd990ea7f48bfcb3eb4271034657dc9d06933c6629a7", - "sha256:5cfca31ab4c13552a0f354c87fbd7f162a4fafd25e6b521bba93a57fe6a3700a", - "sha256:66822d01e82506a19407d1afc104c3fcea3b81d5eb11485e593ad6b8492f995a", - "sha256:69e5ddc609230d4408277af135c5b5c8fe7a54b2bdb8ad7c5100b86b3aab04c6", - "sha256:6b6d4050b208c8ff886fd3db6690bf04f9a48749d78b41b7a5bf24c236ab0165", - "sha256:7a053bd4d65a3294b153bdd7724dce864a1d548416a5ef61f6d03bf149205160", - "sha256:82283af99c1c3a5ba1da44c67296d5aad19f11c535b551a5ae55328a317ce331", - "sha256:8782189c796eff29dbb37dd87afa4ad4d40fc90b2742704f94812851b725964b", - "sha256:8d79c6f468215d1a8415aa53d9868a6b40c4682165b8cb62a221b1baa47db458", - "sha256:97bda660702a856c2c9e12ec26fc6d187631ddfd896ff685814ab21ef0597033", - "sha256:a325ac71914c5c043fa50441b36606e64a10cd262de12f7a179620f579752ff8", - "sha256:a336a4f74baf67e26f3acc4d61c913e378e931817cd1e2ef4dfb79d3e051b481", - "sha256:a598d8830f6ef5501002ae85c7dbfcd9c27cc4efc02a1989369303ba85573e58", - "sha256:a5eaf3b42df2bcda61c53a742ee2c6e63f777d0e085bbc6b2ab7ed57deb13db7", - "sha256:aea7ce61328e15943d7b9eaca87e81f7c62ff90f669116f857262e9da4057ba3", - "sha256:af79d3fde1fc2e33561166d62e3b63f0cc3e47b5a3a2e5fea40d4917754734ea", - "sha256:c24f718f9dd73bb2b31a6201e6db5ea4a61fdd1d1c200f43ee585fc6dcd21b34", - "sha256:c5b0ff59785d93b3437c3703e3c64c178aabada51dea2a7f2c5eccf1bcf565a3", - "sha256:c7110ec1701b0bf8df569a7592a196c9d07c764a0a74f65471ea56816f10e2c8", - "sha256:c870193cce4b76713a2b29be5d8327c8ccbe0d4a49bc22968aa1e680930f5581", - "sha256:c9efef876c21788366ea1f50ecb39d5d6f65febe25ad1d4c0b8dff98843ac244", - "sha256:de344bcf6e2463bb25179d74d6e7989e375f906bcec8cb86edb8b12acbc7dfef", - "sha256:eb1b89b11256b5b6cad5e7593f9061ac4624f7651f7a8eb4dfa37caa1dfaa4d0", - "sha256:ed742214068efa95e9844c2d9129e209ed63f61baa4d54dbf4cf8b5e2d30ccf2", - "sha256:f401ed2bbb155e1ade150ccc63db1a4f6c1909d3d378f7d1235a44e90d75fb97", - "sha256:fb89397013cf302f282f0fc998bb7abf11d49dcff72c8ecb320f76ea6e2c5717" + "sha256:0030fdbd926fb85844b8b92e2f9449ba89607231d3dd597a21ae72dc7fe26927", + "sha256:030e3460861488e249731c3e7ab59b07c7853838ff3b8e16aac9561bb345da14", + "sha256:0ed2c4ef2451de908c90436d6e8092e13a43992f1860275b4d8082667fbb2ffc", + "sha256:136659638f61a251e8ed3b331fc6ccd124590eeff539de57c5f80ef3a9594e58", + "sha256:13b725463f32df1bfeacbf3dd197fb358ae8ebcd8c5548faa75126ea425ccb60", + "sha256:1536ad017a9f789430fb6b8be8bf99d2f214c76502becc196c6f2d9a75b01b76", + "sha256:15928f824870535c85dbf949c09d6ae7d3d6ac2d6efec80f3227f73eefba741c", + "sha256:17d4cafe22f050b46d983b71c707162d63d796a1235cdf8b9d7a112e97b15bac", + "sha256:1802f34298f5ba11d55e5bb09c31997dc0c6aed919658dfdf0198a2fe75d5490", + "sha256:1cc1d2451e8a3b4bfdb9caf745b58e6c7a77d2e469159b0d527a4554d73694d1", + "sha256:1fd6f5e3c0e4697fa7eb45b6e93996299f3feee73a3175fa451f49a74d092b9f", + "sha256:254164c57bab4b459f14c64e93df11eff5ded575192c294a0c49270f22c5d93d", + "sha256:2ad0d4df0f5ef2247e27fc790d5c9b5a0af8ade9ba340db4a73bb1a4a3e5fb4f", + "sha256:2c58b24e3a63efd22554c676d81b0e57f80e0a7d3a5874a7e14ce90ec40d3069", + "sha256:2d33a11f601213dcd5718109c09a52c2a1c893e7461f0be2d6febc2879ec2402", + "sha256:337a74fd2f291c607d220c793a8135273c4c2ab001b03e601c36766005f36885", + "sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e", + "sha256:3d1f14f5f691f55e1b47f824ca4fdcb4b19b4323fe43cc7bb105988cad7496be", + "sha256:408673ed75594933714482501fe97e055a42996087eeca7e5d06e33218d05aa8", + "sha256:4134d3f1ba5f15027ff5c04296f13328fecd46921424084516bdb1b2548e66ff", + "sha256:4ad2f835e0ad81d1689f1b7e3fbac7b01bb8777d5a985c8962bedee0cc6d43da", + "sha256:50dff9cc21826d2977ef2d2a205504034e3a4563ca6f5db739b0d1026658e004", + "sha256:510cef4a3f401c246cfd8227b300828715dd055463cdca6176c2e4036df8bd4f", + "sha256:5aed7dde98403cd91d86a1115c78d8145c83078e864c1de1064f52e6feb61b20", + "sha256:69bd1a15d7ba3694631e00df8de65a8cb031911ca11f44929c97fe05eb9b6c1d", + "sha256:6bf088c1ce160f50ea40764f825ec9b72ed9da25346216b91361eef8ad1b8f8c", + "sha256:6e8c66f70fb539301e064f6478d7453e820d8a2c631da948a23384865cd95544", + "sha256:727dd1389bc5cb9827cbd1f9d40d2c2a1a0c9b32dd2261db522d22a604a6eec9", + "sha256:74a04183e6e64930b667d321524e3c5361094bb4af9083db5c301db64cd341f3", + "sha256:75e636fd3e0fb872693f23ccb8a5ff2cd578801251f3a4f6854c6a5d437d3c04", + "sha256:7761afe0126d046974a01e030ae7529ed0ca6a196de3ec6937c11df0df1bc91c", + "sha256:7888310f6214f19ab2b6df90f3f06afa3df7ef7355fc025e78a3044737fab1f5", + "sha256:7b0554af24df2bf96618dac71ddada02420f946be943b181108cac55a7a2dcd4", + "sha256:7c7b502bc34f6e32ba022b4a209638f9e097d7a9098104ae420eb8186217ebbb", + "sha256:808add66ea764ed97d44dda1ac4f2cfec4c1867d9efb16a33d158be79f32b8a4", + "sha256:831e648102c82f152e14c1a0938689dbb22480c548c8d4b8b248b3e50967b88c", + "sha256:93689632949aff41199090eff5474f3990b6823404e45d66a5d44304e9cdc467", + "sha256:96b5e6874431df16aee0c1ba237574cb6dff1dcb173798faa6a9d8b399a05d0e", + "sha256:9a54614049a18a2d6fe156e68e188da02a046a4a93cf24f373bffd977e943421", + "sha256:a138441e95562b3c078746a22f8fca8ff1c22c014f856278bdbdd89ca36cff1b", + "sha256:a647c0d4478b995c5e54615a2e5360ccedd2f85e70ab57fbe817ca613d5e63b8", + "sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb", + "sha256:ad2277b185ebce47a63f4dc6302e30f05762b688f8dc3de55dbae4651872cdf3", + "sha256:b6d5e92df2b77665e07ddb2e4dbd6d644b78e4c0d2e9272a852627cdba0d75cf", + "sha256:bc431b065722a5ad1dfb4df354fb9333b7a582a5ee39a90e6ffff688d72f27a1", + "sha256:bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a", + "sha256:c79698d4cd9318d9481d89a77e2d3fcaeff5486be641e60a4b49f3d2ecca4e28", + "sha256:cb6259196a589123d755380b65127ddc60f4c64b21fc3bb46ce3a6ea663659b0", + "sha256:d5b87da55a08acb586bad5c3aa3b86505f559b84f39035b233d5bf844b0834b1", + "sha256:dcd7b9c7139dc8258d164b55696ecd16c04607f1cc33ba7af86613881ffe4ac8", + "sha256:dfe4c1fedfde4e2fbc009d5ad420647f7730d719786388b7de0999bf32c0d9fd", + "sha256:ea98f633d45f7e815db648fd7ff0f19e328302ac36427343e4432c84432e7ff4", + "sha256:ec52c351b35ca269cb1f8069d610fc45c5bd38c3e91f9ab4cbbf0aebc136d9c8", + "sha256:eef7592281f7c174d3d6cbfbb7ee5984a671fcd77e3fc78e973d492e9bf0eb3f", + "sha256:f07f1f00e22b231dd3d9b9208692042e29792d6bd4f6639415d2f23158a80013", + "sha256:f3fac744f9b540148fa7715a435d2283b71f68bfb6d4aae24482a890aed18b59", + "sha256:fa768eff5f9f958270b081bb33581b4b569faabf8774726b283edb06617101dc", + "sha256:fac2d65901fb0fdf20363fbd345c01958a742f2dc62a8dd4495af66e3ff502a4" ], "markers": "python_version >= '3.7'", - "version": "==9.1.0" + "version": "==9.2.0" }, "pycparser": { "hashes": [ @@ -471,9 +505,7 @@ "version": "==2.21" }, "pymongo": { - "extras": [ - "srv" - ], + "extras": [], "hashes": [ "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", @@ -782,11 +814,11 @@ }, "colorama": { "hashes": [ - "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b", - "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2" + "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da", + "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4" ], "index": "pypi", - "version": "==0.4.4" + "version": "==0.4.5" }, "gitdb": { "hashes": [ @@ -878,11 +910,11 @@ }, "pbr": { "hashes": [ - "sha256:27108648368782d07bbf1cb468ad2e2eeef29086affd14087a6d04b7de8af4ec", - "sha256:66bc5a34912f408bb3925bf21231cb6f59206267b7f63f3503ef865c1a292e25" + "sha256:e547125940bcc052856ded43be8e101f63828c2d94239ffbe2b327ba3d5ccf0a", + "sha256:e8dca2f4b43560edef58813969f52a56cef023146cbb8931626db80e6c1c4308" ], "markers": "python_version >= '2.6'", - "version": "==5.8.1" + "version": "==5.9.0" }, "platformdirs": { "hashes": [ @@ -941,11 +973,11 @@ }, "setuptools": { "hashes": [ - "sha256:26ead7d1f93efc0f8c804d9fafafbe4a44b179580a7105754b245155f9af05a8", - "sha256:47c7b0c0f8fc10eec4cf1e71c6fdadf8decaa74ffa087e68cd1c20db7ad6a592" + "sha256:16923d366ced322712c71ccb97164d07472abeecd13f3a6c283f6d5d26722793", + "sha256:db3b8e2f922b2a910a29804776c643ea609badb6a32c4bcc226fd4fd902cce65" ], "markers": "python_version >= '3.7'", - "version": "==62.1.0" + "version": "==63.1.0" }, "smmap": { "hashes": [ From a93d81eac495df7fe26a6aabc04c88019f35b3b2 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 6 Jul 2022 01:18:57 +0800 Subject: [PATCH 110/225] fix typo https://github.com/kyb3r/modmail/pull/3161#discussion_r912533027 --- core/clients.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/clients.py b/core/clients.py index df7e1b7b56..eebe3bcff6 100644 --- a/core/clients.py +++ b/core/clients.py @@ -90,7 +90,7 @@ async def request( payload: dict = None, headers: dict = None, return_response: bool = False, - read_before_return: bool = True, + read_before_return: bool = False, ) -> Union[ClientResponse, Dict[str, Any], str]: """ Makes a HTTP request. From ee47143fd01cbc204275397c46b67c7e17efd341 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 6 Jul 2022 01:19:47 +0800 Subject: [PATCH 111/225] update version dv16 --- bot.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index 3723e94325..f3d7198428 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev15" +__version__ = "4.0.0-dev16" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 8b306b2d18..7c1dc0e952 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev15' +version = '4.0.0-dev16' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 07c6dc12bec2ae0a4735c5965ee00d686622a21e Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Fri, 22 Jul 2022 23:38:18 +0530 Subject: [PATCH 112/225] Prevents loaded cogs from being loaded again Fixes #3171 Haven't tested this, but pretty sure it should work. --- bot.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bot.py b/bot.py index f3d7198428..5a1c0a18a5 100644 --- a/bot.py +++ b/bot.py @@ -157,6 +157,8 @@ def startup(self): async def load_extensions(self): for cog in self.loaded_cogs: + if cog in self.bot.extensions: + continue logger.debug("Loading %s.", cog) try: await self.load_extension(cog) From f274a79b98fdd67cafdd3b00fd3888639b9da80f Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Sat, 23 Jul 2022 19:03:26 +0530 Subject: [PATCH 113/225] Update bot.py --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 5a1c0a18a5..bcb0685f08 100644 --- a/bot.py +++ b/bot.py @@ -157,7 +157,7 @@ def startup(self): async def load_extensions(self): for cog in self.loaded_cogs: - if cog in self.bot.extensions: + if cog in self.extensions: continue logger.debug("Loading %s.", cog) try: From c7072eff17c9a35dc9fbf44855970df0da66ea1f Mon Sep 17 00:00:00 2001 From: Stephen <48072084+StephenDaDev@users.noreply.github.com> Date: Sat, 6 Aug 2022 19:20:00 -0400 Subject: [PATCH 114/225] Add aliases to snippet add command. --- cogs/modmail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index deb29d160d..7fc9e5b975 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -193,7 +193,7 @@ async def snippet_raw(self, ctx, *, name: str.lower): return await ctx.send(embed=embed) - @snippet.command(name="add") + @snippet.command(name="add", aliases=["create", "make"]) @checks.has_permissions(PermissionLevel.SUPPORTER) async def snippet_add(self, ctx, name: str.lower, *, value: commands.clean_content): """ From 7bc33401aa56523fc60d9345fe222ef90f2df4cb Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Aug 2022 22:17:15 +0800 Subject: [PATCH 115/225] Bump dpy-2.0 --- CHANGELOG.md | 2 +- Pipfile | 2 +- Pipfile.lock | 307 ++++++++++++++++++++++++------------------------- bot.py | 6 +- pyproject.toml | 2 +- 5 files changed, 154 insertions(+), 165 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 054f126f7f..0070eecf0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Breaking - Modmail now requires [`Message Content` privileged intent](https://support-dev.discord.com/hc/en-us/articles/4404772028055-Message-Content-Privileged-Intent-for-Verified-Bots). -- Upgraded to discord.py v2.0 master ([internal changes](https://gist.github.com/apple502j/f75b4f24652f04de85c7084ffd73ec58), [GH #2990](https://github.com/kyb3r/modmail/issues/2990)). +- Upgraded to discord.py v2.0 ([internal changes](https://discordpy.readthedocs.io/en/latest/migrating.html), [GH #2990](https://github.com/kyb3r/modmail/issues/2990)). - Python 3.8 or higher is required. - Asyncio changes ([gist](https://gist.github.com/Rapptz/6706e1c8f23ac27c98cee4dd985c8120)) diff --git a/Pipfile b/Pipfile index 82ec35158d..12de060a72 100644 --- a/Pipfile +++ b/Pipfile @@ -12,7 +12,7 @@ typing-extensions = "==4.2.0" [packages] aiohttp = "==3.8.1" colorama = "~=0.4.5" -"discord.py" = {ref = "9fe19dcc6923e4b6133bdedafb33658bf37c9ab7", git = "https://github.com/Rapptz/discord.py.git"} +"discord.py" = "==2.0.0" emoji = "==1.7.0" isodate = "~=0.6.0" motor = "==2.5.1" diff --git a/Pipfile.lock b/Pipfile.lock index 87a2f247fc..ed19b5883c 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "89578b9ae8a9a0b580e0af21767bd2f062388ad43c9bdc6e5d113de91361bea3" + "sha256": "aa752693f18b9d6058209883bdcece4e37a1a7a62a5fd564d64e551d91ea49f4" }, "pipfile-spec": 6, "requires": {}, @@ -110,11 +110,11 @@ }, "attrs": { "hashes": [ - "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", - "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd" + "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6", + "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==21.4.0" + "markers": "python_version >= '3.5'", + "version": "==22.1.0" }, "cairocffi": { "hashes": [ @@ -201,11 +201,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", - "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" + "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", + "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" ], "markers": "python_version >= '3.6'", - "version": "==2.1.0" + "version": "==2.1.1" }, "colorama": { "hashes": [ @@ -231,13 +231,13 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==0.7.1" }, - "discord-py": { - "git": "https://github.com/Rapptz/discord.py.git", - "ref": "9fe19dcc6923e4b6133bdedafb33658bf37c9ab7" - }, "discord.py": { - "git": "https://github.com/Rapptz/discord.py.git", - "ref": "9fe19dcc6923e4b6133bdedafb33658bf37c9ab7" + "hashes": [ + "sha256:18b06870bdc85d29e0d55f4a4b2abe9d7cdae2b197e23d49f82886ba27ba1aec", + "sha256:c36f26935938194c3465c2abf8ecfbbf5560c50b189f1b746d6f00d1e78c0d3b" + ], + "index": "pypi", + "version": "==2.0.0" }, "dnspython": { "hashes": [ @@ -256,68 +256,68 @@ }, "frozenlist": { "hashes": [ - "sha256:006d3595e7d4108a12025ddf415ae0f6c9e736e726a5db0183326fd191b14c5e", - "sha256:01a73627448b1f2145bddb6e6c2259988bb8aee0fb361776ff8604b99616cd08", - "sha256:03a7dd1bfce30216a3f51a84e6dd0e4a573d23ca50f0346634916ff105ba6e6b", - "sha256:0437fe763fb5d4adad1756050cbf855bbb2bf0d9385c7bb13d7a10b0dd550486", - "sha256:04cb491c4b1c051734d41ea2552fde292f5f3a9c911363f74f39c23659c4af78", - "sha256:0c36e78b9509e97042ef869c0e1e6ef6429e55817c12d78245eb915e1cca7468", - "sha256:25af28b560e0c76fa41f550eacb389905633e7ac02d6eb3c09017fa1c8cdfde1", - "sha256:2fdc3cd845e5a1f71a0c3518528bfdbfe2efaf9886d6f49eacc5ee4fd9a10953", - "sha256:30530930410855c451bea83f7b272fb1c495ed9d5cc72895ac29e91279401db3", - "sha256:31977f84828b5bb856ca1eb07bf7e3a34f33a5cddce981d880240ba06639b94d", - "sha256:3c62964192a1c0c30b49f403495911298810bada64e4f03249ca35a33ca0417a", - "sha256:3f7c935c7b58b0d78c0beea0c7358e165f95f1fd8a7e98baa40d22a05b4a8141", - "sha256:40dff8962b8eba91fd3848d857203f0bd704b5f1fa2b3fc9af64901a190bba08", - "sha256:40ec383bc194accba825fbb7d0ef3dda5736ceab2375462f1d8672d9f6b68d07", - "sha256:436496321dad302b8b27ca955364a439ed1f0999311c393dccb243e451ff66aa", - "sha256:4406cfabef8f07b3b3af0f50f70938ec06d9f0fc26cbdeaab431cbc3ca3caeaa", - "sha256:45334234ec30fc4ea677f43171b18a27505bfb2dba9aca4398a62692c0ea8868", - "sha256:47be22dc27ed933d55ee55845d34a3e4e9f6fee93039e7f8ebadb0c2f60d403f", - "sha256:4a44ebbf601d7bac77976d429e9bdb5a4614f9f4027777f9e54fd765196e9d3b", - "sha256:4eda49bea3602812518765810af732229b4291d2695ed24a0a20e098c45a707b", - "sha256:57f4d3f03a18facacb2a6bcd21bccd011e3b75d463dc49f838fd699d074fabd1", - "sha256:603b9091bd70fae7be28bdb8aa5c9990f4241aa33abb673390a7f7329296695f", - "sha256:65bc6e2fece04e2145ab6e3c47428d1bbc05aede61ae365b2c1bddd94906e478", - "sha256:691ddf6dc50480ce49f68441f1d16a4c3325887453837036e0fb94736eae1e58", - "sha256:6983a31698490825171be44ffbafeaa930ddf590d3f051e397143a5045513b01", - "sha256:6a202458d1298ced3768f5a7d44301e7c86defac162ace0ab7434c2e961166e8", - "sha256:6eb275c6385dd72594758cbe96c07cdb9bd6becf84235f4a594bdf21e3596c9d", - "sha256:754728d65f1acc61e0f4df784456106e35afb7bf39cfe37227ab00436fb38676", - "sha256:768efd082074bb203c934e83a61654ed4931ef02412c2fbdecea0cff7ecd0274", - "sha256:772965f773757a6026dea111a15e6e2678fbd6216180f82a48a40b27de1ee2ab", - "sha256:871d42623ae15eb0b0e9df65baeee6976b2e161d0ba93155411d58ff27483ad8", - "sha256:88aafd445a233dbbf8a65a62bc3249a0acd0d81ab18f6feb461cc5a938610d24", - "sha256:8c905a5186d77111f02144fab5b849ab524f1e876a1e75205cd1386a9be4b00a", - "sha256:8cf829bd2e2956066dd4de43fd8ec881d87842a06708c035b37ef632930505a2", - "sha256:92e650bd09b5dda929523b9f8e7f99b24deac61240ecc1a32aeba487afcd970f", - "sha256:93641a51f89473837333b2f8100f3f89795295b858cd4c7d4a1f18e299dc0a4f", - "sha256:94c7a8a9fc9383b52c410a2ec952521906d355d18fccc927fca52ab575ee8b93", - "sha256:9f892d6a94ec5c7b785e548e42722e6f3a52f5f32a8461e82ac3e67a3bd073f1", - "sha256:acb267b09a509c1df5a4ca04140da96016f40d2ed183cdc356d237286c971b51", - "sha256:adac9700675cf99e3615eb6a0eb5e9f5a4143c7d42c05cea2e7f71c27a3d0846", - "sha256:aff388be97ef2677ae185e72dc500d19ecaf31b698986800d3fc4f399a5e30a5", - "sha256:b5009062d78a8c6890d50b4e53b0ddda31841b3935c1937e2ed8c1bda1c7fb9d", - "sha256:b684c68077b84522b5c7eafc1dc735bfa5b341fb011d5552ebe0968e22ed641c", - "sha256:b9e3e9e365991f8cc5f5edc1fd65b58b41d0514a6a7ad95ef5c7f34eb49b3d3e", - "sha256:bd89acd1b8bb4f31b47072615d72e7f53a948d302b7c1d1455e42622de180eae", - "sha256:bde99812f237f79eaf3f04ebffd74f6718bbd216101b35ac7955c2d47c17da02", - "sha256:c6c321dd013e8fc20735b92cb4892c115f5cdb82c817b1e5b07f6b95d952b2f0", - "sha256:ce6f2ba0edb7b0c1d8976565298ad2deba6f8064d2bebb6ffce2ca896eb35b0b", - "sha256:d2257aaba9660f78c7b1d8fea963b68f3feffb1a9d5d05a18401ca9eb3e8d0a3", - "sha256:d26b650b71fdc88065b7a21f8ace70175bcf3b5bdba5ea22df4bfd893e795a3b", - "sha256:d6d32ff213aef0fd0bcf803bffe15cfa2d4fde237d1d4838e62aec242a8362fa", - "sha256:e1e26ac0a253a2907d654a37e390904426d5ae5483150ce3adedb35c8c06614a", - "sha256:e30b2f9683812eb30cf3f0a8e9f79f8d590a7999f731cf39f9105a7c4a39489d", - "sha256:e84cb61b0ac40a0c3e0e8b79c575161c5300d1d89e13c0e02f76193982f066ed", - "sha256:e982878792c971cbd60ee510c4ee5bf089a8246226dea1f2138aa0bb67aff148", - "sha256:f20baa05eaa2bcd5404c445ec51aed1c268d62600362dc6cfe04fae34a424bd9", - "sha256:f7353ba3367473d1d616ee727945f439e027f0bb16ac1a750219a8344d1d5d3c", - "sha256:f96293d6f982c58ebebb428c50163d010c2f05de0cde99fd681bfdc18d4b2dc2", - "sha256:ff9310f05b9d9c5c4dd472983dc956901ee6cb2c3ec1ab116ecdde25f3ce4951" + "sha256:022178b277cb9277d7d3b3f2762d294f15e85cd2534047e68a118c2bb0058f3e", + "sha256:086ca1ac0a40e722d6833d4ce74f5bf1aba2c77cbfdc0cd83722ffea6da52a04", + "sha256:0bc75692fb3770cf2b5856a6c2c9de967ca744863c5e89595df64e252e4b3944", + "sha256:0dde791b9b97f189874d654c55c24bf7b6782343e14909c84beebd28b7217845", + "sha256:12607804084d2244a7bd4685c9d0dca5df17a6a926d4f1967aa7978b1028f89f", + "sha256:19127f8dcbc157ccb14c30e6f00392f372ddb64a6ffa7106b26ff2196477ee9f", + "sha256:1b51eb355e7f813bcda00276b0114c4172872dc5fb30e3fea059b9367c18fbcb", + "sha256:1e1cf7bc8cbbe6ce3881863671bac258b7d6bfc3706c600008925fb799a256e2", + "sha256:219a9676e2eae91cb5cc695a78b4cb43d8123e4160441d2b6ce8d2c70c60e2f3", + "sha256:2743bb63095ef306041c8f8ea22bd6e4d91adabf41887b1ad7886c4c1eb43d5f", + "sha256:2af6f7a4e93f5d08ee3f9152bce41a6015b5cf87546cb63872cc19b45476e98a", + "sha256:31b44f1feb3630146cffe56344704b730c33e042ffc78d21f2125a6a91168131", + "sha256:31bf9539284f39ff9398deabf5561c2b0da5bb475590b4e13dd8b268d7a3c5c1", + "sha256:35c3d79b81908579beb1fb4e7fcd802b7b4921f1b66055af2578ff7734711cfa", + "sha256:3a735e4211a04ccfa3f4833547acdf5d2f863bfeb01cfd3edaffbc251f15cec8", + "sha256:42719a8bd3792744c9b523674b752091a7962d0d2d117f0b417a3eba97d1164b", + "sha256:49459f193324fbd6413e8e03bd65789e5198a9fa3095e03f3620dee2f2dabff2", + "sha256:4c0c99e31491a1d92cde8648f2e7ccad0e9abb181f6ac3ddb9fc48b63301808e", + "sha256:52137f0aea43e1993264a5180c467a08a3e372ca9d378244c2d86133f948b26b", + "sha256:526d5f20e954d103b1d47232e3839f3453c02077b74203e43407b962ab131e7b", + "sha256:53b2b45052e7149ee8b96067793db8ecc1ae1111f2f96fe1f88ea5ad5fd92d10", + "sha256:572ce381e9fe027ad5e055f143763637dcbac2542cfe27f1d688846baeef5170", + "sha256:58fb94a01414cddcdc6839807db77ae8057d02ddafc94a42faee6004e46c9ba8", + "sha256:5e77a8bd41e54b05e4fb2708dc6ce28ee70325f8c6f50f3df86a44ecb1d7a19b", + "sha256:5f271c93f001748fc26ddea409241312a75e13466b06c94798d1a341cf0e6989", + "sha256:5f63c308f82a7954bf8263a6e6de0adc67c48a8b484fab18ff87f349af356efd", + "sha256:61d7857950a3139bce035ad0b0945f839532987dfb4c06cfe160254f4d19df03", + "sha256:61e8cb51fba9f1f33887e22488bad1e28dd8325b72425f04517a4d285a04c519", + "sha256:625d8472c67f2d96f9a4302a947f92a7adbc1e20bedb6aff8dbc8ff039ca6189", + "sha256:6e19add867cebfb249b4e7beac382d33215d6d54476bb6be46b01f8cafb4878b", + "sha256:717470bfafbb9d9be624da7780c4296aa7935294bd43a075139c3d55659038ca", + "sha256:74140933d45271c1a1283f708c35187f94e1256079b3c43f0c2267f9db5845ff", + "sha256:74e6b2b456f21fc93ce1aff2b9728049f1464428ee2c9752a4b4f61e98c4db96", + "sha256:9494122bf39da6422b0972c4579e248867b6b1b50c9b05df7e04a3f30b9a413d", + "sha256:94e680aeedc7fd3b892b6fa8395b7b7cc4b344046c065ed4e7a1e390084e8cb5", + "sha256:97d9e00f3ac7c18e685320601f91468ec06c58acc185d18bb8e511f196c8d4b2", + "sha256:9c6ef8014b842f01f5d2b55315f1af5cbfde284eb184075c189fd657c2fd8204", + "sha256:a027f8f723d07c3f21963caa7d585dcc9b089335565dabe9c814b5f70c52705a", + "sha256:a718b427ff781c4f4e975525edb092ee2cdef6a9e7bc49e15063b088961806f8", + "sha256:ab386503f53bbbc64d1ad4b6865bf001414930841a870fc97f1546d4d133f141", + "sha256:ab6fa8c7871877810e1b4e9392c187a60611fbf0226a9e0b11b7b92f5ac72792", + "sha256:b47d64cdd973aede3dd71a9364742c542587db214e63b7529fbb487ed67cddd9", + "sha256:b499c6abe62a7a8d023e2c4b2834fce78a6115856ae95522f2f974139814538c", + "sha256:bbb1a71b1784e68870800b1bc9f3313918edc63dbb8f29fbd2e767ce5821696c", + "sha256:c3b31180b82c519b8926e629bf9f19952c743e089c41380ddca5db556817b221", + "sha256:c56c299602c70bc1bb5d1e75f7d8c007ca40c9d7aebaf6e4ba52925d88ef826d", + "sha256:c92deb5d9acce226a501b77307b3b60b264ca21862bd7d3e0c1f3594022f01bc", + "sha256:cc2f3e368ee5242a2cbe28323a866656006382872c40869b49b265add546703f", + "sha256:d82bed73544e91fb081ab93e3725e45dd8515c675c0e9926b4e1f420a93a6ab9", + "sha256:da1cdfa96425cbe51f8afa43e392366ed0b36ce398f08b60de6b97e3ed4affef", + "sha256:da5ba7b59d954f1f214d352308d1d86994d713b13edd4b24a556bcc43d2ddbc3", + "sha256:e0c8c803f2f8db7217898d11657cb6042b9b0553a997c4a0601f48a691480fab", + "sha256:ee4c5120ddf7d4dd1eaf079af3af7102b56d919fa13ad55600a4e0ebe532779b", + "sha256:eee0c5ecb58296580fc495ac99b003f64f82a74f9576a244d04978a7e97166db", + "sha256:f5abc8b4d0c5b556ed8cd41490b606fe99293175a82b98e652c3f2711b452988", + "sha256:f810e764617b0748b49a731ffaa525d9bb36ff38332411704c2400125af859a6", + "sha256:f89139662cc4e65a4813f4babb9ca9544e42bddb823d2ec434e18dad582543bc", + "sha256:fa47319a10e0a076709644a0efbcaab9e91902c8bd8ef74c6adb19d320f69b83", + "sha256:fabb953ab913dadc1ff9dcc3a7a7d3dc6a92efab3a0373989b8063347f8705be" ], "markers": "python_version >= '3.7'", - "version": "==1.3.0" + "version": "==1.3.1" }, "idna": { "hashes": [ @@ -505,7 +505,9 @@ "version": "==2.21" }, "pymongo": { - "extras": [], + "extras": [ + "srv" + ], "hashes": [ "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", @@ -681,81 +683,68 @@ }, "yarl": { "hashes": [ - "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac", - "sha256:0cba38120db72123db7c58322fa69e3c0efa933040ffb586c3a87c063ec7cae8", - "sha256:167ab7f64e409e9bdd99333fe8c67b5574a1f0495dcfd905bc7454e766729b9e", - "sha256:1be4bbb3d27a4e9aa5f3df2ab61e3701ce8fcbd3e9846dbce7c033a7e8136746", - "sha256:1ca56f002eaf7998b5fcf73b2421790da9d2586331805f38acd9997743114e98", - "sha256:1d3d5ad8ea96bd6d643d80c7b8d5977b4e2fb1bab6c9da7322616fd26203d125", - "sha256:1eb6480ef366d75b54c68164094a6a560c247370a68c02dddb11f20c4c6d3c9d", - "sha256:1edc172dcca3f11b38a9d5c7505c83c1913c0addc99cd28e993efeaafdfaa18d", - "sha256:211fcd65c58bf250fb994b53bc45a442ddc9f441f6fec53e65de8cba48ded986", - "sha256:29e0656d5497733dcddc21797da5a2ab990c0cb9719f1f969e58a4abac66234d", - "sha256:368bcf400247318382cc150aaa632582d0780b28ee6053cd80268c7e72796dec", - "sha256:39d5493c5ecd75c8093fa7700a2fb5c94fe28c839c8e40144b7ab7ccba6938c8", - "sha256:3abddf0b8e41445426d29f955b24aeecc83fa1072be1be4e0d194134a7d9baee", - "sha256:3bf8cfe8856708ede6a73907bf0501f2dc4e104085e070a41f5d88e7faf237f3", - "sha256:3ec1d9a0d7780416e657f1e405ba35ec1ba453a4f1511eb8b9fbab81cb8b3ce1", - "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd", - "sha256:52690eb521d690ab041c3919666bea13ab9fbff80d615ec16fa81a297131276b", - "sha256:534b047277a9a19d858cde163aba93f3e1677d5acd92f7d10ace419d478540de", - "sha256:580c1f15500e137a8c37053e4cbf6058944d4c114701fa59944607505c2fe3a0", - "sha256:59218fef177296451b23214c91ea3aba7858b4ae3306dde120224cfe0f7a6ee8", - "sha256:5ba63585a89c9885f18331a55d25fe81dc2d82b71311ff8bd378fc8004202ff6", - "sha256:5bb7d54b8f61ba6eee541fba4b83d22b8a046b4ef4d8eb7f15a7e35db2e1e245", - "sha256:6152224d0a1eb254f97df3997d79dadd8bb2c1a02ef283dbb34b97d4f8492d23", - "sha256:67e94028817defe5e705079b10a8438b8cb56e7115fa01640e9c0bb3edf67332", - "sha256:695ba021a9e04418507fa930d5f0704edbce47076bdcfeeaba1c83683e5649d1", - "sha256:6a1a9fe17621af43e9b9fcea8bd088ba682c8192d744b386ee3c47b56eaabb2c", - "sha256:6ab0c3274d0a846840bf6c27d2c60ba771a12e4d7586bf550eefc2df0b56b3b4", - "sha256:6feca8b6bfb9eef6ee057628e71e1734caf520a907b6ec0d62839e8293e945c0", - "sha256:737e401cd0c493f7e3dd4db72aca11cfe069531c9761b8ea474926936b3c57c8", - "sha256:788713c2896f426a4e166b11f4ec538b5736294ebf7d5f654ae445fd44270832", - "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58", - "sha256:8300401dc88cad23f5b4e4c1226f44a5aa696436a4026e456fe0e5d2f7f486e6", - "sha256:87f6e082bce21464857ba58b569370e7b547d239ca22248be68ea5d6b51464a1", - "sha256:89ccbf58e6a0ab89d487c92a490cb5660d06c3a47ca08872859672f9c511fc52", - "sha256:8b0915ee85150963a9504c10de4e4729ae700af11df0dc5550e6587ed7891e92", - "sha256:8cce6f9fa3df25f55521fbb5c7e4a736683148bcc0c75b21863789e5185f9185", - "sha256:95a1873b6c0dd1c437fb3bb4a4aaa699a48c218ac7ca1e74b0bee0ab16c7d60d", - "sha256:9b4c77d92d56a4c5027572752aa35082e40c561eec776048330d2907aead891d", - "sha256:9bfcd43c65fbb339dc7086b5315750efa42a34eefad0256ba114cd8ad3896f4b", - "sha256:9c1f083e7e71b2dd01f7cd7434a5f88c15213194df38bc29b388ccdf1492b739", - "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05", - "sha256:a467a431a0817a292121c13cbe637348b546e6ef47ca14a790aa2fa8cc93df63", - "sha256:aa32aaa97d8b2ed4e54dc65d241a0da1c627454950f7d7b1f95b13985afd6c5d", - "sha256:ac10bbac36cd89eac19f4e51c032ba6b412b3892b685076f4acd2de18ca990aa", - "sha256:ac35ccde589ab6a1870a484ed136d49a26bcd06b6a1c6397b1967ca13ceb3913", - "sha256:bab827163113177aee910adb1f48ff7af31ee0289f434f7e22d10baf624a6dfe", - "sha256:baf81561f2972fb895e7844882898bda1eef4b07b5b385bcd308d2098f1a767b", - "sha256:bf19725fec28452474d9887a128e98dd67eee7b7d52e932e6949c532d820dc3b", - "sha256:c01a89a44bb672c38f42b49cdb0ad667b116d731b3f4c896f72302ff77d71656", - "sha256:c0910c6b6c31359d2f6184828888c983d54d09d581a4a23547a35f1d0b9484b1", - "sha256:c10ea1e80a697cf7d80d1ed414b5cb8f1eec07d618f54637067ae3c0334133c4", - "sha256:c1164a2eac148d85bbdd23e07dfcc930f2e633220f3eb3c3e2a25f6148c2819e", - "sha256:c145ab54702334c42237a6c6c4cc08703b6aa9b94e2f227ceb3d477d20c36c63", - "sha256:c17965ff3706beedafd458c452bf15bac693ecd146a60a06a214614dc097a271", - "sha256:c19324a1c5399b602f3b6e7db9478e5b1adf5cf58901996fc973fe4fccd73eed", - "sha256:c2a1ac41a6aa980db03d098a5531f13985edcb451bcd9d00670b03129922cd0d", - "sha256:c6ddcd80d79c96eb19c354d9dca95291589c5954099836b7c8d29278a7ec0bda", - "sha256:c9c6d927e098c2d360695f2e9d38870b2e92e0919be07dbe339aefa32a090265", - "sha256:cc8b7a7254c0fc3187d43d6cb54b5032d2365efd1df0cd1749c0c4df5f0ad45f", - "sha256:cff3ba513db55cc6a35076f32c4cdc27032bd075c9faef31fec749e64b45d26c", - "sha256:d260d4dc495c05d6600264a197d9d6f7fc9347f21d2594926202fd08cf89a8ba", - "sha256:d6f3d62e16c10e88d2168ba2d065aa374e3c538998ed04996cd373ff2036d64c", - "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b", - "sha256:dfe4b95b7e00c6635a72e2d00b478e8a28bfb122dc76349a06e20792eb53a523", - "sha256:e39378894ee6ae9f555ae2de332d513a5763276a9265f8e7cbaeb1b1ee74623a", - "sha256:ede3b46cdb719c794427dcce9d8beb4abe8b9aa1e97526cc20de9bd6583ad1ef", - "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95", - "sha256:f44477ae29025d8ea87ec308539f95963ffdc31a82f42ca9deecf2d505242e72", - "sha256:f64394bd7ceef1237cc604b5a89bf748c95982a84bcd3c4bbeb40f685c810794", - "sha256:fc4dd8b01a8112809e6b636b00f487846956402834a7fd59d46d4f4267181c41", - "sha256:fce78593346c014d0d986b7ebc80d782b7f5e19843ca798ed62f8e3ba8728576", - "sha256:fd547ec596d90c8676e369dd8a581a21227fe9b4ad37d0dc7feb4ccf544c2d59" + "sha256:076eede537ab978b605f41db79a56cad2e7efeea2aa6e0fa8f05a26c24a034fb", + "sha256:07b21e274de4c637f3e3b7104694e53260b5fc10d51fb3ec5fed1da8e0f754e3", + "sha256:0ab5a138211c1c366404d912824bdcf5545ccba5b3ff52c42c4af4cbdc2c5035", + "sha256:0c03f456522d1ec815893d85fccb5def01ffaa74c1b16ff30f8aaa03eb21e453", + "sha256:12768232751689c1a89b0376a96a32bc7633c08da45ad985d0c49ede691f5c0d", + "sha256:19cd801d6f983918a3f3a39f3a45b553c015c5aac92ccd1fac619bd74beece4a", + "sha256:1ca7e596c55bd675432b11320b4eacc62310c2145d6801a1f8e9ad160685a231", + "sha256:1e4808f996ca39a6463f45182e2af2fae55e2560be586d447ce8016f389f626f", + "sha256:205904cffd69ae972a1707a1bd3ea7cded594b1d773a0ce66714edf17833cdae", + "sha256:20df6ff4089bc86e4a66e3b1380460f864df3dd9dccaf88d6b3385d24405893b", + "sha256:21ac44b763e0eec15746a3d440f5e09ad2ecc8b5f6dcd3ea8cb4773d6d4703e3", + "sha256:29e256649f42771829974e742061c3501cc50cf16e63f91ed8d1bf98242e5507", + "sha256:2d800b9c2eaf0684c08be5f50e52bfa2aa920e7163c2ea43f4f431e829b4f0fd", + "sha256:2d93a049d29df172f48bcb09acf9226318e712ce67374f893b460b42cc1380ae", + "sha256:31a9a04ecccd6b03e2b0e12e82131f1488dea5555a13a4d32f064e22a6003cfe", + "sha256:3d1a50e461615747dd93c099f297c1994d472b0f4d2db8a64e55b1edf704ec1c", + "sha256:449c957ffc6bc2309e1fbe67ab7d2c1efca89d3f4912baeb8ead207bb3cc1cd4", + "sha256:4a88510731cd8d4befaba5fbd734a7dd914de5ab8132a5b3dde0bbd6c9476c64", + "sha256:4c322cbaa4ed78a8aac89b2174a6df398faf50e5fc12c4c191c40c59d5e28357", + "sha256:5395da939ffa959974577eff2cbfc24b004a2fb6c346918f39966a5786874e54", + "sha256:5587bba41399854703212b87071c6d8638fa6e61656385875f8c6dff92b2e461", + "sha256:56c11efb0a89700987d05597b08a1efcd78d74c52febe530126785e1b1a285f4", + "sha256:5999c4662631cb798496535afbd837a102859568adc67d75d2045e31ec3ac497", + "sha256:59ddd85a1214862ce7c7c66457f05543b6a275b70a65de366030d56159a979f0", + "sha256:6347f1a58e658b97b0a0d1ff7658a03cb79bdbda0331603bed24dd7054a6dea1", + "sha256:6628d750041550c5d9da50bb40b5cf28a2e63b9388bac10fedd4f19236ef4957", + "sha256:6afb336e23a793cd3b6476c30f030a0d4c7539cd81649683b5e0c1b0ab0bf350", + "sha256:6c8148e0b52bf9535c40c48faebb00cb294ee577ca069d21bd5c48d302a83780", + "sha256:76577f13333b4fe345c3704811ac7509b31499132ff0181f25ee26619de2c843", + "sha256:7c0da7e44d0c9108d8b98469338705e07f4bb7dab96dbd8fa4e91b337db42548", + "sha256:7de89c8456525650ffa2bb56a3eee6af891e98f498babd43ae307bd42dca98f6", + "sha256:7ec362167e2c9fd178f82f252b6d97669d7245695dc057ee182118042026da40", + "sha256:7fce6cbc6c170ede0221cc8c91b285f7f3c8b9fe28283b51885ff621bbe0f8ee", + "sha256:85cba594433915d5c9a0d14b24cfba0339f57a2fff203a5d4fd070e593307d0b", + "sha256:8b0af1cf36b93cee99a31a545fe91d08223e64390c5ecc5e94c39511832a4bb6", + "sha256:9130ddf1ae9978abe63808b6b60a897e41fccb834408cde79522feb37fb72fb0", + "sha256:99449cd5366fe4608e7226c6cae80873296dfa0cde45d9b498fefa1de315a09e", + "sha256:9de955d98e02fab288c7718662afb33aab64212ecb368c5dc866d9a57bf48880", + "sha256:a0fb2cb4204ddb456a8e32381f9a90000429489a25f64e817e6ff94879d432fc", + "sha256:a165442348c211b5dea67c0206fc61366212d7082ba8118c8c5c1c853ea4d82e", + "sha256:ab2a60d57ca88e1d4ca34a10e9fb4ab2ac5ad315543351de3a612bbb0560bead", + "sha256:abc06b97407868ef38f3d172762f4069323de52f2b70d133d096a48d72215d28", + "sha256:af887845b8c2e060eb5605ff72b6f2dd2aab7a761379373fd89d314f4752abbf", + "sha256:b19255dde4b4f4c32e012038f2c169bb72e7f081552bea4641cab4d88bc409dd", + "sha256:b3ded839a5c5608eec8b6f9ae9a62cb22cd037ea97c627f38ae0841a48f09eae", + "sha256:c1445a0c562ed561d06d8cbc5c8916c6008a31c60bc3655cdd2de1d3bf5174a0", + "sha256:d0272228fabe78ce00a3365ffffd6f643f57a91043e119c289aaba202f4095b0", + "sha256:d0b51530877d3ad7a8d47b2fff0c8df3b8f3b8deddf057379ba50b13df2a5eae", + "sha256:d0f77539733e0ec2475ddcd4e26777d08996f8cd55d2aef82ec4d3896687abda", + "sha256:d2b8f245dad9e331540c350285910b20dd913dc86d4ee410c11d48523c4fd546", + "sha256:dd032e8422a52e5a4860e062eb84ac94ea08861d334a4bcaf142a63ce8ad4802", + "sha256:de49d77e968de6626ba7ef4472323f9d2e5a56c1d85b7c0e2a190b2173d3b9be", + "sha256:de839c3a1826a909fdbfe05f6fe2167c4ab033f1133757b5936efe2f84904c07", + "sha256:e80ed5a9939ceb6fda42811542f31c8602be336b1fb977bccb012e83da7e4936", + "sha256:ea30a42dc94d42f2ba4d0f7c0ffb4f4f9baa1b23045910c0c32df9c9902cb272", + "sha256:ea513a25976d21733bff523e0ca836ef1679630ef4ad22d46987d04b372d57fc", + "sha256:ed19b74e81b10b592084a5ad1e70f845f0aacb57577018d31de064e71ffa267a", + "sha256:f5af52738e225fcc526ae64071b7e5342abe03f42e0e8918227b38c9aa711e28", + "sha256:fae37373155f5ef9b403ab48af5136ae9851151f7aacd9926251ab26b953118b" ], - "markers": "python_version >= '3.6'", - "version": "==1.7.2" + "markers": "python_version >= '3.7'", + "version": "==1.8.1" } }, "develop": { @@ -910,11 +899,11 @@ }, "pbr": { "hashes": [ - "sha256:e547125940bcc052856ded43be8e101f63828c2d94239ffbe2b327ba3d5ccf0a", - "sha256:e8dca2f4b43560edef58813969f52a56cef023146cbb8931626db80e6c1c4308" + "sha256:cfcc4ff8e698256fc17ea3ff796478b050852585aa5bae79ecd05b2ab7b39b9a", + "sha256:da3e18aac0a3c003e9eea1a81bd23e5a3a75d745670dcf736317b7d966887fdf" ], "markers": "python_version >= '2.6'", - "version": "==5.9.0" + "version": "==5.10.0" }, "platformdirs": { "hashes": [ @@ -973,11 +962,11 @@ }, "setuptools": { "hashes": [ - "sha256:16923d366ced322712c71ccb97164d07472abeecd13f3a6c283f6d5d26722793", - "sha256:db3b8e2f922b2a910a29804776c643ea609badb6a32c4bcc226fd4fd902cce65" + "sha256:7f4bc85450898a09f76ebf28b72fa25bc7111f6c7d665d514a60bba9c75ef2a9", + "sha256:a3ca5857c89f82f5c9410e8508cb32f4872a3bafd4aa7ae122a24ca33bccc750" ], "markers": "python_version >= '3.7'", - "version": "==63.1.0" + "version": "==65.2.0" }, "smmap": { "hashes": [ @@ -989,11 +978,11 @@ }, "stevedore": { "hashes": [ - "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c", - "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335" + "sha256:87e4d27fe96d0d7e4fc24f0cbe3463baae4ec51e81d95fbe60d2474636e0c7d8", + "sha256:f82cc99a1ff552310d19c379827c2c64dd9f85a38bcd5559db2470161867b786" ], - "markers": "python_version >= '3.6'", - "version": "==3.5.0" + "markers": "python_version >= '3.8'", + "version": "==4.0.0" }, "toml": { "hashes": [ diff --git a/bot.py b/bot.py index f3d7198428..fb373f9e76 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev16" +__version__ = "4.0.0-dev17" import asyncio @@ -1769,9 +1769,9 @@ def main(): sys.exit(0) # check discord version - if discord.__version__ != "2.0.0a": + if discord.__version__ != "2.0.0": logger.error( - "Dependencies are not updated, run pipenv install. discord.py version expected 2.0.0a, received %s", + "Dependencies are not updated, run pipenv install. discord.py version expected 2.0.0, received %s", discord.__version__, ) sys.exit(0) diff --git a/pyproject.toml b/pyproject.toml index 7c1dc0e952..b3dea8293f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev16' +version = '4.0.0-dev17' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From ac2e36ced9ce3fbc27a02ef9f8653c211629a1ee Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Aug 2022 22:20:30 +0800 Subject: [PATCH 116/225] Bump dpy-2.0 --- CHANGELOG.md | 2 +- Pipfile | 2 +- Pipfile.lock | 307 ++++++++++++++++++++++++------------------------- bot.py | 6 +- pyproject.toml | 2 +- 5 files changed, 154 insertions(+), 165 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 054f126f7f..0070eecf0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Breaking - Modmail now requires [`Message Content` privileged intent](https://support-dev.discord.com/hc/en-us/articles/4404772028055-Message-Content-Privileged-Intent-for-Verified-Bots). -- Upgraded to discord.py v2.0 master ([internal changes](https://gist.github.com/apple502j/f75b4f24652f04de85c7084ffd73ec58), [GH #2990](https://github.com/kyb3r/modmail/issues/2990)). +- Upgraded to discord.py v2.0 ([internal changes](https://discordpy.readthedocs.io/en/latest/migrating.html), [GH #2990](https://github.com/kyb3r/modmail/issues/2990)). - Python 3.8 or higher is required. - Asyncio changes ([gist](https://gist.github.com/Rapptz/6706e1c8f23ac27c98cee4dd985c8120)) diff --git a/Pipfile b/Pipfile index 82ec35158d..12de060a72 100644 --- a/Pipfile +++ b/Pipfile @@ -12,7 +12,7 @@ typing-extensions = "==4.2.0" [packages] aiohttp = "==3.8.1" colorama = "~=0.4.5" -"discord.py" = {ref = "9fe19dcc6923e4b6133bdedafb33658bf37c9ab7", git = "https://github.com/Rapptz/discord.py.git"} +"discord.py" = "==2.0.0" emoji = "==1.7.0" isodate = "~=0.6.0" motor = "==2.5.1" diff --git a/Pipfile.lock b/Pipfile.lock index 87a2f247fc..ed19b5883c 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "89578b9ae8a9a0b580e0af21767bd2f062388ad43c9bdc6e5d113de91361bea3" + "sha256": "aa752693f18b9d6058209883bdcece4e37a1a7a62a5fd564d64e551d91ea49f4" }, "pipfile-spec": 6, "requires": {}, @@ -110,11 +110,11 @@ }, "attrs": { "hashes": [ - "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", - "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd" + "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6", + "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==21.4.0" + "markers": "python_version >= '3.5'", + "version": "==22.1.0" }, "cairocffi": { "hashes": [ @@ -201,11 +201,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", - "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" + "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", + "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" ], "markers": "python_version >= '3.6'", - "version": "==2.1.0" + "version": "==2.1.1" }, "colorama": { "hashes": [ @@ -231,13 +231,13 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==0.7.1" }, - "discord-py": { - "git": "https://github.com/Rapptz/discord.py.git", - "ref": "9fe19dcc6923e4b6133bdedafb33658bf37c9ab7" - }, "discord.py": { - "git": "https://github.com/Rapptz/discord.py.git", - "ref": "9fe19dcc6923e4b6133bdedafb33658bf37c9ab7" + "hashes": [ + "sha256:18b06870bdc85d29e0d55f4a4b2abe9d7cdae2b197e23d49f82886ba27ba1aec", + "sha256:c36f26935938194c3465c2abf8ecfbbf5560c50b189f1b746d6f00d1e78c0d3b" + ], + "index": "pypi", + "version": "==2.0.0" }, "dnspython": { "hashes": [ @@ -256,68 +256,68 @@ }, "frozenlist": { "hashes": [ - "sha256:006d3595e7d4108a12025ddf415ae0f6c9e736e726a5db0183326fd191b14c5e", - "sha256:01a73627448b1f2145bddb6e6c2259988bb8aee0fb361776ff8604b99616cd08", - "sha256:03a7dd1bfce30216a3f51a84e6dd0e4a573d23ca50f0346634916ff105ba6e6b", - "sha256:0437fe763fb5d4adad1756050cbf855bbb2bf0d9385c7bb13d7a10b0dd550486", - "sha256:04cb491c4b1c051734d41ea2552fde292f5f3a9c911363f74f39c23659c4af78", - "sha256:0c36e78b9509e97042ef869c0e1e6ef6429e55817c12d78245eb915e1cca7468", - "sha256:25af28b560e0c76fa41f550eacb389905633e7ac02d6eb3c09017fa1c8cdfde1", - "sha256:2fdc3cd845e5a1f71a0c3518528bfdbfe2efaf9886d6f49eacc5ee4fd9a10953", - "sha256:30530930410855c451bea83f7b272fb1c495ed9d5cc72895ac29e91279401db3", - "sha256:31977f84828b5bb856ca1eb07bf7e3a34f33a5cddce981d880240ba06639b94d", - "sha256:3c62964192a1c0c30b49f403495911298810bada64e4f03249ca35a33ca0417a", - "sha256:3f7c935c7b58b0d78c0beea0c7358e165f95f1fd8a7e98baa40d22a05b4a8141", - "sha256:40dff8962b8eba91fd3848d857203f0bd704b5f1fa2b3fc9af64901a190bba08", - "sha256:40ec383bc194accba825fbb7d0ef3dda5736ceab2375462f1d8672d9f6b68d07", - "sha256:436496321dad302b8b27ca955364a439ed1f0999311c393dccb243e451ff66aa", - "sha256:4406cfabef8f07b3b3af0f50f70938ec06d9f0fc26cbdeaab431cbc3ca3caeaa", - "sha256:45334234ec30fc4ea677f43171b18a27505bfb2dba9aca4398a62692c0ea8868", - "sha256:47be22dc27ed933d55ee55845d34a3e4e9f6fee93039e7f8ebadb0c2f60d403f", - "sha256:4a44ebbf601d7bac77976d429e9bdb5a4614f9f4027777f9e54fd765196e9d3b", - "sha256:4eda49bea3602812518765810af732229b4291d2695ed24a0a20e098c45a707b", - "sha256:57f4d3f03a18facacb2a6bcd21bccd011e3b75d463dc49f838fd699d074fabd1", - "sha256:603b9091bd70fae7be28bdb8aa5c9990f4241aa33abb673390a7f7329296695f", - "sha256:65bc6e2fece04e2145ab6e3c47428d1bbc05aede61ae365b2c1bddd94906e478", - "sha256:691ddf6dc50480ce49f68441f1d16a4c3325887453837036e0fb94736eae1e58", - "sha256:6983a31698490825171be44ffbafeaa930ddf590d3f051e397143a5045513b01", - "sha256:6a202458d1298ced3768f5a7d44301e7c86defac162ace0ab7434c2e961166e8", - "sha256:6eb275c6385dd72594758cbe96c07cdb9bd6becf84235f4a594bdf21e3596c9d", - "sha256:754728d65f1acc61e0f4df784456106e35afb7bf39cfe37227ab00436fb38676", - "sha256:768efd082074bb203c934e83a61654ed4931ef02412c2fbdecea0cff7ecd0274", - "sha256:772965f773757a6026dea111a15e6e2678fbd6216180f82a48a40b27de1ee2ab", - "sha256:871d42623ae15eb0b0e9df65baeee6976b2e161d0ba93155411d58ff27483ad8", - "sha256:88aafd445a233dbbf8a65a62bc3249a0acd0d81ab18f6feb461cc5a938610d24", - "sha256:8c905a5186d77111f02144fab5b849ab524f1e876a1e75205cd1386a9be4b00a", - "sha256:8cf829bd2e2956066dd4de43fd8ec881d87842a06708c035b37ef632930505a2", - "sha256:92e650bd09b5dda929523b9f8e7f99b24deac61240ecc1a32aeba487afcd970f", - "sha256:93641a51f89473837333b2f8100f3f89795295b858cd4c7d4a1f18e299dc0a4f", - "sha256:94c7a8a9fc9383b52c410a2ec952521906d355d18fccc927fca52ab575ee8b93", - "sha256:9f892d6a94ec5c7b785e548e42722e6f3a52f5f32a8461e82ac3e67a3bd073f1", - "sha256:acb267b09a509c1df5a4ca04140da96016f40d2ed183cdc356d237286c971b51", - "sha256:adac9700675cf99e3615eb6a0eb5e9f5a4143c7d42c05cea2e7f71c27a3d0846", - "sha256:aff388be97ef2677ae185e72dc500d19ecaf31b698986800d3fc4f399a5e30a5", - "sha256:b5009062d78a8c6890d50b4e53b0ddda31841b3935c1937e2ed8c1bda1c7fb9d", - "sha256:b684c68077b84522b5c7eafc1dc735bfa5b341fb011d5552ebe0968e22ed641c", - "sha256:b9e3e9e365991f8cc5f5edc1fd65b58b41d0514a6a7ad95ef5c7f34eb49b3d3e", - "sha256:bd89acd1b8bb4f31b47072615d72e7f53a948d302b7c1d1455e42622de180eae", - "sha256:bde99812f237f79eaf3f04ebffd74f6718bbd216101b35ac7955c2d47c17da02", - "sha256:c6c321dd013e8fc20735b92cb4892c115f5cdb82c817b1e5b07f6b95d952b2f0", - "sha256:ce6f2ba0edb7b0c1d8976565298ad2deba6f8064d2bebb6ffce2ca896eb35b0b", - "sha256:d2257aaba9660f78c7b1d8fea963b68f3feffb1a9d5d05a18401ca9eb3e8d0a3", - "sha256:d26b650b71fdc88065b7a21f8ace70175bcf3b5bdba5ea22df4bfd893e795a3b", - "sha256:d6d32ff213aef0fd0bcf803bffe15cfa2d4fde237d1d4838e62aec242a8362fa", - "sha256:e1e26ac0a253a2907d654a37e390904426d5ae5483150ce3adedb35c8c06614a", - "sha256:e30b2f9683812eb30cf3f0a8e9f79f8d590a7999f731cf39f9105a7c4a39489d", - "sha256:e84cb61b0ac40a0c3e0e8b79c575161c5300d1d89e13c0e02f76193982f066ed", - "sha256:e982878792c971cbd60ee510c4ee5bf089a8246226dea1f2138aa0bb67aff148", - "sha256:f20baa05eaa2bcd5404c445ec51aed1c268d62600362dc6cfe04fae34a424bd9", - "sha256:f7353ba3367473d1d616ee727945f439e027f0bb16ac1a750219a8344d1d5d3c", - "sha256:f96293d6f982c58ebebb428c50163d010c2f05de0cde99fd681bfdc18d4b2dc2", - "sha256:ff9310f05b9d9c5c4dd472983dc956901ee6cb2c3ec1ab116ecdde25f3ce4951" + "sha256:022178b277cb9277d7d3b3f2762d294f15e85cd2534047e68a118c2bb0058f3e", + "sha256:086ca1ac0a40e722d6833d4ce74f5bf1aba2c77cbfdc0cd83722ffea6da52a04", + "sha256:0bc75692fb3770cf2b5856a6c2c9de967ca744863c5e89595df64e252e4b3944", + "sha256:0dde791b9b97f189874d654c55c24bf7b6782343e14909c84beebd28b7217845", + "sha256:12607804084d2244a7bd4685c9d0dca5df17a6a926d4f1967aa7978b1028f89f", + "sha256:19127f8dcbc157ccb14c30e6f00392f372ddb64a6ffa7106b26ff2196477ee9f", + "sha256:1b51eb355e7f813bcda00276b0114c4172872dc5fb30e3fea059b9367c18fbcb", + "sha256:1e1cf7bc8cbbe6ce3881863671bac258b7d6bfc3706c600008925fb799a256e2", + "sha256:219a9676e2eae91cb5cc695a78b4cb43d8123e4160441d2b6ce8d2c70c60e2f3", + "sha256:2743bb63095ef306041c8f8ea22bd6e4d91adabf41887b1ad7886c4c1eb43d5f", + "sha256:2af6f7a4e93f5d08ee3f9152bce41a6015b5cf87546cb63872cc19b45476e98a", + "sha256:31b44f1feb3630146cffe56344704b730c33e042ffc78d21f2125a6a91168131", + "sha256:31bf9539284f39ff9398deabf5561c2b0da5bb475590b4e13dd8b268d7a3c5c1", + "sha256:35c3d79b81908579beb1fb4e7fcd802b7b4921f1b66055af2578ff7734711cfa", + "sha256:3a735e4211a04ccfa3f4833547acdf5d2f863bfeb01cfd3edaffbc251f15cec8", + "sha256:42719a8bd3792744c9b523674b752091a7962d0d2d117f0b417a3eba97d1164b", + "sha256:49459f193324fbd6413e8e03bd65789e5198a9fa3095e03f3620dee2f2dabff2", + "sha256:4c0c99e31491a1d92cde8648f2e7ccad0e9abb181f6ac3ddb9fc48b63301808e", + "sha256:52137f0aea43e1993264a5180c467a08a3e372ca9d378244c2d86133f948b26b", + "sha256:526d5f20e954d103b1d47232e3839f3453c02077b74203e43407b962ab131e7b", + "sha256:53b2b45052e7149ee8b96067793db8ecc1ae1111f2f96fe1f88ea5ad5fd92d10", + "sha256:572ce381e9fe027ad5e055f143763637dcbac2542cfe27f1d688846baeef5170", + "sha256:58fb94a01414cddcdc6839807db77ae8057d02ddafc94a42faee6004e46c9ba8", + "sha256:5e77a8bd41e54b05e4fb2708dc6ce28ee70325f8c6f50f3df86a44ecb1d7a19b", + "sha256:5f271c93f001748fc26ddea409241312a75e13466b06c94798d1a341cf0e6989", + "sha256:5f63c308f82a7954bf8263a6e6de0adc67c48a8b484fab18ff87f349af356efd", + "sha256:61d7857950a3139bce035ad0b0945f839532987dfb4c06cfe160254f4d19df03", + "sha256:61e8cb51fba9f1f33887e22488bad1e28dd8325b72425f04517a4d285a04c519", + "sha256:625d8472c67f2d96f9a4302a947f92a7adbc1e20bedb6aff8dbc8ff039ca6189", + "sha256:6e19add867cebfb249b4e7beac382d33215d6d54476bb6be46b01f8cafb4878b", + "sha256:717470bfafbb9d9be624da7780c4296aa7935294bd43a075139c3d55659038ca", + "sha256:74140933d45271c1a1283f708c35187f94e1256079b3c43f0c2267f9db5845ff", + "sha256:74e6b2b456f21fc93ce1aff2b9728049f1464428ee2c9752a4b4f61e98c4db96", + "sha256:9494122bf39da6422b0972c4579e248867b6b1b50c9b05df7e04a3f30b9a413d", + "sha256:94e680aeedc7fd3b892b6fa8395b7b7cc4b344046c065ed4e7a1e390084e8cb5", + "sha256:97d9e00f3ac7c18e685320601f91468ec06c58acc185d18bb8e511f196c8d4b2", + "sha256:9c6ef8014b842f01f5d2b55315f1af5cbfde284eb184075c189fd657c2fd8204", + "sha256:a027f8f723d07c3f21963caa7d585dcc9b089335565dabe9c814b5f70c52705a", + "sha256:a718b427ff781c4f4e975525edb092ee2cdef6a9e7bc49e15063b088961806f8", + "sha256:ab386503f53bbbc64d1ad4b6865bf001414930841a870fc97f1546d4d133f141", + "sha256:ab6fa8c7871877810e1b4e9392c187a60611fbf0226a9e0b11b7b92f5ac72792", + "sha256:b47d64cdd973aede3dd71a9364742c542587db214e63b7529fbb487ed67cddd9", + "sha256:b499c6abe62a7a8d023e2c4b2834fce78a6115856ae95522f2f974139814538c", + "sha256:bbb1a71b1784e68870800b1bc9f3313918edc63dbb8f29fbd2e767ce5821696c", + "sha256:c3b31180b82c519b8926e629bf9f19952c743e089c41380ddca5db556817b221", + "sha256:c56c299602c70bc1bb5d1e75f7d8c007ca40c9d7aebaf6e4ba52925d88ef826d", + "sha256:c92deb5d9acce226a501b77307b3b60b264ca21862bd7d3e0c1f3594022f01bc", + "sha256:cc2f3e368ee5242a2cbe28323a866656006382872c40869b49b265add546703f", + "sha256:d82bed73544e91fb081ab93e3725e45dd8515c675c0e9926b4e1f420a93a6ab9", + "sha256:da1cdfa96425cbe51f8afa43e392366ed0b36ce398f08b60de6b97e3ed4affef", + "sha256:da5ba7b59d954f1f214d352308d1d86994d713b13edd4b24a556bcc43d2ddbc3", + "sha256:e0c8c803f2f8db7217898d11657cb6042b9b0553a997c4a0601f48a691480fab", + "sha256:ee4c5120ddf7d4dd1eaf079af3af7102b56d919fa13ad55600a4e0ebe532779b", + "sha256:eee0c5ecb58296580fc495ac99b003f64f82a74f9576a244d04978a7e97166db", + "sha256:f5abc8b4d0c5b556ed8cd41490b606fe99293175a82b98e652c3f2711b452988", + "sha256:f810e764617b0748b49a731ffaa525d9bb36ff38332411704c2400125af859a6", + "sha256:f89139662cc4e65a4813f4babb9ca9544e42bddb823d2ec434e18dad582543bc", + "sha256:fa47319a10e0a076709644a0efbcaab9e91902c8bd8ef74c6adb19d320f69b83", + "sha256:fabb953ab913dadc1ff9dcc3a7a7d3dc6a92efab3a0373989b8063347f8705be" ], "markers": "python_version >= '3.7'", - "version": "==1.3.0" + "version": "==1.3.1" }, "idna": { "hashes": [ @@ -505,7 +505,9 @@ "version": "==2.21" }, "pymongo": { - "extras": [], + "extras": [ + "srv" + ], "hashes": [ "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", @@ -681,81 +683,68 @@ }, "yarl": { "hashes": [ - "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac", - "sha256:0cba38120db72123db7c58322fa69e3c0efa933040ffb586c3a87c063ec7cae8", - "sha256:167ab7f64e409e9bdd99333fe8c67b5574a1f0495dcfd905bc7454e766729b9e", - "sha256:1be4bbb3d27a4e9aa5f3df2ab61e3701ce8fcbd3e9846dbce7c033a7e8136746", - "sha256:1ca56f002eaf7998b5fcf73b2421790da9d2586331805f38acd9997743114e98", - "sha256:1d3d5ad8ea96bd6d643d80c7b8d5977b4e2fb1bab6c9da7322616fd26203d125", - "sha256:1eb6480ef366d75b54c68164094a6a560c247370a68c02dddb11f20c4c6d3c9d", - "sha256:1edc172dcca3f11b38a9d5c7505c83c1913c0addc99cd28e993efeaafdfaa18d", - "sha256:211fcd65c58bf250fb994b53bc45a442ddc9f441f6fec53e65de8cba48ded986", - "sha256:29e0656d5497733dcddc21797da5a2ab990c0cb9719f1f969e58a4abac66234d", - "sha256:368bcf400247318382cc150aaa632582d0780b28ee6053cd80268c7e72796dec", - "sha256:39d5493c5ecd75c8093fa7700a2fb5c94fe28c839c8e40144b7ab7ccba6938c8", - "sha256:3abddf0b8e41445426d29f955b24aeecc83fa1072be1be4e0d194134a7d9baee", - "sha256:3bf8cfe8856708ede6a73907bf0501f2dc4e104085e070a41f5d88e7faf237f3", - "sha256:3ec1d9a0d7780416e657f1e405ba35ec1ba453a4f1511eb8b9fbab81cb8b3ce1", - "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd", - "sha256:52690eb521d690ab041c3919666bea13ab9fbff80d615ec16fa81a297131276b", - "sha256:534b047277a9a19d858cde163aba93f3e1677d5acd92f7d10ace419d478540de", - "sha256:580c1f15500e137a8c37053e4cbf6058944d4c114701fa59944607505c2fe3a0", - "sha256:59218fef177296451b23214c91ea3aba7858b4ae3306dde120224cfe0f7a6ee8", - "sha256:5ba63585a89c9885f18331a55d25fe81dc2d82b71311ff8bd378fc8004202ff6", - "sha256:5bb7d54b8f61ba6eee541fba4b83d22b8a046b4ef4d8eb7f15a7e35db2e1e245", - "sha256:6152224d0a1eb254f97df3997d79dadd8bb2c1a02ef283dbb34b97d4f8492d23", - "sha256:67e94028817defe5e705079b10a8438b8cb56e7115fa01640e9c0bb3edf67332", - "sha256:695ba021a9e04418507fa930d5f0704edbce47076bdcfeeaba1c83683e5649d1", - "sha256:6a1a9fe17621af43e9b9fcea8bd088ba682c8192d744b386ee3c47b56eaabb2c", - "sha256:6ab0c3274d0a846840bf6c27d2c60ba771a12e4d7586bf550eefc2df0b56b3b4", - "sha256:6feca8b6bfb9eef6ee057628e71e1734caf520a907b6ec0d62839e8293e945c0", - "sha256:737e401cd0c493f7e3dd4db72aca11cfe069531c9761b8ea474926936b3c57c8", - "sha256:788713c2896f426a4e166b11f4ec538b5736294ebf7d5f654ae445fd44270832", - "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58", - "sha256:8300401dc88cad23f5b4e4c1226f44a5aa696436a4026e456fe0e5d2f7f486e6", - "sha256:87f6e082bce21464857ba58b569370e7b547d239ca22248be68ea5d6b51464a1", - "sha256:89ccbf58e6a0ab89d487c92a490cb5660d06c3a47ca08872859672f9c511fc52", - "sha256:8b0915ee85150963a9504c10de4e4729ae700af11df0dc5550e6587ed7891e92", - "sha256:8cce6f9fa3df25f55521fbb5c7e4a736683148bcc0c75b21863789e5185f9185", - "sha256:95a1873b6c0dd1c437fb3bb4a4aaa699a48c218ac7ca1e74b0bee0ab16c7d60d", - "sha256:9b4c77d92d56a4c5027572752aa35082e40c561eec776048330d2907aead891d", - "sha256:9bfcd43c65fbb339dc7086b5315750efa42a34eefad0256ba114cd8ad3896f4b", - "sha256:9c1f083e7e71b2dd01f7cd7434a5f88c15213194df38bc29b388ccdf1492b739", - "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05", - "sha256:a467a431a0817a292121c13cbe637348b546e6ef47ca14a790aa2fa8cc93df63", - "sha256:aa32aaa97d8b2ed4e54dc65d241a0da1c627454950f7d7b1f95b13985afd6c5d", - "sha256:ac10bbac36cd89eac19f4e51c032ba6b412b3892b685076f4acd2de18ca990aa", - "sha256:ac35ccde589ab6a1870a484ed136d49a26bcd06b6a1c6397b1967ca13ceb3913", - "sha256:bab827163113177aee910adb1f48ff7af31ee0289f434f7e22d10baf624a6dfe", - "sha256:baf81561f2972fb895e7844882898bda1eef4b07b5b385bcd308d2098f1a767b", - "sha256:bf19725fec28452474d9887a128e98dd67eee7b7d52e932e6949c532d820dc3b", - "sha256:c01a89a44bb672c38f42b49cdb0ad667b116d731b3f4c896f72302ff77d71656", - "sha256:c0910c6b6c31359d2f6184828888c983d54d09d581a4a23547a35f1d0b9484b1", - "sha256:c10ea1e80a697cf7d80d1ed414b5cb8f1eec07d618f54637067ae3c0334133c4", - "sha256:c1164a2eac148d85bbdd23e07dfcc930f2e633220f3eb3c3e2a25f6148c2819e", - "sha256:c145ab54702334c42237a6c6c4cc08703b6aa9b94e2f227ceb3d477d20c36c63", - "sha256:c17965ff3706beedafd458c452bf15bac693ecd146a60a06a214614dc097a271", - "sha256:c19324a1c5399b602f3b6e7db9478e5b1adf5cf58901996fc973fe4fccd73eed", - "sha256:c2a1ac41a6aa980db03d098a5531f13985edcb451bcd9d00670b03129922cd0d", - "sha256:c6ddcd80d79c96eb19c354d9dca95291589c5954099836b7c8d29278a7ec0bda", - "sha256:c9c6d927e098c2d360695f2e9d38870b2e92e0919be07dbe339aefa32a090265", - "sha256:cc8b7a7254c0fc3187d43d6cb54b5032d2365efd1df0cd1749c0c4df5f0ad45f", - "sha256:cff3ba513db55cc6a35076f32c4cdc27032bd075c9faef31fec749e64b45d26c", - "sha256:d260d4dc495c05d6600264a197d9d6f7fc9347f21d2594926202fd08cf89a8ba", - "sha256:d6f3d62e16c10e88d2168ba2d065aa374e3c538998ed04996cd373ff2036d64c", - "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b", - "sha256:dfe4b95b7e00c6635a72e2d00b478e8a28bfb122dc76349a06e20792eb53a523", - "sha256:e39378894ee6ae9f555ae2de332d513a5763276a9265f8e7cbaeb1b1ee74623a", - "sha256:ede3b46cdb719c794427dcce9d8beb4abe8b9aa1e97526cc20de9bd6583ad1ef", - "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95", - "sha256:f44477ae29025d8ea87ec308539f95963ffdc31a82f42ca9deecf2d505242e72", - "sha256:f64394bd7ceef1237cc604b5a89bf748c95982a84bcd3c4bbeb40f685c810794", - "sha256:fc4dd8b01a8112809e6b636b00f487846956402834a7fd59d46d4f4267181c41", - "sha256:fce78593346c014d0d986b7ebc80d782b7f5e19843ca798ed62f8e3ba8728576", - "sha256:fd547ec596d90c8676e369dd8a581a21227fe9b4ad37d0dc7feb4ccf544c2d59" + "sha256:076eede537ab978b605f41db79a56cad2e7efeea2aa6e0fa8f05a26c24a034fb", + "sha256:07b21e274de4c637f3e3b7104694e53260b5fc10d51fb3ec5fed1da8e0f754e3", + "sha256:0ab5a138211c1c366404d912824bdcf5545ccba5b3ff52c42c4af4cbdc2c5035", + "sha256:0c03f456522d1ec815893d85fccb5def01ffaa74c1b16ff30f8aaa03eb21e453", + "sha256:12768232751689c1a89b0376a96a32bc7633c08da45ad985d0c49ede691f5c0d", + "sha256:19cd801d6f983918a3f3a39f3a45b553c015c5aac92ccd1fac619bd74beece4a", + "sha256:1ca7e596c55bd675432b11320b4eacc62310c2145d6801a1f8e9ad160685a231", + "sha256:1e4808f996ca39a6463f45182e2af2fae55e2560be586d447ce8016f389f626f", + "sha256:205904cffd69ae972a1707a1bd3ea7cded594b1d773a0ce66714edf17833cdae", + "sha256:20df6ff4089bc86e4a66e3b1380460f864df3dd9dccaf88d6b3385d24405893b", + "sha256:21ac44b763e0eec15746a3d440f5e09ad2ecc8b5f6dcd3ea8cb4773d6d4703e3", + "sha256:29e256649f42771829974e742061c3501cc50cf16e63f91ed8d1bf98242e5507", + "sha256:2d800b9c2eaf0684c08be5f50e52bfa2aa920e7163c2ea43f4f431e829b4f0fd", + "sha256:2d93a049d29df172f48bcb09acf9226318e712ce67374f893b460b42cc1380ae", + "sha256:31a9a04ecccd6b03e2b0e12e82131f1488dea5555a13a4d32f064e22a6003cfe", + "sha256:3d1a50e461615747dd93c099f297c1994d472b0f4d2db8a64e55b1edf704ec1c", + "sha256:449c957ffc6bc2309e1fbe67ab7d2c1efca89d3f4912baeb8ead207bb3cc1cd4", + "sha256:4a88510731cd8d4befaba5fbd734a7dd914de5ab8132a5b3dde0bbd6c9476c64", + "sha256:4c322cbaa4ed78a8aac89b2174a6df398faf50e5fc12c4c191c40c59d5e28357", + "sha256:5395da939ffa959974577eff2cbfc24b004a2fb6c346918f39966a5786874e54", + "sha256:5587bba41399854703212b87071c6d8638fa6e61656385875f8c6dff92b2e461", + "sha256:56c11efb0a89700987d05597b08a1efcd78d74c52febe530126785e1b1a285f4", + "sha256:5999c4662631cb798496535afbd837a102859568adc67d75d2045e31ec3ac497", + "sha256:59ddd85a1214862ce7c7c66457f05543b6a275b70a65de366030d56159a979f0", + "sha256:6347f1a58e658b97b0a0d1ff7658a03cb79bdbda0331603bed24dd7054a6dea1", + "sha256:6628d750041550c5d9da50bb40b5cf28a2e63b9388bac10fedd4f19236ef4957", + "sha256:6afb336e23a793cd3b6476c30f030a0d4c7539cd81649683b5e0c1b0ab0bf350", + "sha256:6c8148e0b52bf9535c40c48faebb00cb294ee577ca069d21bd5c48d302a83780", + "sha256:76577f13333b4fe345c3704811ac7509b31499132ff0181f25ee26619de2c843", + "sha256:7c0da7e44d0c9108d8b98469338705e07f4bb7dab96dbd8fa4e91b337db42548", + "sha256:7de89c8456525650ffa2bb56a3eee6af891e98f498babd43ae307bd42dca98f6", + "sha256:7ec362167e2c9fd178f82f252b6d97669d7245695dc057ee182118042026da40", + "sha256:7fce6cbc6c170ede0221cc8c91b285f7f3c8b9fe28283b51885ff621bbe0f8ee", + "sha256:85cba594433915d5c9a0d14b24cfba0339f57a2fff203a5d4fd070e593307d0b", + "sha256:8b0af1cf36b93cee99a31a545fe91d08223e64390c5ecc5e94c39511832a4bb6", + "sha256:9130ddf1ae9978abe63808b6b60a897e41fccb834408cde79522feb37fb72fb0", + "sha256:99449cd5366fe4608e7226c6cae80873296dfa0cde45d9b498fefa1de315a09e", + "sha256:9de955d98e02fab288c7718662afb33aab64212ecb368c5dc866d9a57bf48880", + "sha256:a0fb2cb4204ddb456a8e32381f9a90000429489a25f64e817e6ff94879d432fc", + "sha256:a165442348c211b5dea67c0206fc61366212d7082ba8118c8c5c1c853ea4d82e", + "sha256:ab2a60d57ca88e1d4ca34a10e9fb4ab2ac5ad315543351de3a612bbb0560bead", + "sha256:abc06b97407868ef38f3d172762f4069323de52f2b70d133d096a48d72215d28", + "sha256:af887845b8c2e060eb5605ff72b6f2dd2aab7a761379373fd89d314f4752abbf", + "sha256:b19255dde4b4f4c32e012038f2c169bb72e7f081552bea4641cab4d88bc409dd", + "sha256:b3ded839a5c5608eec8b6f9ae9a62cb22cd037ea97c627f38ae0841a48f09eae", + "sha256:c1445a0c562ed561d06d8cbc5c8916c6008a31c60bc3655cdd2de1d3bf5174a0", + "sha256:d0272228fabe78ce00a3365ffffd6f643f57a91043e119c289aaba202f4095b0", + "sha256:d0b51530877d3ad7a8d47b2fff0c8df3b8f3b8deddf057379ba50b13df2a5eae", + "sha256:d0f77539733e0ec2475ddcd4e26777d08996f8cd55d2aef82ec4d3896687abda", + "sha256:d2b8f245dad9e331540c350285910b20dd913dc86d4ee410c11d48523c4fd546", + "sha256:dd032e8422a52e5a4860e062eb84ac94ea08861d334a4bcaf142a63ce8ad4802", + "sha256:de49d77e968de6626ba7ef4472323f9d2e5a56c1d85b7c0e2a190b2173d3b9be", + "sha256:de839c3a1826a909fdbfe05f6fe2167c4ab033f1133757b5936efe2f84904c07", + "sha256:e80ed5a9939ceb6fda42811542f31c8602be336b1fb977bccb012e83da7e4936", + "sha256:ea30a42dc94d42f2ba4d0f7c0ffb4f4f9baa1b23045910c0c32df9c9902cb272", + "sha256:ea513a25976d21733bff523e0ca836ef1679630ef4ad22d46987d04b372d57fc", + "sha256:ed19b74e81b10b592084a5ad1e70f845f0aacb57577018d31de064e71ffa267a", + "sha256:f5af52738e225fcc526ae64071b7e5342abe03f42e0e8918227b38c9aa711e28", + "sha256:fae37373155f5ef9b403ab48af5136ae9851151f7aacd9926251ab26b953118b" ], - "markers": "python_version >= '3.6'", - "version": "==1.7.2" + "markers": "python_version >= '3.7'", + "version": "==1.8.1" } }, "develop": { @@ -910,11 +899,11 @@ }, "pbr": { "hashes": [ - "sha256:e547125940bcc052856ded43be8e101f63828c2d94239ffbe2b327ba3d5ccf0a", - "sha256:e8dca2f4b43560edef58813969f52a56cef023146cbb8931626db80e6c1c4308" + "sha256:cfcc4ff8e698256fc17ea3ff796478b050852585aa5bae79ecd05b2ab7b39b9a", + "sha256:da3e18aac0a3c003e9eea1a81bd23e5a3a75d745670dcf736317b7d966887fdf" ], "markers": "python_version >= '2.6'", - "version": "==5.9.0" + "version": "==5.10.0" }, "platformdirs": { "hashes": [ @@ -973,11 +962,11 @@ }, "setuptools": { "hashes": [ - "sha256:16923d366ced322712c71ccb97164d07472abeecd13f3a6c283f6d5d26722793", - "sha256:db3b8e2f922b2a910a29804776c643ea609badb6a32c4bcc226fd4fd902cce65" + "sha256:7f4bc85450898a09f76ebf28b72fa25bc7111f6c7d665d514a60bba9c75ef2a9", + "sha256:a3ca5857c89f82f5c9410e8508cb32f4872a3bafd4aa7ae122a24ca33bccc750" ], "markers": "python_version >= '3.7'", - "version": "==63.1.0" + "version": "==65.2.0" }, "smmap": { "hashes": [ @@ -989,11 +978,11 @@ }, "stevedore": { "hashes": [ - "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c", - "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335" + "sha256:87e4d27fe96d0d7e4fc24f0cbe3463baae4ec51e81d95fbe60d2474636e0c7d8", + "sha256:f82cc99a1ff552310d19c379827c2c64dd9f85a38bcd5559db2470161867b786" ], - "markers": "python_version >= '3.6'", - "version": "==3.5.0" + "markers": "python_version >= '3.8'", + "version": "==4.0.0" }, "toml": { "hashes": [ diff --git a/bot.py b/bot.py index f3d7198428..fb373f9e76 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev16" +__version__ = "4.0.0-dev17" import asyncio @@ -1769,9 +1769,9 @@ def main(): sys.exit(0) # check discord version - if discord.__version__ != "2.0.0a": + if discord.__version__ != "2.0.0": logger.error( - "Dependencies are not updated, run pipenv install. discord.py version expected 2.0.0a, received %s", + "Dependencies are not updated, run pipenv install. discord.py version expected 2.0.0, received %s", discord.__version__, ) sys.exit(0) diff --git a/pyproject.toml b/pyproject.toml index 7c1dc0e952..b3dea8293f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev16' +version = '4.0.0-dev17' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 57eca05d471fd5e68b8e25c889e33dcb6522bcef Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Aug 2022 22:21:20 +0800 Subject: [PATCH 117/225] Skip loading of already-loaded cog #3172 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0070eecf0a..44097a7527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Old data causing `?blocked` to fail. ([GH #3131](https://github.com/kyb3r/modmail/issues/3131)) - Delete channel auto close functionality now works. - Improved error handling for autoupdate. ([PR #3161](https://github.com/kyb3r/modmail/pull/3161)) +- Skip loading of already-loaded cog. ([PR #3172](https://github.com/kyb3r/modmail/pull/3172)) ### Internal From 48ad5c4ee6f92b86d32737568ae94d8637f70219 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Mon, 22 Aug 2022 22:22:47 +0800 Subject: [PATCH 118/225] snippet make create aliases, resolve #3172, close #3174 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44097a7527..27165ebda8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Select menus for certain paginators. - `Title` field in `?logs`. ([GH #3142](https://github.com/kyb3r/modmail/issues/3142)) - Snippets can be used in aliases. ([GH #3108](https://github.com/kyb3r/modmail/issues/3108), [PR #3124](https://github.com/kyb3r/modmail/pull/3124)) +- `?snippet make/create` as aliases to `?snippet add`. ([GH #3172](https://github.com/kyb3r/modmail/issues/3173), [PR #3174](https://github.com/kyb3r/modmail/pull/3174)) ### Improved From f68d8a20861eb851f2713b796f639b44ba6b16c0 Mon Sep 17 00:00:00 2001 From: Jerrie-Aries <hidzrie@gmail.com> Date: Wed, 24 Aug 2022 14:10:48 +0000 Subject: [PATCH 119/225] Add `unhandled_by_cog` parameter to `ModmailBot.on_command_error`: - Resolve #3170 --- bot.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 5b71c9bc71..6ea42499cb 100644 --- a/bot.py +++ b/bot.py @@ -1511,7 +1511,17 @@ async def on_error(self, event_method, *args, **kwargs): logger.error("Ignoring exception in %s.", event_method) logger.error("Unexpected exception:", exc_info=sys.exc_info()) - async def on_command_error(self, context, exception): + async def on_command_error( + self, context: commands.Context, exception: Exception, *, unhandled_by_cog: bool = False + ) -> None: + if not unhandled_by_cog: + command = context.command + if command and command.has_error_handler(): + return + cog = context.cog + if cog and cog.has_error_handler(): + return + if isinstance(exception, (commands.BadArgument, commands.BadUnionArgument)): await context.typing() await context.send(embed=discord.Embed(color=self.error_color, description=str(exception))) From fa3ad60af794c5fe766697f6c070a43d21840cfe Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 6 Sep 2022 22:36:26 +0800 Subject: [PATCH 120/225] Update to discord.py 2.0.1 and fix time module --- Pipfile | 2 +- Pipfile.lock | 27 +-- bot.py | 15 +- cogs/modmail.py | 10 +- core/config.py | 7 +- core/time.py | 436 ++++++++++++++++++++++++++++++----------------- core/utils.py | 17 +- pyproject.toml | 2 +- requirements.txt | 2 +- 9 files changed, 333 insertions(+), 185 deletions(-) diff --git a/Pipfile b/Pipfile index 12de060a72..573f06cb76 100644 --- a/Pipfile +++ b/Pipfile @@ -12,7 +12,7 @@ typing-extensions = "==4.2.0" [packages] aiohttp = "==3.8.1" colorama = "~=0.4.5" -"discord.py" = "==2.0.0" +"discord.py" = "==2.0.1" emoji = "==1.7.0" isodate = "~=0.6.0" motor = "==2.5.1" diff --git a/Pipfile.lock b/Pipfile.lock index ed19b5883c..9657e2b273 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "aa752693f18b9d6058209883bdcece4e37a1a7a62a5fd564d64e551d91ea49f4" + "sha256": "c074bd9564d93aac78141ccfec1138ffeb561dfa0956f60ee5b10322d156d20f" }, "pipfile-spec": 6, "requires": {}, @@ -233,11 +233,11 @@ }, "discord.py": { "hashes": [ - "sha256:18b06870bdc85d29e0d55f4a4b2abe9d7cdae2b197e23d49f82886ba27ba1aec", - "sha256:c36f26935938194c3465c2abf8ecfbbf5560c50b189f1b746d6f00d1e78c0d3b" + "sha256:309146476e986cb8faf038cd5d604d4b3834ef15c2d34df697ce5064bf5cd779", + "sha256:aeb186348bf011708b085b2715cf92bbb72c692eb4f59c4c0b488130cc4c4b7e" ], "index": "pypi", - "version": "==2.0.0" + "version": "==2.0.1" }, "dnspython": { "hashes": [ @@ -450,6 +450,7 @@ "sha256:2ad0d4df0f5ef2247e27fc790d5c9b5a0af8ade9ba340db4a73bb1a4a3e5fb4f", "sha256:2c58b24e3a63efd22554c676d81b0e57f80e0a7d3a5874a7e14ce90ec40d3069", "sha256:2d33a11f601213dcd5718109c09a52c2a1c893e7461f0be2d6febc2879ec2402", + "sha256:336b9036127eab855beec9662ac3ea13a4544a523ae273cbf108b228ecac8437", "sha256:337a74fd2f291c607d220c793a8135273c4c2ab001b03e601c36766005f36885", "sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e", "sha256:3d1f14f5f691f55e1b47f824ca4fdcb4b19b4323fe43cc7bb105988cad7496be", @@ -478,6 +479,7 @@ "sha256:a647c0d4478b995c5e54615a2e5360ccedd2f85e70ab57fbe817ca613d5e63b8", "sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb", "sha256:ad2277b185ebce47a63f4dc6302e30f05762b688f8dc3de55dbae4651872cdf3", + "sha256:adabc0bce035467fb537ef3e5e74f2847c8af217ee0be0455d4fec8adc0462fc", "sha256:b6d5e92df2b77665e07ddb2e4dbd6d644b78e4c0d2e9272a852627cdba0d75cf", "sha256:bc431b065722a5ad1dfb4df354fb9333b7a582a5ee39a90e6ffff688d72f27a1", "sha256:bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a", @@ -505,9 +507,7 @@ "version": "==2.21" }, "pymongo": { - "extras": [ - "srv" - ], + "extras": [], "hashes": [ "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", @@ -892,10 +892,11 @@ }, "pathspec": { "hashes": [ - "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a", - "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1" + "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93", + "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d" ], - "version": "==0.9.0" + "markers": "python_version >= '3.7'", + "version": "==0.10.1" }, "pbr": { "hashes": [ @@ -962,11 +963,11 @@ }, "setuptools": { "hashes": [ - "sha256:7f4bc85450898a09f76ebf28b72fa25bc7111f6c7d665d514a60bba9c75ef2a9", - "sha256:a3ca5857c89f82f5c9410e8508cb32f4872a3bafd4aa7ae122a24ca33bccc750" + "sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82", + "sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57" ], "markers": "python_version >= '3.7'", - "version": "==65.2.0" + "version": "==65.3.0" }, "smmap": { "hashes": [ diff --git a/bot.py b/bot.py index 5b71c9bc71..ffc2c01dc6 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev17" +__version__ = "4.0.0-dev18" import asyncio @@ -18,6 +18,7 @@ import discord import isodate from aiohttp import ClientSession, ClientResponseError +from discord.utils import MISSING from discord.ext import commands, tasks from discord.ext.commands.view import StringView from emoji import UNICODE_EMOJI @@ -247,10 +248,10 @@ async def runner(): except Exception: logger.critical("Fatal exception", exc_info=True) finally: - if not self.is_closed(): - await self.close() if self.session: await self.session.close() + if not self.is_closed(): + await self.close() async def _cancel_tasks(): async with self: @@ -282,7 +283,7 @@ async def _cancel_tasks(): pass try: - asyncio.run(runner()) + asyncio.run(runner(), debug=bool(os.getenv("DEBUG_ASYNCIO"))) except (KeyboardInterrupt, SystemExit): logger.info("Received signal to terminate bot and event loop.") finally: @@ -1771,9 +1772,11 @@ def main(): sys.exit(0) # check discord version - if discord.__version__ != "2.0.0": + discord_version = "2.0.1" + if discord.__version__ != discord_version: logger.error( - "Dependencies are not updated, run pipenv install. discord.py version expected 2.0.0, received %s", + "Dependencies are not updated, run pipenv install. discord.py version expected %s, received %s", + discord_version, discord.__version__, ) sys.exit(0) diff --git a/cogs/modmail.py b/cogs/modmail.py index 7fc9e5b975..a623ed3cdd 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -2,6 +2,7 @@ import re from datetime import datetime, timezone from itertools import zip_longest +import time from typing import Optional, Union, List, Tuple from types import SimpleNamespace @@ -1848,14 +1849,17 @@ async def block( return await ctx.send(embed=embed) reason = f"by {escape_markdown(ctx.author.name)}#{ctx.author.discriminator}" + now = discord.utils.utcnow() if after is not None: if "%" in reason: raise commands.BadArgument('The reason contains illegal character "%".') + unixtime = int(after.dt.replace(tzinfo=timezone.utc).timestamp()) + if after.arg: - reason += f" for `{after.arg}`" - if after.dt > after.now: - reason += f" until {after.dt.isoformat()}" + reason += f" until: <t:{unixtime}:R>" + if after.dt > now: + reason += f" until <t:{unixtime}:f>" reason += "." diff --git a/core/config.py b/core/config.py index 6cff7f0bd7..dd76776092 100644 --- a/core/config.py +++ b/core/config.py @@ -13,7 +13,7 @@ from core._color_data import ALL_COLORS from core.models import DMDisabled, InvalidConfigError, Default, getLogger -from core.time import UserFriendlyTimeSync +from core.time import UserFriendlyTime from core.utils import strtobool logger = getLogger(__name__) @@ -400,7 +400,7 @@ def set(self, key: str, item: typing.Any, convert=True) -> None: isodate.parse_duration(item) except isodate.ISO8601Error: try: - converter = UserFriendlyTimeSync() + converter = UserFriendlyTime() time = converter.convert(None, item) if time.arg: raise ValueError @@ -412,7 +412,8 @@ def set(self, key: str, item: typing.Any, convert=True) -> None: "Unrecognized time, please use ISO-8601 duration format " 'string or a simpler "human readable" time.' ) - item = isodate.duration_isoformat(time.dt - converter.now) + now = discord.utils.utcnow() + item = isodate.duration_isoformat(time.dt - now) return self.__setitem__(key, item) if key in self.booleans: diff --git a/core/time.py b/core/time.py index 26b41b9043..b66f84757f 100644 --- a/core/time.py +++ b/core/time.py @@ -3,223 +3,353 @@ Source: https://github.com/Rapptz/RoboDanny/blob/rewrite/cogs/utils/time.py """ -import re -from datetime import datetime - -import discord -from discord.ext.commands import BadArgument, Converter +from __future__ import annotations +import datetime +from typing import TYPE_CHECKING, Any, Optional, Union import parsedatetime as pdt from dateutil.relativedelta import relativedelta +from .utils import human_join +from discord.ext import commands +from discord import app_commands +import re + +# Monkey patch mins and secs into the units +units = pdt.pdtLocales["en_US"].units +units["minutes"].append("mins") +units["seconds"].append("secs") -from core.models import getLogger +if TYPE_CHECKING: + from typing_extensions import Self + from cogs.utils.context import Context -logger = getLogger(__name__) +class plural: + """https://github.com/Rapptz/RoboDanny/blob/bf7d4226350dff26df4981dd53134eeb2aceeb87/cogs/utils/formats.py#L8-L18""" + + def __init__(self, value: int): + self.value: int = value + + def __format__(self, format_spec: str) -> str: + v = self.value + singular, sep, plural = format_spec.partition("|") + plural = plural or f"{singular}s" + if abs(v) != 1: + return f"{v} {plural}" + return f"{v} {singular}" + + +def format_dt(dt: datetime.datetime, style: Optional[str] = None) -> str: + """https://github.com/Rapptz/RoboDanny/blob/bf7d4226350dff26df4981dd53134eeb2aceeb87/cogs/utils/formats.py#L89-L95""" + if dt.tzinfo is None: + dt = dt.replace(tzinfo=datetime.timezone.utc) + + if style is None: + return f"<t:{int(dt.timestamp())}>" + return f"<t:{int(dt.timestamp())}:{style}>" class ShortTime: compiled = re.compile( - r""" - (?:(?P<years>[0-9])(?:years?|y))? # e.g. 2y - (?:(?P<months>[0-9]{1,2})(?:months?|mo))? # e.g. 9mo - (?:(?P<weeks>[0-9]{1,4})(?:weeks?|w))? # e.g. 10w - (?:(?P<days>[0-9]{1,5})(?:days?|d))? # e.g. 14d - (?:(?P<hours>[0-9]{1,5})(?:hours?|h))? # e.g. 12h - (?:(?P<minutes>[0-9]{1,5})(?:min(?:ute)?s?|m))? # e.g. 10m - (?:(?P<seconds>[0-9]{1,5})(?:sec(?:ond)?s?|s))? # e.g. 15s - """, + """ + (?:(?P<years>[0-9])(?:years?|y))? # e.g. 2y + (?:(?P<months>[0-9]{1,2})(?:months?|mo))? # e.g. 2months + (?:(?P<weeks>[0-9]{1,4})(?:weeks?|w))? # e.g. 10w + (?:(?P<days>[0-9]{1,5})(?:days?|d))? # e.g. 14d + (?:(?P<hours>[0-9]{1,5})(?:hours?|h))? # e.g. 12h + (?:(?P<minutes>[0-9]{1,5})(?:minutes?|m))? # e.g. 10m + (?:(?P<seconds>[0-9]{1,5})(?:seconds?|s))? # e.g. 15s + """, re.VERBOSE, ) - def __init__(self, argument): + discord_fmt = re.compile(r"<t:(?P<ts>[0-9]+)(?:\:?[RFfDdTt])?>") + + dt: datetime.datetime + + def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None): match = self.compiled.fullmatch(argument) if match is None or not match.group(0): - raise BadArgument("Invalid time provided.") + match = self.discord_fmt.fullmatch(argument) + if match is not None: + self.dt = datetime.datetime.fromtimestamp(int(match.group("ts")), tz=datetime.timezone.utc) + return + else: + raise commands.BadArgument("invalid time provided") - data = {k: int(v) for k, v in match.groupdict(default="0").items()} - now = discord.utils.utcnow() + data = {k: int(v) for k, v in match.groupdict(default=0).items()} + now = now or datetime.datetime.now(datetime.timezone.utc) self.dt = now + relativedelta(**data) - -# Monkey patch mins and secs into the units -units = pdt.pdtLocales["en_US"].units -units["minutes"].append("mins") -units["seconds"].append("secs") + @classmethod + async def convert(cls, ctx: Context, argument: str) -> Self: + return cls(argument, now=ctx.message.created_at) class HumanTime: calendar = pdt.Calendar(version=pdt.VERSION_CONTEXT_STYLE) - def __init__(self, argument): - now = discord.utils.utcnow() + def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None): + now = now or datetime.datetime.utcnow() dt, status = self.calendar.parseDT(argument, sourceTime=now) if not status.hasDateOrTime: - raise BadArgument('Invalid time provided, try e.g. "tomorrow" or "3 days".') + raise commands.BadArgument('invalid time provided, try e.g. "tomorrow" or "3 days"') if not status.hasTime: # replace it with the current time dt = dt.replace(hour=now.hour, minute=now.minute, second=now.second, microsecond=now.microsecond) - self.dt = dt - self._past = dt < now + self.dt: datetime.datetime = dt + self._past: bool = dt < now + + @classmethod + async def convert(cls, ctx: Context, argument: str) -> Self: + return cls(argument, now=ctx.message.created_at) class Time(HumanTime): - def __init__(self, argument): + def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None): try: - short_time = ShortTime(argument) - except Exception: + o = ShortTime(argument, now=now) + except Exception as e: super().__init__(argument) else: - self.dt = short_time.dt + self.dt = o.dt self._past = False class FutureTime(Time): - def __init__(self, argument): - super().__init__(argument) + def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None): + super().__init__(argument, now=now) if self._past: - raise BadArgument("The time is in the past.") + raise commands.BadArgument("this time is in the past") -class UserFriendlyTimeSync(Converter): - """That way quotes aren't absolutely necessary.""" +class BadTimeTransform(app_commands.AppCommandError): + pass + + +class TimeTransformer(app_commands.Transformer): + async def transform(self, interaction, value: str) -> datetime.datetime: + now = interaction.created_at + try: + short = ShortTime(value, now=now) + except commands.BadArgument: + try: + human = FutureTime(value, now=now) + except commands.BadArgument as e: + raise BadTimeTransform(str(e)) from None + else: + return human.dt + else: + return short.dt + + +class FriendlyTimeResult: + dt: datetime.datetime + arg: str - def __init__(self): - self.raw: str = None - self.dt: datetime = None - self.arg = None - self.now: datetime = None + __slots__ = ("dt", "arg") - def check_constraints(self, now, remaining): + def __init__(self, dt: datetime.datetime): + self.dt = dt + self.arg = "" + + async def ensure_constraints( + self, ctx: Context, uft: UserFriendlyTime, now: datetime.datetime, remaining: str + ) -> None: if self.dt < now: - raise BadArgument("This time is in the past.") + raise commands.BadArgument("This time is in the past.") - self.arg = remaining - return self + # if not remaining: + # if uft.default is None: + # raise commands.BadArgument("Missing argument after the time.") + # remaining = uft.default - def convert(self, ctx, argument): - self.raw = argument - remaining = "" - try: - calendar = HumanTime.calendar - regex = ShortTime.compiled - self.dt = self.now = discord.utils.utcnow() + if uft.converter is not None: + self.arg = await uft.converter.convert(ctx, remaining) + else: + self.arg = remaining - match = regex.match(argument) - if match is not None and match.group(0): - data = {k: int(v) for k, v in match.groupdict(default="0").items()} - remaining = argument[match.end() :].strip() - self.dt = self.now + relativedelta(**data) - return self.check_constraints(self.now, remaining) - - # apparently nlp does not like "from now" - # it likes "from x" in other cases though - # so let me handle the 'now' case - if argument.endswith(" from now"): - argument = argument[:-9].strip() - # handles "in xxx hours" - if argument.startswith("in "): - argument = argument[3:].strip() - - elements = calendar.nlp(argument, sourceTime=self.now) - if elements is None or not elements: - return self.check_constraints(self.now, argument) - - # handle the following cases: - # "date time" foo - # date time foo - # foo date time - - # first the first two cases: - dt, status, begin, end, _ = elements[0] - - if not status.hasDateOrTime: - return self.check_constraints(self.now, argument) - - if begin not in (0, 1) and end != len(argument): - raise BadArgument( - "Time is either in an inappropriate location, which must " - "be either at the end or beginning of your input, or I " - "just flat out did not understand what you meant. Sorry." - ) - if not status.hasTime: - # replace it with the current time - dt = dt.replace( - hour=self.now.hour, - minute=self.now.minute, - second=self.now.second, - microsecond=self.now.microsecond, - ) +class UserFriendlyTime(commands.Converter): + """That way quotes aren't absolutely necessary.""" - # if midnight is provided, just default to next day - if status.accuracy == pdt.pdtContext.ACU_HALFDAY: - dt = dt.replace(day=self.now.day + 1) + def __init__( + self, + converter: Optional[Union[type[commands.Converter], commands.Converter]] = None, + *, + default: Any = None, + ): + if isinstance(converter, type) and issubclass(converter, commands.Converter): + converter = converter() + + if converter is not None and not isinstance(converter, commands.Converter): + raise TypeError("commands.Converter subclass necessary.") + + self.converter: commands.Converter = converter # type: ignore # It doesn't understand this narrowing + self.default: Any = default + + async def convert(self, ctx: Context, argument: str) -> FriendlyTimeResult: + calendar = HumanTime.calendar + regex = ShortTime.compiled + now = ctx.message.created_at + + match = regex.match(argument) + if match is not None and match.group(0): + data = {k: int(v) for k, v in match.groupdict(default=0).items()} + remaining = argument[match.end() :].strip() + result = FriendlyTimeResult(now + relativedelta(**data)) + await result.ensure_constraints(ctx, self, now, remaining) + return result - self.dt = dt + if match is None or not match.group(0): + match = ShortTime.discord_fmt.match(argument) + if match is not None: + result = FriendlyTimeResult( + datetime.datetime.fromtimestamp(int(match.group("ts")), tz=datetime.timezone.utc) + ) + remaining = argument[match.end() :].strip() + await result.ensure_constraints(ctx, self, now, remaining) + return result - if begin in (0, 1): - if begin == 1: - # check if it's quoted: - if argument[0] != '"': - raise BadArgument("Expected quote before time input...") + # apparently nlp does not like "from now" + # it likes "from x" in other cases though so let me handle the 'now' case + if argument.endswith("from now"): + argument = argument[:-8].strip() - if not (end < len(argument) and argument[end] == '"'): - raise BadArgument("If the time is quoted, you must unquote it.") + if argument[0:2] == "me": + # starts with "me to", "me in", or "me at " + if argument[0:6] in ("me to ", "me in ", "me at "): + argument = argument[6:] - remaining = argument[end + 1 :].lstrip(" ,.!") - else: - remaining = argument[end:].lstrip(" ,.!") - elif len(argument) == end: - remaining = argument[:begin].strip() + elements = calendar.nlp(argument, sourceTime=now) + if elements is None or len(elements) == 0: + raise commands.BadArgument('Invalid time provided, try e.g. "tomorrow" or "3 days".') - return self.check_constraints(self.now, remaining) - except Exception: - logger.exception("Something went wrong while parsing the time.") - raise + # handle the following cases: + # "date time" foo + # date time foo + # foo date time + # first the first two cases: + dt, status, begin, end, dt_string = elements[0] -class UserFriendlyTime(UserFriendlyTimeSync): - async def convert(self, ctx, argument): - return super().convert(ctx, argument) + if not status.hasDateOrTime: + raise commands.BadArgument('Invalid time provided, try e.g. "tomorrow" or "3 days".') + if begin not in (0, 1) and end != len(argument): + raise commands.BadArgument( + "Time is either in an inappropriate location, which " + "must be either at the end or beginning of your input, " + "or I just flat out did not understand what you meant. Sorry." + ) -def human_timedelta(dt, *, spec="R"): - if spec == "manual": - now = discord.utils.utcnow() - if dt > now: - delta = relativedelta(dt, now) - suffix = "" - else: - delta = relativedelta(now, dt) - suffix = " ago" + if not status.hasTime: + # replace it with the current time + dt = dt.replace(hour=now.hour, minute=now.minute, second=now.second, microsecond=now.microsecond) + + # if midnight is provided, just default to next day + if status.accuracy == pdt.pdtContext.ACU_HALFDAY: + dt = dt.replace(day=now.day + 1) - if delta.microseconds and delta.seconds: - delta = delta + relativedelta(seconds=+1) + result = FriendlyTimeResult(dt.replace(tzinfo=datetime.timezone.utc)) + remaining = "" - attrs = ["years", "months", "days", "hours", "minutes", "seconds"] + if begin in (0, 1): + if begin == 1: + # check if it's quoted: + if argument[0] != '"': + raise commands.BadArgument("Expected quote before time input...") - output = [] - for attr in attrs: - elem = getattr(delta, attr) - if not elem: - continue + if not (end < len(argument) and argument[end] == '"'): + raise commands.BadArgument("If the time is quoted, you must unquote it.") - if elem > 1: - output.append(f"{elem} {attr}") + remaining = argument[end + 1 :].lstrip(" ,.!") else: - output.append(f"{elem} {attr[:-1]}") - - if not output: - return "now" - if len(output) == 1: - return output[0] + suffix - if len(output) == 2: - return f"{output[0]} and {output[1]}{suffix}" - return f"{output[0]}, {output[1]} and {output[2]}{suffix}" + remaining = argument[end:].lstrip(" ,.!") + elif len(argument) == end: + remaining = argument[:begin].strip() + + await result.ensure_constraints(ctx, self, now, remaining) + return result + + +def human_timedelta( + dt: datetime.datetime, + *, + source: Optional[datetime.datetime] = None, + accuracy: Optional[int] = 3, + brief: bool = False, + suffix: bool = True, +) -> str: + now = source or datetime.datetime.now(datetime.timezone.utc) + if dt.tzinfo is None: + dt = dt.replace(tzinfo=datetime.timezone.utc) + + if now.tzinfo is None: + now = now.replace(tzinfo=datetime.timezone.utc) + + # Microsecond free zone + now = now.replace(microsecond=0) + dt = dt.replace(microsecond=0) + + # This implementation uses relativedelta instead of the much more obvious + # divmod approach with seconds because the seconds approach is not entirely + # accurate once you go over 1 week in terms of accuracy since you have to + # hardcode a month as 30 or 31 days. + # A query like "11 months" can be interpreted as "!1 months and 6 days" + if dt > now: + delta = relativedelta(dt, now) + output_suffix = "" else: - unixtime = int(dt.timestamp()) - return f"<t:{unixtime}:{spec}>" + delta = relativedelta(now, dt) + output_suffix = " ago" if suffix else "" + + attrs = [ + ("year", "y"), + ("month", "mo"), + ("day", "d"), + ("hour", "h"), + ("minute", "m"), + ("second", "s"), + ] + + output = [] + for attr, brief_attr in attrs: + elem = getattr(delta, attr + "s") + if not elem: + continue + + if attr == "day": + weeks = delta.weeks + if weeks: + elem -= weeks * 7 + if not brief: + output.append(format(plural(weeks), "week")) + else: + output.append(f"{weeks}w") + + if elem <= 0: + continue + + if brief: + output.append(f"{elem}{brief_attr}") + else: + output.append(format(plural(elem), attr)) + + if accuracy is not None: + output = output[:accuracy] + + if len(output) == 0: + return "now" + else: + if not brief: + return human_join(output, final="and") + output_suffix + else: + return " ".join(output) + output_suffix + + +def format_relative(dt: datetime.datetime) -> str: + return format_dt(dt, "R") diff --git a/core/utils.py b/core/utils.py index 30efb05e75..ce28f243c1 100644 --- a/core/utils.py +++ b/core/utils.py @@ -172,10 +172,19 @@ def parse_image_url(url: str, *, convert_size=True) -> str: return "" -def human_join(strings): - if len(strings) <= 2: - return " or ".join(strings) - return ", ".join(strings[: len(strings) - 1]) + " or " + strings[-1] +def human_join(seq: typing.Sequence[str], delim: str = ", ", final: str = "or") -> str: + """https://github.com/Rapptz/RoboDanny/blob/bf7d4226350dff26df4981dd53134eeb2aceeb87/cogs/utils/formats.py#L21-L32""" + size = len(seq) + if size == 0: + return "" + + if size == 1: + return seq[0] + + if size == 2: + return f"{seq[0]} {final} {seq[1]}" + + return delim.join(seq[:-1]) + f" {final} {seq[-1]}" def days(day: typing.Union[str, int]) -> str: diff --git a/pyproject.toml b/pyproject.toml index b3dea8293f..b1826a921d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev17' +version = '4.0.0-dev18' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ diff --git a/requirements.txt b/requirements.txt index edc784029b..313426315e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,7 +20,7 @@ defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, dnspython==2.2.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' emoji==1.7.0 frozenlist==1.3.0; python_version >= '3.7' -git+https://github.com/Rapptz/discord.py.git@e9c7c09ebfe780d8f9de1e9e4d3c2dddf85eccfd#egg=discord.py +discord.py==2.0.1 idna==3.3; python_version >= '3.5' isodate==0.6.1 lottie[pdf]==0.6.11 From 3ea3cf2f8cbc67e39e9a85beb7bfb88934aca22d Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 6 Sep 2022 22:40:54 +0800 Subject: [PATCH 121/225] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27165ebda8..0d32c078b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Delete channel auto close functionality now works. - Improved error handling for autoupdate. ([PR #3161](https://github.com/kyb3r/modmail/pull/3161)) - Skip loading of already-loaded cog. ([PR #3172](https://github.com/kyb3r/modmail/pull/3172)) +- Respect plugin's `cog_command_error`. ([GH #3170](https://github.com/kyb3r/modmail/issues/3170), [PR #3178](https://github.com/kyb3r/modmail/pull/3178)) ### Internal From ecffec2604e8e52b9248f1971751996dc383c461 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 6 Sep 2022 23:01:09 +0800 Subject: [PATCH 122/225] use silent as typing literal, resolve #3179 --- CHANGELOG.md | 1 + cogs/modmail.py | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d32c078b1..8789209eb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Improved error handling for autoupdate. ([PR #3161](https://github.com/kyb3r/modmail/pull/3161)) - Skip loading of already-loaded cog. ([PR #3172](https://github.com/kyb3r/modmail/pull/3172)) - Respect plugin's `cog_command_error`. ([GH #3170](https://github.com/kyb3r/modmail/issues/3170), [PR #3178](https://github.com/kyb3r/modmail/pull/3178)) +- Use silent as a typing literal for contacting. ([GH #3179](https://github.com/kyb3r/modmail/issues/3179)) ### Internal diff --git a/cogs/modmail.py b/cogs/modmail.py index a623ed3cdd..68c4c4715d 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -3,7 +3,7 @@ from datetime import datetime, timezone from itertools import zip_longest import time -from typing import Optional, Union, List, Tuple +from typing import Optional, Union, List, Tuple, Literal from types import SimpleNamespace import discord @@ -1500,9 +1500,9 @@ async def selfcontact(self, ctx): async def contact( self, ctx, - users: commands.Greedy[Union[discord.Member, discord.User, discord.Role]], + users: commands.Greedy[Union[Literal["silent", "silently"], discord.Member, discord.User, discord.Role]], *, - category: Union[SimilarCategoryConverter, str] = None, + category: SimilarCategoryConverter = None, manual_trigger=True, ): """ @@ -1516,16 +1516,22 @@ async def contact( A maximum of 5 users are allowed. `options` can be `silent` or `silently`. """ - silent = False + silent = any(x in users for x in ("silent", "silently")) + if silent: + try: + users.remove("silent") + except ValueError: + pass + + try: + users.remove("silently") + except ValueError: + pass + + print(users, silent) if isinstance(category, str): category = category.split() - # just check the last element in the list - if category[-1].lower() in ("silent", "silently"): - silent = True - # remove the last element as we no longer need it - category.pop() - category = " ".join(category) if category: try: From 7b0c360dd249f9dd6cc75b8f0c1cfc2f76ddc91e Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 6 Sep 2022 23:01:19 +0800 Subject: [PATCH 123/225] fix formatting --- cogs/modmail.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index 68c4c4715d..a21dc205b4 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1500,7 +1500,9 @@ async def selfcontact(self, ctx): async def contact( self, ctx, - users: commands.Greedy[Union[Literal["silent", "silently"], discord.Member, discord.User, discord.Role]], + users: commands.Greedy[ + Union[Literal["silent", "silently"], discord.Member, discord.User, discord.Role] + ], *, category: SimilarCategoryConverter = None, manual_trigger=True, From 60e8444a46c7f94ab923e0cd0c2ca8351172985a Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 6 Sep 2022 23:01:50 +0800 Subject: [PATCH 124/225] bump ver --- bot.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index 846eccd3ac..b05d1435c8 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev18" +__version__ = "4.0.0-dev19" import asyncio diff --git a/pyproject.toml b/pyproject.toml index b1826a921d..9a22625dba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev18' +version = '4.0.0-dev19' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From ec399c3e579ff31492ad7223a9242809b4f9bb7d Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 6 Sep 2022 23:07:24 +0800 Subject: [PATCH 125/225] Autoupdate now automatically updates pipenv dependencies if possible --- CHANGELOG.md | 1 + bot.py | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8789209eb1..e584286230 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Use discord relative timedeltas. ([GH #3046](https://github.com/kyb3r/modmail/issues/3046)) - Use discord native buttons for all paginator sessions. - `?help` and `?blocked` paginator sessions now have better multi-page UI. +- Autoupdate now automatically updates pipenv dependencies if possible. ### Fixed diff --git a/bot.py b/bot.py index b05d1435c8..418916b528 100644 --- a/bot.py +++ b/bot.py @@ -1674,17 +1674,28 @@ async def autoupdate(self): return elif res != "Already up to date.": + if os.getenv("PIPENV_ACTIVE"): + # Update pipenv if possible + await asyncio.create_subprocess_shell( + "pipenv sync", + stderr=PIPE, + stdout=PIPE, + ) + message = "" + else: + message = "\n\nDo manually update dependencies if your bot has crashed." + logger.info("Bot has been updated.") channel = self.update_channel if self.hosting_method in (HostingMethod.PM2, HostingMethod.SYSTEMD): embed = discord.Embed(title="Bot has been updated", color=self.main_color) - embed.set_footer(text=f"Updating Modmail v{self.version} " f"-> v{latest.version}") + embed.set_footer(text=f"Updating Modmail v{self.version} " f"-> v{latest.version} {message}") if self.config["update_notifications"]: await channel.send(embed=embed) else: embed = discord.Embed( title="Bot has been updated and is logging out.", - description="If you do not have an auto-restart setup, please manually start the bot.", + description=f"If you do not have an auto-restart setup, please manually start the bot. {message}", color=self.main_color, ) embed.set_footer(text=f"Updating Modmail v{self.version} -> v{latest.version}") From ddc34c0624e5b18c4f24f923813d79ccfd94424f Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 6 Sep 2022 23:07:40 +0800 Subject: [PATCH 126/225] formatting --- bot.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 418916b528..a990ac772c 100644 --- a/bot.py +++ b/bot.py @@ -1689,7 +1689,9 @@ async def autoupdate(self): channel = self.update_channel if self.hosting_method in (HostingMethod.PM2, HostingMethod.SYSTEMD): embed = discord.Embed(title="Bot has been updated", color=self.main_color) - embed.set_footer(text=f"Updating Modmail v{self.version} " f"-> v{latest.version} {message}") + embed.set_footer( + text=f"Updating Modmail v{self.version} " f"-> v{latest.version} {message}" + ) if self.config["update_notifications"]: await channel.send(embed=embed) else: From 1d3aac9bec0ea71f8f06720e33d5d04f7ac0b047 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 7 Sep 2022 00:09:51 +0800 Subject: [PATCH 127/225] Fix time args, and use literals for close --- cogs/modmail.py | 19 +++++++------------ core/time.py | 29 +++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index a21dc205b4..279df07dd6 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -464,7 +464,7 @@ async def send_scheduled_close_message(self, ctx, after, silent=False): @commands.command(usage="[after] [close message]") @checks.has_permissions(PermissionLevel.SUPPORTER) @checks.thread_only() - async def close(self, ctx, *, after: UserFriendlyTime = None): + async def close(self, ctx, option: Optional[Literal["silent", "silently", "cancel"]]='', *, after: UserFriendlyTime = None): """ Close the current thread. @@ -486,15 +486,11 @@ async def close(self, ctx, *, after: UserFriendlyTime = None): thread = ctx.thread - now = discord.utils.utcnow() - - close_after = (after.dt - now).total_seconds() if after else 0 - message = after.arg if after else None - silent = str(message).lower() in {"silent", "silently"} - cancel = str(message).lower() == "cancel" + close_after = (after.dt - after.now).total_seconds() if after else 0 + silent = any(x == option for x in {"silent", "silently"}) + cancel = option == "cancel" if cancel: - if thread.close_task is not None or thread.auto_close_task is not None: await thread.cancel_closure(all=True) embed = discord.Embed( @@ -508,10 +504,11 @@ async def close(self, ctx, *, after: UserFriendlyTime = None): return await ctx.send(embed=embed) + message = after.arg if after else None if self.bot.config["require_close_reason"] and message is None: raise commands.BadArgument("Provide a reason for closing the thread.") - if after and after.dt > now: + if after and after.dt > after.now: await self.send_scheduled_close_message(ctx, after, silent) await thread.close(closer=ctx.author, after=close_after, message=message, silent=silent) @@ -1530,7 +1527,6 @@ async def contact( except ValueError: pass - print(users, silent) if isinstance(category, str): category = category.split() @@ -1857,7 +1853,6 @@ async def block( return await ctx.send(embed=embed) reason = f"by {escape_markdown(ctx.author.name)}#{ctx.author.discriminator}" - now = discord.utils.utcnow() if after is not None: if "%" in reason: @@ -1866,7 +1861,7 @@ async def block( if after.arg: reason += f" until: <t:{unixtime}:R>" - if after.dt > now: + if after.dt > after.now: reason += f" until <t:{unixtime}:f>" reason += "." diff --git a/core/time.py b/core/time.py index b66f84757f..d0698d6381 100644 --- a/core/time.py +++ b/core/time.py @@ -20,8 +20,8 @@ units["seconds"].append("secs") if TYPE_CHECKING: + from discord.ext.commands import Context from typing_extensions import Self - from cogs.utils.context import Context class plural: @@ -82,7 +82,7 @@ def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None): self.dt = now + relativedelta(**data) @classmethod - async def convert(cls, ctx: Context, argument: str) -> Self: + async def convert(cls, ctx: Context, argument: str) -> Self: return cls(argument, now=ctx.message.created_at) @@ -146,14 +146,23 @@ async def transform(self, interaction, value: str) -> datetime.datetime: return short.dt +## CHANGE: Added now class FriendlyTimeResult: dt: datetime.datetime + now: datetime.datetime arg: str - __slots__ = ("dt", "arg") + __slots__ = ("dt", "arg", "now") - def __init__(self, dt: datetime.datetime): + def __init__(self, dt: datetime.datetime, now: datetime.datetime=None): self.dt = dt + self.now = now + + if now is None: + self.now = dt + else: + self.now = now + self.arg = "" async def ensure_constraints( @@ -162,6 +171,7 @@ async def ensure_constraints( if self.dt < now: raise commands.BadArgument("This time is in the past.") + # CHANGE # if not remaining: # if uft.default is None: # raise commands.BadArgument("Missing argument after the time.") @@ -200,7 +210,7 @@ async def convert(self, ctx: Context, argument: str) -> FriendlyTimeResult: if match is not None and match.group(0): data = {k: int(v) for k, v in match.groupdict(default=0).items()} remaining = argument[match.end() :].strip() - result = FriendlyTimeResult(now + relativedelta(**data)) + result = FriendlyTimeResult(now + relativedelta(**data), now) await result.ensure_constraints(ctx, self, now, remaining) return result @@ -208,7 +218,7 @@ async def convert(self, ctx: Context, argument: str) -> FriendlyTimeResult: match = ShortTime.discord_fmt.match(argument) if match is not None: result = FriendlyTimeResult( - datetime.datetime.fromtimestamp(int(match.group("ts")), tz=datetime.timezone.utc) + datetime.datetime.fromtimestamp(int(match.group("ts")), now, tz=datetime.timezone.utc) ) remaining = argument[match.end() :].strip() await result.ensure_constraints(ctx, self, now, remaining) @@ -226,7 +236,10 @@ async def convert(self, ctx: Context, argument: str) -> FriendlyTimeResult: elements = calendar.nlp(argument, sourceTime=now) if elements is None or len(elements) == 0: - raise commands.BadArgument('Invalid time provided, try e.g. "tomorrow" or "3 days".') + # CHANGE + result = FriendlyTimeResult(now) + await result.ensure_constraints(ctx, self, now, argument) + return result # handle the following cases: # "date time" foo @@ -254,7 +267,7 @@ async def convert(self, ctx: Context, argument: str) -> FriendlyTimeResult: if status.accuracy == pdt.pdtContext.ACU_HALFDAY: dt = dt.replace(day=now.day + 1) - result = FriendlyTimeResult(dt.replace(tzinfo=datetime.timezone.utc)) + result = FriendlyTimeResult(dt.replace(tzinfo=datetime.timezone.utc), now) remaining = "" if begin in (0, 1): From 30430a6c255407729472445961c11dd9c6a4bf06 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 7 Sep 2022 00:10:19 +0800 Subject: [PATCH 128/225] bump ver --- bot.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index a990ac772c..7c9f19f920 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev19" +__version__ = "4.0.0-dev20" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 9a22625dba..f4faae86fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev19' +version = '4.0.0-dev20' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 420d4dc577c1ac5d68360dac81a9f9a023d473b0 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 7 Sep 2022 00:10:56 +0800 Subject: [PATCH 129/225] formatting --- cogs/modmail.py | 8 +++++++- core/time.py | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index 279df07dd6..d1528f9b46 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -464,7 +464,13 @@ async def send_scheduled_close_message(self, ctx, after, silent=False): @commands.command(usage="[after] [close message]") @checks.has_permissions(PermissionLevel.SUPPORTER) @checks.thread_only() - async def close(self, ctx, option: Optional[Literal["silent", "silently", "cancel"]]='', *, after: UserFriendlyTime = None): + async def close( + self, + ctx, + option: Optional[Literal["silent", "silently", "cancel"]] = "", + *, + after: UserFriendlyTime = None, + ): """ Close the current thread. diff --git a/core/time.py b/core/time.py index d0698d6381..90aca9c021 100644 --- a/core/time.py +++ b/core/time.py @@ -82,7 +82,7 @@ def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None): self.dt = now + relativedelta(**data) @classmethod - async def convert(cls, ctx: Context, argument: str) -> Self: + async def convert(cls, ctx: Context, argument: str) -> Self: return cls(argument, now=ctx.message.created_at) @@ -154,7 +154,7 @@ class FriendlyTimeResult: __slots__ = ("dt", "arg", "now") - def __init__(self, dt: datetime.datetime, now: datetime.datetime=None): + def __init__(self, dt: datetime.datetime, now: datetime.datetime = None): self.dt = dt self.now = now From 711fb68c4d0378b3f79a83ce18a1778ffc1d2f64 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 7 Sep 2022 00:13:18 +0800 Subject: [PATCH 130/225] formatting --- bot.py | 1 - cogs/modmail.py | 1 - cogs/utility.py | 2 +- core/time.py | 4 ++-- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/bot.py b/bot.py index 7c9f19f920..5eb3378d45 100644 --- a/bot.py +++ b/bot.py @@ -18,7 +18,6 @@ import discord import isodate from aiohttp import ClientSession, ClientResponseError -from discord.utils import MISSING from discord.ext import commands, tasks from discord.ext.commands.view import StringView from emoji import UNICODE_EMOJI diff --git a/cogs/modmail.py b/cogs/modmail.py index d1528f9b46..ecdf7144e6 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -2,7 +2,6 @@ import re from datetime import datetime, timezone from itertools import zip_longest -import time from typing import Optional, Union, List, Tuple, Literal from types import SimpleNamespace diff --git a/cogs/utility.py b/cogs/utility.py index 7f623141b7..af0e70beec 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -197,7 +197,7 @@ async def send_error_message(self, error): if snippet_aliases: embed.add_field( - name=f"Aliases to this snippet:", value=",".join(snippet_aliases), inline=False + name="Aliases to this snippet:", value=",".join(snippet_aliases), inline=False ) return await self.get_destination().send(embed=embed) diff --git a/core/time.py b/core/time.py index 90aca9c021..99c1ed7713 100644 --- a/core/time.py +++ b/core/time.py @@ -111,7 +111,7 @@ class Time(HumanTime): def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None): try: o = ShortTime(argument, now=now) - except Exception as e: + except Exception: super().__init__(argument) else: self.dt = o.dt @@ -146,7 +146,7 @@ async def transform(self, interaction, value: str) -> datetime.datetime: return short.dt -## CHANGE: Added now +# CHANGE: Added now class FriendlyTimeResult: dt: datetime.datetime now: datetime.datetime From 3d7b6261ea5c7e7eb36da0cc9c2962621e475b39 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 7 Sep 2022 00:25:22 +0800 Subject: [PATCH 131/225] add comnts to lint file --- .github/workflows/lints.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index a7418930be..21bf39368e 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -23,6 +23,7 @@ jobs: run: | python -m pip install --upgrade pip pipenv pipenv install --dev --system + # to refresh: bandit -f json -o .bandit_baseline.json -r . # - name: Bandit syntax check # run: bandit -r . -b .bandit_baseline.json - name: Pylint From 039347fb05b38ab39b4ea0acad7be3ee1cab27e1 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 20 Sep 2022 22:10:47 +0800 Subject: [PATCH 132/225] Use new timestamps for userinfo and fix potential blocked parsing --- bot.py | 2 +- cogs/modmail.py | 48 ++++++++++++++++++++++++++++++++++++++---------- core/thread.py | 9 ++++----- core/time.py | 13 ++----------- pyproject.toml | 2 +- 5 files changed, 46 insertions(+), 28 deletions(-) diff --git a/bot.py b/bot.py index a96a58fd6e..23c911b8ea 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0-dev20" +__version__ = "4.0.0" import asyncio diff --git a/cogs/modmail.py b/cogs/modmail.py index ecdf7144e6..85b4af62ac 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1654,21 +1654,48 @@ async def blocked(self, ctx): blocked_users = list(self.bot.blocked_users.items()) for id_, reason in blocked_users: # parse "reason" and check if block is expired - # etc "blah blah blah... until 2019-10-14T21:12:45.559948." - end_time = re.search(r"until ([^`]+?)\.$", reason) - if end_time is None: + # etc "blah blah blah... until <t:XX:f>." + end_time = re.search(r"until <t:(\d+):(?:R|f)>.$", reason) + attempts = [ # backwards compat - end_time = re.search(r"%([^%]+?)%", reason) + re.search(r"until ([^`]+?)\.$", reason), + re.search(r"%([^%]+?)%", reason), + ] + if end_time is None: + for i in attempts: + if i is not None: + end_time = i + break + if end_time is not None: + # found a deprecated version + try: + after = ( + datetime.fromisoformat(end_time.group(1)).replace(tzinfo=timezone.utc) - now + ).total_seconds() + except ValueError: + logger.warning( + r"Broken block message for user %s, block and unblock again with a different message to prevent further issues", + id_, + ) + continue logger.warning( r"Deprecated time message for user %s, block and unblock again to update.", id_, ) + else: + try: + after = ( + datetime.fromtimestamp(int(end_time.group(1))).replace(tzinfo=timezone.utc) - now + ).total_seconds() + except ValueError: + logger.warning( + r"Broken block message for user %s, block and unblock again with a different message to prevent further issues", + id_, + ) + continue if end_time is not None: - after = ( - datetime.fromisoformat(end_time.group(1)).replace(tzinfo=timezone.utc) - now - ).total_seconds() if after <= 0: # No longer blocked self.bot.blocked_users.pop(str(id_)) @@ -1862,12 +1889,13 @@ async def block( if after is not None: if "%" in reason: raise commands.BadArgument('The reason contains illegal character "%".') - unixtime = int(after.dt.replace(tzinfo=timezone.utc).timestamp()) if after.arg: - reason += f" until: <t:{unixtime}:R>" + fmt_dt = discord.utils.format_dt(after.dt, "R") if after.dt > after.now: - reason += f" until <t:{unixtime}:f>" + fmt_dt = discord.utils.format_dt(after.dt, "f") + + reason += f" until {fmt_dt}" reason += "." diff --git a/core/thread.py b/core/thread.py index 606a204b37..99a805fef5 100644 --- a/core/thread.py +++ b/core/thread.py @@ -322,10 +322,10 @@ def _format_info_embed(self, user, log_url, log_count, color): role_names = separator.join(roles) - created = str((time - user.created_at).days) user_info = [] if self.bot.config["thread_show_account_age"]: - user_info.append(f" was created {days(created)}") + created = discord.utils.format_dt(user.created_at, "R") + user_info.append(f" was created {created}") embed = discord.Embed(color=color, description=user.mention, timestamp=time) @@ -337,10 +337,9 @@ def _format_info_embed(self, user, log_url, log_count, color): if member is not None: embed.set_author(name=str(user), icon_url=member.display_avatar.url, url=log_url) - joined = str((time - member.joined_at).days) - # embed.add_field(name='Joined', value=joined + days(joined)) if self.bot.config["thread_show_join_age"]: - user_info.append(f"joined {days(joined)}") + joined = discord.utils.format_dt(member.joined_at, "R") + user_info.append(f"joined {joined}") if member.nick: embed.add_field(name="Nickname", value=member.nick, inline=True) diff --git a/core/time.py b/core/time.py index 99c1ed7713..64dcd88507 100644 --- a/core/time.py +++ b/core/time.py @@ -6,6 +6,7 @@ from __future__ import annotations import datetime +import discord from typing import TYPE_CHECKING, Any, Optional, Union import parsedatetime as pdt from dateutil.relativedelta import relativedelta @@ -39,16 +40,6 @@ def __format__(self, format_spec: str) -> str: return f"{v} {singular}" -def format_dt(dt: datetime.datetime, style: Optional[str] = None) -> str: - """https://github.com/Rapptz/RoboDanny/blob/bf7d4226350dff26df4981dd53134eeb2aceeb87/cogs/utils/formats.py#L89-L95""" - if dt.tzinfo is None: - dt = dt.replace(tzinfo=datetime.timezone.utc) - - if style is None: - return f"<t:{int(dt.timestamp())}>" - return f"<t:{int(dt.timestamp())}:{style}>" - - class ShortTime: compiled = re.compile( """ @@ -365,4 +356,4 @@ def human_timedelta( def format_relative(dt: datetime.datetime) -> str: - return format_dt(dt, "R") + return discord.utils.format_dt(dt, "R") diff --git a/pyproject.toml b/pyproject.toml index f4faae86fd..a19e436399 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0-dev20' +version = '4.0.0' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From ba4d6fb81fe61628fda805d56d5d9a0a2f560cdf Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 20 Sep 2022 22:11:47 +0800 Subject: [PATCH 133/225] Fix removeprefix issue by @Jerrie-Aries https://github.com/kyb3r/modmail/commit/ecc92e4bbf44d0f44d2df902e16a30734320070e#r83768323 --- bot.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 23c911b8ea..52ba65b960 100644 --- a/bot.py +++ b/bot.py @@ -1000,7 +1000,8 @@ async def get_contexts(self, message, *, cls=commands.Context): # This needs to be done before checking for aliases since # snippets can have multiple words. try: - snippet_text = self.snippets[message.content.strip(invoked_prefix)] + # Use removeprefix once PY3.9+ + snippet_text = self.snippets[message.content[len(invoked_prefix) :]] except KeyError: snippet_text = None From c6b4f530de7765839278546ed7351433450d99f9 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 20 Sep 2022 22:31:04 +0800 Subject: [PATCH 134/225] Fix block logic and rewrite into helper function --- bot.py | 41 +++++++++++------------------------ cogs/modmail.py | 57 +++++++------------------------------------------ core/thread.py | 1 - core/time.py | 4 ++-- core/utils.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 80 deletions(-) diff --git a/bot.py b/bot.py index 52ba65b960..9f13e3e04e 100644 --- a/bot.py +++ b/bot.py @@ -47,7 +47,7 @@ ) from core.thread import ThreadManager from core.time import human_timedelta -from core.utils import normalize_alias, parse_alias, truncate, tryint +from core.utils import extract_block_timestamp, normalize_alias, parse_alias, truncate, tryint logger = getLogger(__name__) @@ -735,21 +735,13 @@ def check_manual_blocked_roles(self, author: discord.Member) -> bool: if str(r.id) in self.blocked_roles: blocked_reason = self.blocked_roles.get(str(r.id)) or "" - now = discord.utils.utcnow() - - # etc "blah blah blah... until 2019-10-14T21:12:45.559948." - end_time = re.search(r"until ([^`]+?)\.$", blocked_reason) - if end_time is None: - # backwards compat - end_time = re.search(r"%([^%]+?)%", blocked_reason) - if end_time is not None: - logger.warning( - r"Deprecated time message for role %s, block and unblock again to update.", - r.name, - ) + + try: + end_time, after = extract_block_timestamp(blocked_reason, author.id) + except ValueError: + return False if end_time is not None: - after = (datetime.fromisoformat(end_time.group(1)) - now).total_seconds() if after <= 0: # No longer blocked self.blocked_roles.pop(str(r.id)) @@ -765,26 +757,19 @@ def check_manual_blocked(self, author: discord.Member) -> bool: return True blocked_reason = self.blocked_users.get(str(author.id)) or "" - now = discord.utils.utcnow() if blocked_reason.startswith("System Message:"): # Met the limits already, otherwise it would've been caught by the previous checks logger.debug("No longer internally blocked, user %s.", author.name) self.blocked_users.pop(str(author.id)) return True - # etc "blah blah blah... until 2019-10-14T21:12:45.559948." - end_time = re.search(r"until ([^`]+?)\.$", blocked_reason) - if end_time is None: - # backwards compat - end_time = re.search(r"%([^%]+?)%", blocked_reason) - if end_time is not None: - logger.warning( - r"Deprecated time message for user %s, block and unblock again to update.", - author.name, - ) + + try: + end_time, after = extract_block_timestamp(blocked_reason, author.id) + except ValueError: + return False if end_time is not None: - after = (datetime.fromisoformat(end_time.group(1)) - now).total_seconds() if after <= 0: # No longer blocked self.blocked_users.pop(str(author.id)) @@ -891,7 +876,7 @@ async def add_reaction( if reaction != "disable": try: await msg.add_reaction(reaction) - except (discord.HTTPException, discord.InvalidArgument) as e: + except (discord.HTTPException, discord.BadArgument) as e: logger.warning("Failed to add reaction %s: %s.", reaction, e) return False return True @@ -1316,7 +1301,7 @@ async def handle_reaction_events(self, payload): for msg in linked_messages: await msg.remove_reaction(reaction, self.user) await message.remove_reaction(reaction, self.user) - except (discord.HTTPException, discord.InvalidArgument) as e: + except (discord.HTTPException, discord.BadArgument) as e: logger.warning("Failed to remove reaction: %s", e) async def handle_react_to_contact(self, payload): diff --git a/cogs/modmail.py b/cogs/modmail.py index 85b4af62ac..b6ebe81baf 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1654,46 +1654,10 @@ async def blocked(self, ctx): blocked_users = list(self.bot.blocked_users.items()) for id_, reason in blocked_users: # parse "reason" and check if block is expired - # etc "blah blah blah... until <t:XX:f>." - end_time = re.search(r"until <t:(\d+):(?:R|f)>.$", reason) - attempts = [ - # backwards compat - re.search(r"until ([^`]+?)\.$", reason), - re.search(r"%([^%]+?)%", reason), - ] - if end_time is None: - for i in attempts: - if i is not None: - end_time = i - break - - if end_time is not None: - # found a deprecated version - try: - after = ( - datetime.fromisoformat(end_time.group(1)).replace(tzinfo=timezone.utc) - now - ).total_seconds() - except ValueError: - logger.warning( - r"Broken block message for user %s, block and unblock again with a different message to prevent further issues", - id_, - ) - continue - logger.warning( - r"Deprecated time message for user %s, block and unblock again to update.", - id_, - ) - else: - try: - after = ( - datetime.fromtimestamp(int(end_time.group(1))).replace(tzinfo=timezone.utc) - now - ).total_seconds() - except ValueError: - logger.warning( - r"Broken block message for user %s, block and unblock again with a different message to prevent further issues", - id_, - ) - continue + try: + end_time, after = extract_block_timestamp(reason, id_) + except ValueError: + continue if end_time is not None: if after <= 0: @@ -1713,15 +1677,10 @@ async def blocked(self, ctx): for id_, reason in blocked_roles: # parse "reason" and check if block is expired # etc "blah blah blah... until 2019-10-14T21:12:45.559948." - end_time = re.search(r"until ([^`]+?)\.$", reason) - if end_time is None: - # backwards compat - end_time = re.search(r"%([^%]+?)%", reason) - if end_time is not None: - logger.warning( - r"Deprecated time message for role %s, block and unblock again to update.", - id_, - ) + try: + end_time, after = extract_block_timestamp(reason, id_) + except ValueError: + continue if end_time is not None: after = (datetime.fromisoformat(end_time.group(1)) - now).total_seconds() diff --git a/core/thread.py b/core/thread.py index 99a805fef5..c9d8ae5bcb 100644 --- a/core/thread.py +++ b/core/thread.py @@ -22,7 +22,6 @@ from core.time import human_timedelta from core.utils import ( is_image_url, - days, parse_channel_topic, match_title, match_user_id, diff --git a/core/time.py b/core/time.py index 64dcd88507..963eac5a6e 100644 --- a/core/time.py +++ b/core/time.py @@ -63,7 +63,7 @@ def __init__(self, argument: str, *, now: Optional[datetime.datetime] = None): if match is None or not match.group(0): match = self.discord_fmt.fullmatch(argument) if match is not None: - self.dt = datetime.datetime.fromtimestamp(int(match.group("ts")), tz=datetime.timezone.utc) + self.dt = datetime.datetime.utcfromtimestamp(int(match.group("ts")), tz=datetime.timezone.utc) return else: raise commands.BadArgument("invalid time provided") @@ -209,7 +209,7 @@ async def convert(self, ctx: Context, argument: str) -> FriendlyTimeResult: match = ShortTime.discord_fmt.match(argument) if match is not None: result = FriendlyTimeResult( - datetime.datetime.fromtimestamp(int(match.group("ts")), now, tz=datetime.timezone.utc) + datetime.datetime.utcfromtimestamp(int(match.group("ts")), now, tz=datetime.timezone.utc) ) remaining = argument[match.end() :].strip() await result.ensure_constraints(ctx, self, now, remaining) diff --git a/core/utils.py b/core/utils.py index ce28f243c1..30130eb740 100644 --- a/core/utils.py +++ b/core/utils.py @@ -2,6 +2,7 @@ import functools import re import typing +from datetime import datetime, timezone from difflib import get_close_matches from distutils.util import strtobool as _stb # pylint: disable=import-error from itertools import takewhile, zip_longest @@ -10,6 +11,9 @@ import discord from discord.ext import commands +from core.models import getLogger + + __all__ = [ "strtobool", "User", @@ -34,9 +38,13 @@ "tryint", "get_top_role", "get_joint_id", + "extract_block_timestamp", ] +logger = getLogger(__name__) + + def strtobool(val): if isinstance(val, bool): return val @@ -504,3 +512,50 @@ def get_joint_id(message: discord.Message) -> typing.Optional[int]: except ValueError: pass return None + + +def extract_block_timestamp(reason, id_): + # etc "blah blah blah... until <t:XX:f>." + now = discord.utils.utcnow() + end_time = re.search(r"until <t:(\d+):(?:R|f)>.$", reason) + attempts = [ + # backwards compat + re.search(r"until ([^`]+?)\.$", reason), + re.search(r"%([^%]+?)%", reason), + ] + after = None + if end_time is None: + for i in attempts: + if i is not None: + end_time = i + break + + if end_time is not None: + # found a deprecated version + try: + after = ( + datetime.fromisoformat(end_time.group(1)).replace(tzinfo=timezone.utc) - now + ).total_seconds() + except ValueError: + logger.warning( + r"Broken block message for user %s, block and unblock again with a different message to prevent further issues", + id_, + ) + raise + logger.warning( + r"Deprecated time message for user %s, block and unblock again to update.", + id_, + ) + else: + try: + after = ( + datetime.utcfromtimestamp(int(end_time.group(1))).replace(tzinfo=timezone.utc) - now + ).total_seconds() + except ValueError: + logger.warning( + r"Broken block message for user %s, block and unblock again with a different message to prevent further issues", + id_, + ) + raise + + return end_time, after From ebfd37baccfacf3aa9f34100ae1a3b91e6e7ec7f Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 20 Sep 2022 22:33:23 +0800 Subject: [PATCH 135/225] Purge Registry --- plugins/registry.json | 260 +----------------------------------------- 1 file changed, 1 insertion(+), 259 deletions(-) diff --git a/plugins/registry.json b/plugins/registry.json index ad8dbebaf9..9e26dfeeb6 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -1,259 +1 @@ -{ - "close_message": { - "repository": "python-discord/modmail-plugins", - "branch": "main", - "description": "Add a ?closemessage command that will close the thread after 15 minutes with a default message.", - "bot_version": "2.20.1", - "title": "Close message", - "icon_url": "https://i.imgur.com/ev7BFMz.png", - "thumbnail_url": "https://i.imgur.com/ev7BFMz.png" - }, - "mdlink": { - "repository": "python-discord/modmail-plugins", - "branch": "main", - "description": "Generate a ready to paste link to the thread logs.", - "bot_version": "2.20.1", - "title": "MDLink", - "icon_url": "https://i.imgur.com/JA2E63R.png", - "thumbnail_url": "https://i.imgur.com/JA2E63R.png" - }, - "reply_cooldown": { - "repository": "python-discord/modmail-plugins", - "branch": "main", - "description": "Forbid you from sending the same message twice in ten seconds.", - "bot_version": "2.20.1", - "title": "Reply cooldown", - "icon_url": "https://i.imgur.com/FtRQveT.png", - "thumbnail_url": "https://i.imgur.com/FtRQveT.png" - }, - "dragory-migrate": { - "repository": "kyb3r/modmail-plugins", - "branch": "master", - "description": "Migrate your logs from Dragory's modmail bot to this one with a simple command. Added at the request of users.", - "bot_version": "2.20.1", - "title": "Dragory Logs Migration", - "icon_url": "https://cdn1.iconfinder.com/data/icons/web-hosting-2-4/52/200-512.png", - "thumbnail_url": "https://cdn1.iconfinder.com/data/icons/web-hosting-2-4/52/200-512.png" - }, - "music": { - "repository": "Taaku18/modmail-plugins", - "branch": "master", - "description": "Play wonderfull jams through your modmail!", - "bot_version": "2.20.1", - "title": "music", - "icon_url": "https://i.imgur.com/JmJPX5W.gif", - "thumbnail_url": "https://i.imgur.com/jrYL7F8.gif" - }, - "media-only": { - "repository": "lorenzo132/modmail-plugins", - "branch": "master", - "description": "Make a channel mediaonly, only the following mediatypes will be accepted `.png` / `.gif` / `.jpg` / `.mp4`/ `.jpeg`", - "bot_version": "2.20.1", - "title": "Media-only", - "icon_url": "https://i.imgur.com/ussAoIi.png", - "thumbnail_url": "https://i.imgur.com/ussAoIi.png" - }, - "anti-steal-close": { - "repository": "officialpiyush/modmail-plugins", - "branch": "master", - "description": "Don't let anyone steal ya close.", - "title": "Anti Steal Close", - "icon_url": "https://i.imgur.com/LovxyV3.png", - "thumbnail_url": "https://i.imgur.com/LovxyV3.png" - }, - "announcement": { - "repository": "officialpiyush/modmail-plugins", - "branch": "master", - "description": "Easily make announcements in your server!", - "bot_version": "2.20.1", - "title": "Announcement Plugin", - "icon_url": "https://images.ionadev.ml/b/ZIDUUsl.png", - "thumbnail_url": "https://images.ionadev.ml/b/ZIDUUsl.png" - }, - "dm-on-join": { - "repository": "officialpiyush/modmail-plugins", - "branch": "master", - "description": "DM New Users when they join", - "bot_version": "2.20.1", - "title": "DM-on-join Plugin", - "icon_url": "https://images.ionadev.ml/b/ZIDUUsl.png", - "thumbnail_url": "https://images.ionadev.ml/b/ZIDUUsl.png" - }, - "giveaway": { - "repository": "officialpiyush/modmail-plugins", - "branch": "master", - "description": "Host giveaways on your server", - "bot_version": "2.20.1", - "title": "\uD83C\uDF89 Giveaway Plugin \uD83C\uDF89", - "icon_url": "https://i.imgur.com/qk85xdi.png", - "thumbnail_url": "https://i.imgur.com/gUHB91v.png" - }, - "hastebin": { - "repository": "officialpiyush/modmail-plugins", - "branch": "master", - "description": "Easily Upload Text To hastebin!", - "bot_version": "2.20.1", - "title": "Hastebin Plugin", - "icon_url": "https://images.ionadev.ml/b/ZIDUUsl.png", - "thumbnail_url": "https://images.ionadev.ml/b/ZIDUUsl.png" - }, - "leave-server": { - "repository": "officialpiyush/modmail-plugins", - "branch": "master", - "description": "Don't want your bot in a server? Did someone invite it without your permission? If so, this plugin is useful for you!", - "bot_version": "2.20.1", - "title": "Leave-server Plugin", - "icon_url": "https://images.ionadev.ml/b/ZIDUUsl.png", - "thumbnail_url": "https://images.ionadev.ml/b/ZIDUUsl.png" - }, - "welcomer": { - "repository": "fourjr/modmail-plugins", - "branch": "master", - "description": "Add messages to welcome new members! Allows for embedded messages as well. [Read more](https://github.com/fourjr/modmail-plugins/blob/master/welcomer/README.md)", - "bot_version": "2.20.1", - "title": "New member messages plugin", - "icon_url": "https://cdn.discordapp.com/avatars/180314310298304512/7552e0089004079304cc9912d13ac81d.png", - "thumbnail_url": "https://cdn.discordapp.com/avatars/180314310298304512/7552e0089004079304cc9912d13ac81d.png" - }, - "tags": { - "repository": "officialpiyush/modmail-plugins", - "branch": "master", - "description": "Tag Management For Your Server", - "bot_version": "2.20.1", - "title": "Tags Plugin", - "icon_url": "https://images.ionadev.ml/b/ZIDUUsl.png", - "thumbnail_url": "https://images.ionadev.ml/b/ZIDUUsl.png" - }, - "backupdb": { - "repository": "officialpiyush/modmail-plugins", - "branch": "master", - "description": "Backup you're current Modmail DB with a single command!\n\n**Requires `BACKUP_MONGO_URI` in either config.json or environment variables**", - "bot_version": "2.20.1", - "title": "Backup Database (backupdb)", - "icon_url": "https://images.ionadev.ml/b/nKAlOC4.jpg", - "thumbnail_url": "https://images.ionadev.ml/b/nKAlOC4.jpg" - }, - "colors": { - "repository": "Taaku18/modmail-plugins", - "branch": "master", - "description": "Conversions between hex, RGB, and color names.", - "bot_version": "2.20.1", - "title": "Colors!!", - "icon_url": "https://cdn1.iconfinder.com/data/icons/weather-19/32/rainbow-512.png", - "thumbnail_url": "https://i.imgur.com/fSxnc9W.jpg" - }, - "fun": { - "repository": "TheKinG2149/modmail-plugins", - "branch": "master", - "description": "Some fun commands like 8ball, dadjokes", - "bot_version": "2.24.1", - "title": "Fun", - "icon_url": "https://cdn.discordapp.com/attachments/584692239893135362/591588754142265354/43880032.png", - "thumbnail_url": "https://cdn.discordapp.com/attachments/584692239893135362/591588754142265354/43880032.png" - }, - "stats": { - "repository": "KarateWumpus/modmail-plugins", - "branch": "master", - "description": "Get useful stats directly in an embed about either the Modmail bot, a user or the server.", - "bot_version": "2.24.1", - "title": "Get Stats", - "icon_url": "https://image.flaticon.com/icons/png/512/117/117761.png", - "thumbnail_url": "http://www.pngmart.com/files/7/Statistics-PNG-Clipart.png" - }, - "moderation": { - "repository": "Vincysuper07/modmail-plugins", - "branch": "main", - "description": "Moderate your server with Modmail, bring the Mod to Modmail!", - "bot_version": "3.6.2", - "title": "Moderate your server", - "icon_url": "https://cdn.discordapp.com/attachments/759829573654544454/773535811143598110/ad2e4d6e7b90ca6005a5038e22b099cc.png", - "thumbnail_url": "https://cdn.discordapp.com/attachments/759829573654544454/773535811143598110/ad2e4d6e7b90ca6005a5038e22b099cc.png" - }, - "serverstats": { - "repository": "dazvise/modmail-plugins", - "branch": "master", - "description": "Voice channels containing interesting and accurate statistics about your server such as Member Count.", - "bot_version": "2.20.1", - "title": "Server Stats", - "icon_url": "https://i.gyazo.com/fadb70740e83f2448b23ffe192a1f32d.png", - "thumbnail_url": "https://i.gyazo.com/fadb70740e83f2448b23ffe192a1f32d.png" - }, - "suggest": { - "repository": "realcyguy/modmail-plugins", - "branch": "master", - "description": "Send suggestions to a selected server! It has accepting, denying, and moderation-ing.", - "bot_version": "3.4.1", - "title": "Suggest stuff.", - "icon_url": "https://i.imgur.com/qtE7AH8.png", - "thumbnail_url": "https://i.imgur.com/qtE7AH8.png" - }, - "githubstats": { - "repository": "mischievousdev/modmail-plugins", - "branch": "master", - "description": "Github statistics in discord", - "bot_version": "2.20.1", - "title": "Github Stats", - "icon_url": "https://raw.githubusercontent.com/mischievousdev/modmail-plugins/master/download%20(9).jpeg", - "thumbnail_url": "https://raw.githubusercontent.com/mischievousdev/modmail-plugins/master/download%20(9).jpeg" - }, - "slowmode": { - "repository": "teen1/modmail-plugins", - "branch": "master", - "description": "Configure slow mode for your channels with Modmail!", - "bot_version": "2.20.1", - "title": "Slow Mode", - "icon_url": "https://cdn.discordapp.com/attachments/717029057635549274/717033838966210601/Slow_mode_-_icon.png", - "thumbnail_url": "https://cdn.discordapp.com/attachments/717029057635549274/717029110907666482/Slow_mode_plugin_-_thumbnail.png" - }, - "translate": { - "repository": "WebKide/modmail-plugins", - "branch": "master", - "description": "(โˆฉ๏ฝ€-ยด)โŠƒโ”โ˜†๏พŸ.*๏ฝฅ๏ฝก๏พŸ translate text from one language to another (defaults to English)\n\nGet full list of available languages at: https://github.com/WebKide/modmail-plugins/blob/master/translate/langs.json\n\nThis command conflicts with Translator-plugin", - "bot_version": "3.5.0", - "title": "Translate", - "icon_url": "https://i.imgur.com/yeHFKgl.png", - "thumbnail_url": "https://i.imgur.com/yeHFKgl.png" - }, - "countdowns": { - "repository": "fourjr/modmail-plugins", - "branch": "master", - "description": "Setup a countdown voice channel in your server!", - "bot_version": "3.6.2", - "title": "Countdowns", - "icon_url": "https://cdn.discordapp.com/avatars/180314310298304512/7552e0089004079304cc9912d13ac81d.png", - "thumbnail_url": "https://cdn.discordapp.com/avatars/180314310298304512/7552e0089004079304cc9912d13ac81d.png" - }, - "action": { - "repository": "6days9weeks/modmail-plugins", - "branch": "master", - "description": "Have fun with others by hugging them or giving them pats~!!", - "title": "Action", - "icon_url": "https://media.discordapp.net/attachments/720733784970100776/820933433579798528/689105042212388965.png", - "thumbnail_url": "https://data.whicdn.com/images/58526601/original.gif" - }, - "menu": { - "repository": "fourjr/modmail-plugins", - "branch": "master", - "description": "Adds reaction-based menus into thread creates. Check out `?configmenu`", - "title": "Menus", - "bot_version": "3.9.0", - "icon_url": "https://cdn.discordapp.com/avatars/180314310298304512/7552e0089004079304cc9912d13ac81d.png", - "thumbnail_url": "https://cdn.discordapp.com/avatars/180314310298304512/7552e0089004079304cc9912d13ac81d.png" - }, - "claim": { - "repository": "fourjr/modmail-plugins", - "branch": "master", - "description": "Allows supporters to claim thread by sending ?claim in the thread channel", - "title": "Claim Thread", - "icon_url": "https://cdn.discordapp.com/avatars/180314310298304512/7552e0089004079304cc9912d13ac81d.png", - "thumbnail_url": "https://cdn.discordapp.com/avatars/180314310298304512/7552e0089004079304cc9912d13ac81d.png" - }, - "phishchecker": { - "repository": "TheDiscordHistorian/historian-cogs", - "branch": "main", - "description": "Deletes scam links from your server and optionally kick / ban the user.", - "title": "Scam Link Detector", - "icon_url": "https://cdn.discordapp.com/attachments/576521645540245505/895661244743299102/antifish.png", - "thumbnail_url": "https://cdn.discordapp.com/attachments/576521645540245505/895661244743299102/antifish.png" - } -} +{} \ No newline at end of file From 7c2875c9e1db45f4120da17cb5dff85c7134f043 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 20 Sep 2022 22:34:00 +0800 Subject: [PATCH 136/225] Lock registry version --- cogs/plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/plugins.py b/cogs/plugins.py index 4cdd0aba3f..dc4c89aa6b 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -131,7 +131,7 @@ def __init__(self, bot): logger.info("Plugins not loaded since ENABLE_PLUGINS=false.") async def populate_registry(self): - url = "https://raw.githubusercontent.com/kyb3r/modmail/master/plugins/registry.json" + url = "https://raw.githubusercontent.com/kyb3r/modmail/be14cca89742cd691f6b91f0d0931a074ad81e3b/plugins/registry.json" async with self.bot.session.get(url) as resp: self.registry = json.loads(await resp.text()) From b7e25a0d5eed17808911a8532338c6bd3ba061f2 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 20 Sep 2022 22:35:11 +0800 Subject: [PATCH 137/225] Upgrade version to 3.10.5 with locked registry --- CHANGELOG.md | 3 +++ bot.py | 2 +- pyproject.toml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f9b461169..268ee82a1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html); however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. +# v3.10.5 +Locked plugin registry version impending v4 release. + # v3.10.3 This is a hotfix for contact command. diff --git a/bot.py b/bot.py index 0ee38be340..5113f367f8 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "3.10.3" +__version__ = "3.10.5" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 341e506413..cad728fd2a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '3.10.3' +version = '3.10.5' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 1f9f633ae1111b04701c137da192dc1d3d63a493 Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 20 Sep 2022 22:36:58 +0800 Subject: [PATCH 138/225] Add suggest plugin #3189 --- plugins/registry.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/plugins/registry.json b/plugins/registry.json index 9e26dfeeb6..494feebee4 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -1 +1,11 @@ -{} \ No newline at end of file +{ + "suggest": { + "repository": "realcyguy/modmail-plugins", + "branch": "v4", + "description": "Send suggestions to a selected server! It has accepting, denying, and moderation-ing.", + "bot_version": "4.0.0", + "title": "Suggest stuff.", + "icon_url": "https://i.imgur.com/qtE7AH8.png", + "thumbnail_url": "https://i.imgur.com/qtE7AH8.png" + } +} \ No newline at end of file From cc4b4ff0aa345fc93dafa9556eacb4ec56d3a15f Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Tue, 20 Sep 2022 22:37:54 +0800 Subject: [PATCH 139/225] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e90aeb637..4c1c3327ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Upgraded to discord.py v2.0 ([internal changes](https://discordpy.readthedocs.io/en/latest/migrating.html), [GH #2990](https://github.com/kyb3r/modmail/issues/2990)). - Python 3.8 or higher is required. - Asyncio changes ([gist](https://gist.github.com/Rapptz/6706e1c8f23ac27c98cee4dd985c8120)) +- Plugin registry is purged and all developers have to re-apply due to breaking changes. ### Added From b04ac7836abae923794cc6ca69e80a434c855fbb Mon Sep 17 00:00:00 2001 From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com> Date: Wed, 21 Sep 2022 00:12:09 +0800 Subject: [PATCH 140/225] Hotfix v4.0.1 for thread cooldown --- CHANGELOG.md | 13 +++++++ Pipfile | 1 + Pipfile.lock | 98 ++++++++++++++++++++++++++++++++++++------------- README.md | 2 +- bot.py | 20 +++++++--- cogs/modmail.py | 1 - cogs/utility.py | 2 +- core/config.py | 4 +- core/thread.py | 2 +- core/time.py | 5 ++- core/utils.py | 2 +- pyproject.toml | 2 +- 12 files changed, 111 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20403c41a2..c46714146c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html); however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. +# v4.0.1 + +This is a hotfix release. + +### Improved + +- Error Messages + +### Fixed + +- Thread cooldown + + # v4.0.0 ### Breaking diff --git a/Pipfile b/Pipfile index 573f06cb76..e61e3b9288 100644 --- a/Pipfile +++ b/Pipfile @@ -23,6 +23,7 @@ python-dateutil = "~=2.8.1" python-dotenv = "==0.20.0" uvloop = {version = ">=0.15.2", markers = "sys_platform != 'win32'"} lottie = {version = "==0.6.11", extras = ["pdf"]} +requests = "==2.28.1" [scripts] bot = "python bot.py" diff --git a/Pipfile.lock b/Pipfile.lock index 9657e2b273..e1c531856e 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "c074bd9564d93aac78141ccfec1138ffeb561dfa0956f60ee5b10322d156d20f" + "sha256": "9d1171901e036b1f78a2e89855d564e9f559736ca076128fa27eb14ee8f917a4" }, "pipfile-spec": 6, "requires": {}, @@ -130,6 +130,14 @@ ], "version": "==2.5.2" }, + "certifi": { + "hashes": [ + "sha256:36973885b9542e6bd01dea287b2b4b3b21236307c56324fcc3f1160f2d655ed5", + "sha256:e232343de1ab72c2aa521b625c80f699e356830fd0e2c620b465b304b17b0516" + ], + "markers": "python_version >= '3.6'", + "version": "==2022.9.14" + }, "cffi": { "hashes": [ "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", @@ -217,11 +225,11 @@ }, "cssselect2": { "hashes": [ - "sha256:3a83b2a68370c69c9cd3fcb88bbfaebe9d22edeef2c22d1ff3e1ed9c7fa45ed8", - "sha256:5b5d6dea81a5eb0c9ca39f116c8578dd413778060c94c1f51196371618909325" + "sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a", + "sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969" ], "markers": "python_version >= '3.7'", - "version": "==0.6.0" + "version": "==0.7.0" }, "defusedxml": { "hashes": [ @@ -321,11 +329,11 @@ }, "idna": { "hashes": [ - "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", - "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" + "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", + "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" ], "markers": "python_version >= '3.5'", - "version": "==3.3" + "version": "==3.4" }, "isodate": { "hashes": [ @@ -507,7 +515,9 @@ "version": "==2.21" }, "pymongo": { - "extras": [], + "extras": [ + "srv" + ], "hashes": [ "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", @@ -570,6 +580,7 @@ "sha256:81a3ebc33b1367f301d1c8eda57eec4868e951504986d5d3fe437479dcdac5b2", "sha256:8455176fd1b86de97d859fed4ae0ef867bf998581f584c7a1a591246dfec330f", "sha256:845b178bd127bb074835d2eac635b980c58ec5e700ebadc8355062df708d5a71", + "sha256:858af7c2ab98f21ed06b642578b769ecfcabe4754648b033168a91536f7beef9", "sha256:87e18f29bac4a6be76a30e74de9c9005475e27100acf0830679420ce1fd9a6fd", "sha256:89d7baa847383b9814de640c6f1a8553d125ec65e2761ad146ea2e75a7ad197c", "sha256:8c7ad5cab282f53b9d78d51504330d1c88c83fbe187e472c07e6908a0293142e", @@ -636,6 +647,14 @@ "index": "pypi", "version": "==0.20.0" }, + "requests": { + "hashes": [ + "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", + "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" + ], + "index": "pypi", + "version": "==2.28.1" + }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", @@ -652,27 +671,49 @@ "markers": "python_version >= '3.6'", "version": "==1.1.1" }, + "urllib3": { + "hashes": [ + "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e", + "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'", + "version": "==1.26.12" + }, "uvloop": { "hashes": [ - "sha256:04ff57aa137230d8cc968f03481176041ae789308b4d5079118331ab01112450", - "sha256:089b4834fd299d82d83a25e3335372f12117a7d38525217c2258e9b9f4578897", - "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861", - "sha256:30ba9dcbd0965f5c812b7c2112a1ddf60cf904c1c160f398e7eed3a6b82dcd9c", - "sha256:3a19828c4f15687675ea912cc28bbcb48e9bb907c801873bd1519b96b04fb805", - "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d", - "sha256:647e481940379eebd314c00440314c81ea547aa636056f554d491e40503c8464", - "sha256:6ccd57ae8db17d677e9e06192e9c9ec4bd2066b77790f9aa7dede2cc4008ee8f", - "sha256:772206116b9b57cd625c8a88f2413df2fcfd0b496eb188b82a43bed7af2c2ec9", - "sha256:8e0d26fa5875d43ddbb0d9d79a447d2ace4180d9e3239788208527c4784f7cab", - "sha256:98d117332cc9e5ea8dfdc2b28b0a23f60370d02e1395f88f40d1effd2cb86c4f", - "sha256:b572256409f194521a9895aef274cea88731d14732343da3ecdb175228881638", - "sha256:bd53f7f5db562f37cd64a3af5012df8cac2c464c97e732ed556800129505bd64", - "sha256:bd8f42ea1ea8f4e84d265769089964ddda95eb2bb38b5cbe26712b0616c3edee", - "sha256:e814ac2c6f9daf4c36eb8e85266859f42174a4ff0d71b99405ed559257750382", - "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228" + "sha256:0949caf774b9fcefc7c5756bacbbbd3fc4c05a6b7eebc7c7ad6f825b23998d6d", + "sha256:0ddf6baf9cf11a1a22c71487f39f15b2cf78eb5bde7e5b45fbb99e8a9d91b9e1", + "sha256:1436c8673c1563422213ac6907789ecb2b070f5939b9cbff9ef7113f2b531595", + "sha256:23609ca361a7fc587031429fa25ad2ed7242941adec948f9d10c045bfecab06b", + "sha256:2a6149e1defac0faf505406259561bc14b034cdf1d4711a3ddcdfbaa8d825a05", + "sha256:2deae0b0fb00a6af41fe60a675cec079615b01d68beb4cc7b722424406b126a8", + "sha256:307958f9fc5c8bb01fad752d1345168c0abc5d62c1b72a4a8c6c06f042b45b20", + "sha256:30babd84706115626ea78ea5dbc7dd8d0d01a2e9f9b306d24ca4ed5796c66ded", + "sha256:3378eb62c63bf336ae2070599e49089005771cc651c8769aaad72d1bd9385a7c", + "sha256:3d97672dc709fa4447ab83276f344a165075fd9f366a97b712bdd3fee05efae8", + "sha256:3db8de10ed684995a7f34a001f15b374c230f7655ae840964d51496e2f8a8474", + "sha256:3ebeeec6a6641d0adb2ea71dcfb76017602ee2bfd8213e3fcc18d8f699c5104f", + "sha256:45cea33b208971e87a31c17622e4b440cac231766ec11e5d22c76fab3bf9df62", + "sha256:6708f30db9117f115eadc4f125c2a10c1a50d711461699a0cbfaa45b9a78e376", + "sha256:68532f4349fd3900b839f588972b3392ee56042e440dd5873dfbbcd2cc67617c", + "sha256:6aafa5a78b9e62493539456f8b646f85abc7093dd997f4976bb105537cf2635e", + "sha256:7d37dccc7ae63e61f7b96ee2e19c40f153ba6ce730d8ba4d3b4e9738c1dccc1b", + "sha256:864e1197139d651a76c81757db5eb199db8866e13acb0dfe96e6fc5d1cf45fc4", + "sha256:8887d675a64cfc59f4ecd34382e5b4f0ef4ae1da37ed665adba0c2badf0d6578", + "sha256:8efcadc5a0003d3a6e887ccc1fb44dec25594f117a94e3127954c05cf144d811", + "sha256:9b09e0f0ac29eee0451d71798878eae5a4e6a91aa275e114037b27f7db72702d", + "sha256:a4aee22ece20958888eedbad20e4dbb03c37533e010fb824161b4f05e641f738", + "sha256:a5abddb3558d3f0a78949c750644a67be31e47936042d4f6c888dd6f3c95f4aa", + "sha256:c092a2c1e736086d59ac8e41f9c98f26bbf9b9222a76f21af9dfe949b99b2eb9", + "sha256:c686a47d57ca910a2572fddfe9912819880b8765e2f01dc0dd12a9bf8573e539", + "sha256:cbbe908fda687e39afd6ea2a2f14c2c3e43f2ca88e3a11964b297822358d0e6c", + "sha256:ce9f61938d7155f79d3cb2ffa663147d4a76d16e08f65e2c66b77bd41b356718", + "sha256:dbbaf9da2ee98ee2531e0c780455f2841e4675ff580ecf93fe5c48fe733b5667", + "sha256:f1e507c9ee39c61bfddd79714e4f85900656db1aec4d40c6de55648e85c2799c", + "sha256:ff3d00b70ce95adce264462c930fbaecb29718ba6563db354608f37e49e09024" ], "markers": "sys_platform != 'win32'", - "version": "==0.16.0" + "version": "==0.17.0" }, "webencodings": { "hashes": [ @@ -924,6 +965,7 @@ }, "pyyaml": { "hashes": [ + "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", @@ -935,26 +977,32 @@ "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", + "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", + "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", + "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", + "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", + "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", + "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" ], diff --git a/README.md b/README.md index ace61fb903..559d49ba65 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ <br> <a href="#"> - <img src="https://img.shields.io/badge/Latest%20Version-v4.0.0-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> + <img src="https://img.shields.io/badge/Latest%20Version-v4.0.1-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> </a> <br> diff --git a/bot.py b/bot.py index 9f13e3e04e..1f62bfcac7 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.0" +__version__ = "4.0.1" import asyncio @@ -10,6 +10,7 @@ import string import struct import sys +import platform import typing from datetime import datetime, timezone from subprocess import PIPE @@ -857,10 +858,12 @@ async def get_thread_cooldown(self, author: discord.Member): return try: - cooldown = datetime.fromisoformat(last_log_closed_at) + thread_cooldown + cooldown = datetime.fromisoformat(last_log_closed_at).astimezone(timezone.utc) + thread_cooldown except ValueError: logger.warning("Error with 'thread_cooldown'.", exc_info=True) - cooldown = datetime.fromisoformat(last_log_closed_at) + self.config.remove("thread_cooldown") + cooldown = datetime.fromisoformat(last_log_closed_at).astimezone( + timezone.utc + ) + self.config.remove("thread_cooldown") if cooldown > now: # User messaged before thread cooldown ended @@ -1774,9 +1777,14 @@ def main(): "Unable to import cairosvg, install GTK Installer for Windows and restart your system (https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer/releases/latest)" ) else: - logger.error( - "Unable to import cairosvg, report on our support server with your OS details: https://discord.gg/etJNHCQ" - ) + if "ubuntu" in platform.version().lower() or "debian" in platform.version().lower(): + logger.error( + "Unable to import cairosvg, try running `sudo apt-get install libpangocairo-1.0-0` or report on our support server with your OS details: https://discord.gg/etJNHCQ" + ) + else: + logger.error( + "Unable to import cairosvg, report on our support server with your OS details: https://discord.gg/etJNHCQ" + ) sys.exit(0) # check discord version diff --git a/cogs/modmail.py b/cogs/modmail.py index b6ebe81baf..75130fdb6e 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1683,7 +1683,6 @@ async def blocked(self, ctx): continue if end_time is not None: - after = (datetime.fromisoformat(end_time.group(1)) - now).total_seconds() if after <= 0: # No longer blocked self.bot.blocked_roles.pop(str(id_)) diff --git a/cogs/utility.py b/cogs/utility.py index af0e70beec..16c84af29d 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -810,7 +810,7 @@ async def config_set(self, ctx, key: str.lower, *, value: str): if key in keys: try: - self.bot.config.set(key, value) + await self.bot.config.set(key, value) await self.bot.config.update() embed = discord.Embed( title="Success", diff --git a/core/config.py b/core/config.py index dd76776092..c25eef3921 100644 --- a/core/config.py +++ b/core/config.py @@ -366,7 +366,7 @@ def get(self, key: str, convert=True) -> typing.Any: return value - def set(self, key: str, item: typing.Any, convert=True) -> None: + async def set(self, key: str, item: typing.Any, convert=True) -> None: if not convert: return self.__setitem__(key, item) @@ -401,7 +401,7 @@ def set(self, key: str, item: typing.Any, convert=True) -> None: except isodate.ISO8601Error: try: converter = UserFriendlyTime() - time = converter.convert(None, item) + time = await converter.convert(None, item, now=discord.utils.utcnow()) if time.arg: raise ValueError except BadArgument as exc: diff --git a/core/thread.py b/core/thread.py index c9d8ae5bcb..30f0542c6d 100644 --- a/core/thread.py +++ b/core/thread.py @@ -568,7 +568,7 @@ async def _restart_close_timer(self): seconds = timeout.total_seconds() # seconds = 20 # Uncomment to debug with just 20 seconds reset_time = discord.utils.utcnow() + timedelta(seconds=seconds) - human_time = human_timedelta(dt=reset_time, spec="manual") + human_time = discord.utils.format_dt(reset_time) if self.bot.config.get("thread_auto_close_silently"): return await self.close(closer=self.bot.user, silent=True, after=int(seconds), auto_close=True) diff --git a/core/time.py b/core/time.py index 963eac5a6e..c56c7264e2 100644 --- a/core/time.py +++ b/core/time.py @@ -192,10 +192,11 @@ def __init__( self.converter: commands.Converter = converter # type: ignore # It doesn't understand this narrowing self.default: Any = default - async def convert(self, ctx: Context, argument: str) -> FriendlyTimeResult: + async def convert(self, ctx: Context, argument: str, *, now=None) -> FriendlyTimeResult: calendar = HumanTime.calendar regex = ShortTime.compiled - now = ctx.message.created_at + if now is None: + now = ctx.message.created_at match = regex.match(argument) if match is not None and match.group(0): diff --git a/core/utils.py b/core/utils.py index 30130eb740..d8046ade5f 100644 --- a/core/utils.py +++ b/core/utils.py @@ -469,7 +469,7 @@ async def create_thread_channel(bot, recipient, category, overwrites, *, name=No if not fallback: fallback = await category.clone(name="Fallback Modmail") - bot.config.set("fallback_category_id", str(fallback.id)) + await bot.config.set("fallback_category_id", str(fallback.id)) await bot.config.update() return await create_thread_channel( diff --git a/pyproject.toml b/pyproject.toml index a19e436399..79a3e74f0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.0' +version = '4.0.1' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From d63575281f23286a103ed340968aa50b880ecb1d Mon Sep 17 00:00:00 2001 From: Sebastian Kuipers <61157793+sebkuip@users.noreply.github.com> Date: Wed, 21 Sep 2022 12:52:32 +0200 Subject: [PATCH 141/225] Fixed runtime.txt to use a valid python version --- runtime.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime.txt b/runtime.txt index 30e81e3130..119ff10234 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.10.3 +python-3.10.7 From ec52cc2001f487ab74f5b649f2a085828e9b8b22 Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Thu, 22 Sep 2022 17:39:18 +0530 Subject: [PATCH 142/225] Update modmail.py --- cogs/modmail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index 75130fdb6e..57d4e4e844 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -749,7 +749,7 @@ def format_log_embeds(self, logs, avatar_url): if entry["recipient"]["id"] != entry["creator"]["id"]: embed.add_field(name="Created by", value=f"<@{entry['creator']['id']}>") - if entry["title"]: + if entry.get("title"): embed.add_field(name="Title", value=entry["title"], inline=False) embed.add_field(name="Preview", value=format_preview(entry["messages"]), inline=False) From 7960761ea740d2e5ed7f43ab03b0c11f6215afb6 Mon Sep 17 00:00:00 2001 From: Jerrie-Aries <hidzrie@gmail.com> Date: Fri, 23 Sep 2022 11:42:44 +0000 Subject: [PATCH 143/225] Fix RuntimeError when presence intent disabled. --- bot.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bot.py b/bot.py index 1f62bfcac7..06841e90b9 100644 --- a/bot.py +++ b/bot.py @@ -225,7 +225,6 @@ async def runner(): except discord.PrivilegedIntentsRequired: retry_intents = True if retry_intents: - await self.http.close() if self.ws is not None and self.ws.open: await self.ws.close(code=1000) self._ready.clear() @@ -236,9 +235,9 @@ async def runner(): # Try again with members intent self._connection._intents = intents logger.warning( - "Attempting to login with only the server members and message content privileged intent. Some plugins might not work correctly." + "Attempting to reconnect with only the server members and message content privileged intent. Some plugins might not work correctly." ) - await self.start(self.token) + await self.connect(reconnect=True) except discord.PrivilegedIntentsRequired: logger.critical( "Privileged intents are not explicitly granted in the discord developers dashboard." From ea0c5fce3241ef12aa8753c269b12c6498e0413b Mon Sep 17 00:00:00 2001 From: Sebastian Kuipers <61157793+sebkuip@users.noreply.github.com> Date: Sat, 24 Sep 2022 13:53:19 +0200 Subject: [PATCH 144/225] Added advanced menu to registry --- plugins/registry.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/registry.json b/plugins/registry.json index 494feebee4..325ee2fac0 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -1,4 +1,13 @@ { + "advanced-menu": { + "repository": "sebkuip/mm-plugins", + "branch": "master", + "description": "Advanced menu plugin using dropdown selectors. Supports submenus (and sub-submenus infinitely).", + "bot_version": "v4.0.0", + "title": "Advanced menu", + "icon_url": "https://raw.githubusercontent.com/sebkuip/mm-plugins/master/advanced-menu/logo.png", + "thumbnail_url": "https://raw.githubusercontent.com/sebkuip/mm-plugins/master/advanced-menu/logo.png" + }, "suggest": { "repository": "realcyguy/modmail-plugins", "branch": "v4", @@ -8,4 +17,4 @@ "icon_url": "https://i.imgur.com/qtE7AH8.png", "thumbnail_url": "https://i.imgur.com/qtE7AH8.png" } -} \ No newline at end of file +} From 9e86f224fcf4f18a5c73fe3592098640964e0920 Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Sat, 1 Oct 2022 09:37:10 +0800 Subject: [PATCH 145/225] Add giveaway plugin to registry. (#3208) * Add giveaway plugin to registry. * Update `thumbnail_url` for giveaway plugin. --- plugins/registry.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/registry.json b/plugins/registry.json index 325ee2fac0..27f304c983 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -8,6 +8,15 @@ "icon_url": "https://raw.githubusercontent.com/sebkuip/mm-plugins/master/advanced-menu/logo.png", "thumbnail_url": "https://raw.githubusercontent.com/sebkuip/mm-plugins/master/advanced-menu/logo.png" }, + "giveaway": { + "repository": "Jerrie-Aries/modmail-plugins", + "branch": "master", + "description": "Host giveaways on your server with this plugin.", + "bot_version": "4.0.0", + "title": "Giveaway", + "icon_url": "https://github.com/Jerrie-Aries.png", + "thumbnail_url": "https://raw.githubusercontent.com/Jerrie-Aries/modmail-plugins/master/.static/giveaway.jpg" + }, "suggest": { "repository": "realcyguy/modmail-plugins", "branch": "v4", From a5156621a85da28938b078c73153bb840d3e7a06 Mon Sep 17 00:00:00 2001 From: Ralph <blackbirdralph@aol.com> Date: Fri, 30 Sep 2022 23:03:19 -0400 Subject: [PATCH 146/225] Re-add/Expand FourJR Plugins --- plugins/registry.json | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/plugins/registry.json b/plugins/registry.json index 27f304c983..7f09fbe2cc 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -25,5 +25,79 @@ "title": "Suggest stuff.", "icon_url": "https://i.imgur.com/qtE7AH8.png", "thumbnail_url": "https://i.imgur.com/qtE7AH8.png" + }, + "welcomer": { + "repository": "fourjr/modmail-plugins", + "branch": "master", + "description": "Add messages to welcome new members! Allows for embedded messages as well. [Read more](https://github.com/fourjr/modmail-plugins/blob/master/welcomer/README.md)", + "bot_version": "2.20.1", + "title": "New member messages plugin", + "icon_url": "https://i.imgur.com/Mo60CdK.png", + "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" + }, + "countdowns": { + "repository": "fourjr/modmail-plugins", + "branch": "master", + "description": "Setup a countdown voice channel in your server!", + "bot_version": "3.6.2", + "title": "Countdowns", + "icon_url": "https://i.imgur.com/Mo60CdK.png", + "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" + }, + "claim": { + "repository": "fourjr/modmail-plugins", + "branch": "master", + "description": "Allows supporters to claim thread by sending ?claim in the thread channel", + "title": "Claim Thread", + "icon_url": "https://i.imgur.com/Mo60CdK.png", + "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" + }, + "emote-manager": { + "repository": "fourjr/modmail-plugins", + "branch": "master", + "description": "Allows managing server emotes via ?emoji", + "title": "Emote Manager", + "icon_url": "https://i.imgur.com/Mo60CdK.png", + "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" + }, + "claim": { + "repository": "fourjr/modmail-plugins", + "branch": "master", + "description": "Allows supporters to claim thread by sending ?claim in the thread channel", + "title": "Claim Thread", + "icon_url": "https://i.imgur.com/Mo60CdK.png", + "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" + }, + "gen-log": { + "repository": "fourjr/modmail-plugins", + "branch": "master", + "description": "Outputs a text log of a thread in a specified channel", + "title": "Log Generator", + "icon_url": "https://i.imgur.com/Mo60CdK.png", + "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" + }, + "media-logger": { + "repository": "fourjr/modmail-plugins", + "branch": "master", + "description": "Re-posts detected media from all visible channels into a specified logging channel", + "title": "Media Logger", + "icon_url": "https://i.imgur.com/Mo60CdK.png", + "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" + }, + "report": { + "repository": "fourjr/modmail-plugins", + "branch": "master", + "description": "Specify an emoji to react with on messages. Generates a "report" in specified logging channel upon react.", + "title": "Report", + "icon_url": "https://i.imgur.com/Mo60CdK.png", + "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" + }, + "top-supporters": { + "repository": "fourjr/modmail-plugins", + "branch": "master", + "description": "Gathers and prints the top supporters of handling threads.", + "title": "Top Supporters", + "icon_url": "https://i.imgur.com/Mo60CdK.png", + "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" } } From e978457f2ae61c5c9ee6c58fb64742376a62c1d5 Mon Sep 17 00:00:00 2001 From: Ralph <blackbirdralph@aol.com> Date: Fri, 30 Sep 2022 23:04:47 -0400 Subject: [PATCH 147/225] remove extra quotes --- plugins/registry.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/registry.json b/plugins/registry.json index 7f09fbe2cc..23feb063f9 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -87,7 +87,7 @@ "report": { "repository": "fourjr/modmail-plugins", "branch": "master", - "description": "Specify an emoji to react with on messages. Generates a "report" in specified logging channel upon react.", + "description": "Specify an emoji to react with on messages. Generates a 'report' in specified logging channel upon react.", "title": "Report", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" From 964c809dd880f4aebba3a458c16f116757d29b93 Mon Sep 17 00:00:00 2001 From: Ralph <blackbirdralph@aol.com> Date: Sat, 1 Oct 2022 03:05:34 -0400 Subject: [PATCH 148/225] Update plugins/registry.json Co-authored-by: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> --- plugins/registry.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/plugins/registry.json b/plugins/registry.json index 23feb063f9..57d735198d 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -59,14 +59,6 @@ "title": "Emote Manager", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" - }, - "claim": { - "repository": "fourjr/modmail-plugins", - "branch": "master", - "description": "Allows supporters to claim thread by sending ?claim in the thread channel", - "title": "Claim Thread", - "icon_url": "https://i.imgur.com/Mo60CdK.png", - "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, "gen-log": { "repository": "fourjr/modmail-plugins", From a139de8432b0abe7acb6018aff80e7ee4def84f6 Mon Sep 17 00:00:00 2001 From: Jerrie-Aries <hidzrie@gmail.com> Date: Sat, 1 Oct 2022 07:55:02 +0000 Subject: [PATCH 149/225] Add `announcement` plugin to registry. --- plugins/registry.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/registry.json b/plugins/registry.json index 27f304c983..141ff174c2 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -8,6 +8,15 @@ "icon_url": "https://raw.githubusercontent.com/sebkuip/mm-plugins/master/advanced-menu/logo.png", "thumbnail_url": "https://raw.githubusercontent.com/sebkuip/mm-plugins/master/advanced-menu/logo.png" }, + "announcement": { + "repository": "Jerrie-Aries/modmail-plugins", + "branch": "master", + "description": "Create and post announcements. Supports both plain and embed. Also customisable using buttons and dropdown menus.", + "bot_version": "4.0.0", + "title": "Announcement", + "icon_url": "https://github.com/Jerrie-Aries.png", + "thumbnail_url": "https://raw.githubusercontent.com/Jerrie-Aries/modmail-plugins/master/.static/announcement.jpg" + }, "giveaway": { "repository": "Jerrie-Aries/modmail-plugins", "branch": "master", From 766bbbbd0e494c17dc2cffefb5c906216a7fcb2d Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 2 Oct 2022 22:49:22 -0700 Subject: [PATCH 150/225] Update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c46714146c..3f19259a9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html); however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. + +# [Unreleased] + +### Fixed + +- Bots without presence intent encountering RuntimeError on start. + + # v4.0.1 This is a hotfix release. From 4aadf63590175213ca918e748893311913fd4814 Mon Sep 17 00:00:00 2001 From: Ralph <blackbirdralph@aol.com> Date: Mon, 3 Oct 2022 10:08:39 -0400 Subject: [PATCH 151/225] Update Branch and Bot_Version --- plugins/registry.json | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/plugins/registry.json b/plugins/registry.json index 57d735198d..558d725814 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -28,66 +28,72 @@ }, "welcomer": { "repository": "fourjr/modmail-plugins", - "branch": "master", + "branch": "v4", "description": "Add messages to welcome new members! Allows for embedded messages as well. [Read more](https://github.com/fourjr/modmail-plugins/blob/master/welcomer/README.md)", - "bot_version": "2.20.1", + "bot_version": "4.0.0", "title": "New member messages plugin", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, "countdowns": { "repository": "fourjr/modmail-plugins", - "branch": "master", + "branch": "v4", "description": "Setup a countdown voice channel in your server!", - "bot_version": "3.6.2", + "bot_version": "4.0.0", "title": "Countdowns", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, "claim": { "repository": "fourjr/modmail-plugins", - "branch": "master", + "branch": "v4", "description": "Allows supporters to claim thread by sending ?claim in the thread channel", + "bot_version": "4.0.0", "title": "Claim Thread", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, "emote-manager": { "repository": "fourjr/modmail-plugins", - "branch": "master", + "branch": "v4", "description": "Allows managing server emotes via ?emoji", + "bot_version": "4.0.0", "title": "Emote Manager", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, "gen-log": { "repository": "fourjr/modmail-plugins", - "branch": "master", + "branch": "v4", "description": "Outputs a text log of a thread in a specified channel", + "bot_version": "4.0.0", "title": "Log Generator", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, "media-logger": { "repository": "fourjr/modmail-plugins", - "branch": "master", + "branch": "v4", "description": "Re-posts detected media from all visible channels into a specified logging channel", + "bot_version": "4.0.0", "title": "Media Logger", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, "report": { "repository": "fourjr/modmail-plugins", - "branch": "master", + "branch": "v4", "description": "Specify an emoji to react with on messages. Generates a 'report' in specified logging channel upon react.", + "bot_version": "4.0.0", "title": "Report", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, "top-supporters": { "repository": "fourjr/modmail-plugins", - "branch": "master", + "branch": "v4", "description": "Gathers and prints the top supporters of handling threads.", + "bot_version": "4.0.0", "title": "Top Supporters", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" From df63dec4b02d449c39cc79616dfff0ef00ce37a8 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sat, 15 Oct 2022 04:34:33 -0700 Subject: [PATCH 152/225] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c46714146c..db997890ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html); however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. +# Unreleased + +### Fixed + +- Resolved an issue where `?logs` doesn't work when the thread has no title. ([PR #3201](https://github.com/kyb3r/modmail/pull/3201)) + # v4.0.1 This is a hotfix release. From 03558f742bc0df5aff38eb67fa6e0370bba8f8c9 Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Sun, 4 Dec 2022 11:47:32 +0530 Subject: [PATCH 153/225] Remove hard coded "( )" from plain messages --- core/thread.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/thread.py b/core/thread.py index 30f0542c6d..4d883ae687 100644 --- a/core/thread.py +++ b/core/thread.py @@ -1150,7 +1150,7 @@ def lottie_to_png(data): additional_images = [] if embed.footer.text: - plain_message = f"**({embed.footer.text}) " + plain_message = f"**{embed.footer.text} " else: plain_message = "**" plain_message += f"{embed.author.name}:** {embed.description}" From cde98e90b4119fca97bd80880d3e33cc044cc9ef Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Sun, 4 Dec 2022 13:35:03 +0530 Subject: [PATCH 154/225] Fix guild icon not set issue --- bot.py | 16 +++++++++++++--- cogs/modmail.py | 14 +++++++------- cogs/utility.py | 8 +++++--- core/thread.py | 6 +++--- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/bot.py b/bot.py index 1f62bfcac7..01d8a52c11 100644 --- a/bot.py +++ b/bot.py @@ -87,6 +87,13 @@ def __init__(self): self.plugin_db = PluginDatabaseClient(self) # Deprecated self.startup() + def get_guild_icon(self, guild: typing.Optional[discord.Guild]) -> str: + if guild is None: + guild = self.guild + if guild.icon is None: + return self.user.display_avatar.url + return guild.icon_url + def _resolve_snippet(self, name: str) -> typing.Optional[str]: """ Get actual snippet names from direct aliases to snippets. @@ -913,7 +920,10 @@ async def process_dm_modmail(self, message: discord.Message) -> None: color=self.error_color, description=self.config["disabled_new_thread_response"], ) - embed.set_footer(text=self.config["disabled_new_thread_footer"], icon_url=self.guild.icon.url) + embed.set_footer( + text=self.config["disabled_new_thread_footer"], + icon_url=self.get_guild_icon(guild=message.guild), + ) logger.info("A new thread was blocked from %s due to disabled Modmail.", message.author) await self.add_reaction(message, blocked_emoji) return await message.channel.send(embed=embed) @@ -928,7 +938,7 @@ async def process_dm_modmail(self, message: discord.Message) -> None: ) embed.set_footer( text=self.config["disabled_current_thread_footer"], - icon_url=self.guild.icon.url, + icon_url=self.get_guild_icon(guild=message.guild), ) logger.info("A message was blocked from %s due to disabled Modmail.", message.author) await self.add_reaction(message, blocked_emoji) @@ -1335,7 +1345,7 @@ async def handle_react_to_contact(self, payload): ) embed.set_footer( text=self.config["disabled_new_thread_footer"], - icon_url=self.guild.icon.url, + icon_url=self.get_guild_icon(guild=channel.guild), ) logger.info( "A new thread using react to contact was blocked from %s due to disabled Modmail.", diff --git a/cogs/modmail.py b/cogs/modmail.py index 75130fdb6e..1e4e00a8d0 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -160,7 +160,7 @@ async def snippet(self, ctx, *, name: str.lower = None): color=self.bot.error_color, description="You dont have any snippets at the moment." ) embed.set_footer(text=f'Check "{self.bot.prefix}help snippet add" to add a snippet.') - embed.set_author(name="Snippets", icon_url=ctx.guild.icon.url) + embed.set_author(name="Snippets", icon_url=self.bot.get_guild_icon(guild=ctx.guild)) return await ctx.send(embed=embed) embeds = [] @@ -168,7 +168,7 @@ async def snippet(self, ctx, *, name: str.lower = None): for i, names in enumerate(zip_longest(*(iter(sorted(self.bot.snippets)),) * 15)): description = format_description(i, names) embed = discord.Embed(color=self.bot.main_color, description=description) - embed.set_author(name="Snippets", icon_url=ctx.guild.icon.url) + embed.set_author(name="Snippets", icon_url=self.bot.get_guild_icon(guild=ctx.guild)) embeds.append(embed) session = EmbedPaginatorSession(ctx, *embeds) @@ -1031,7 +1031,7 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: - avatar_url = self.bot.guild.icon.url + avatar_url = self.bot.get_guild_icon(guild=ctx.guild) em.set_footer(text=name, icon_url=avatar_url) for u in users: @@ -1120,7 +1120,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: - avatar_url = self.bot.guild.icon.url + avatar_url = self.bot.get_guild_icon(guild=ctx.guild) em.set_footer(text=name, icon_url=avatar_url) for u in users: @@ -1200,7 +1200,7 @@ async def logs_closed_by(self, ctx, *, user: User = None): user = user if user is not None else ctx.author entries = await self.bot.api.search_closed_by(user.id) - embeds = self.format_log_embeds(entries, avatar_url=self.bot.guild.icon.url) + embeds = self.format_log_embeds(entries, avatar_url=self.bot.get_guild_icon(guild=ctx.guild)) if not embeds: embed = discord.Embed( @@ -1250,7 +1250,7 @@ async def logs_responded(self, ctx, *, user: User = None): entries = await self.bot.api.get_responded_logs(user.id) - embeds = self.format_log_embeds(entries, avatar_url=self.bot.guild.icon.url) + embeds = self.format_log_embeds(entries, avatar_url=self.bot.get_guild_icon(guild=ctx.guild)) if not embeds: embed = discord.Embed( @@ -1275,7 +1275,7 @@ async def logs_search(self, ctx, limit: Optional[int] = None, *, query): entries = await self.bot.api.search_by_text(query, limit) - embeds = self.format_log_embeds(entries, avatar_url=self.bot.guild.icon.url) + embeds = self.format_log_embeds(entries, avatar_url=self.bot.get_guild_icon(guild=ctx.guild)) if not embeds: embed = discord.Embed( diff --git a/cogs/utility.py b/cogs/utility.py index 16c84af29d..5c0ea09eb3 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -1020,7 +1020,7 @@ async def alias(self, ctx, *, name: str.lower = None): color=self.bot.error_color, description="You dont have any aliases at the moment." ) embed.set_footer(text=f'Do "{self.bot.prefix}help alias" for more commands.') - embed.set_author(name="Aliases", icon_url=ctx.guild.icon.url) + embed.set_author(name="Aliases", icon_url=self.bot.get_guild_icon(guild=ctx.guild)) return await ctx.send(embed=embed) embeds = [] @@ -1028,7 +1028,7 @@ async def alias(self, ctx, *, name: str.lower = None): for i, names in enumerate(zip_longest(*(iter(sorted(self.bot.aliases)),) * 15)): description = utils.format_description(i, names) embed = discord.Embed(color=self.bot.main_color, description=description) - embed.set_author(name="Command Aliases", icon_url=ctx.guild.icon.url) + embed.set_author(name="Command Aliases", icon_url=self.bot.get_guild_icon(guild=ctx.guild)) embeds.append(embed) session = EmbedPaginatorSession(ctx, *embeds) @@ -1611,7 +1611,9 @@ async def permissions_get( for name, level in takewhile(lambda x: x is not None, items) ) embed = discord.Embed(color=self.bot.main_color, description=description) - embed.set_author(name="Permission Overrides", icon_url=ctx.guild.icon.url) + embed.set_author( + name="Permission Overrides", icon_url=self.bot.get_guild_icon(guild=ctx.guild) + ) embeds.append(embed) session = EmbedPaginatorSession(ctx, *embeds) diff --git a/core/thread.py b/core/thread.py index 30f0542c6d..07f3108914 100644 --- a/core/thread.py +++ b/core/thread.py @@ -228,7 +228,7 @@ async def send_recipient_genesis_message(): else: footer = self.bot.config["thread_creation_footer"] - embed.set_footer(text=footer, icon_url=self.bot.guild.icon.url) + embed.set_footer(text=footer, icon_url=self.bot.get_guild_icon(guild=self.bot.modmail_guild)) embed.title = self.bot.config["thread_creation_title"] if creator is None or creator == recipient: @@ -521,7 +521,7 @@ async def _close(self, closer, silent=False, delete_channel=True, message=None, embed.description = message footer = self.bot.config["thread_close_footer"] - embed.set_footer(text=footer, icon_url=self.bot.guild.icon.url) + embed.set_footer(text=footer, icon_url=self.bot.get_guild_icon(guild=self.bot.guild)) if not silent: for user in self.recipients: @@ -957,7 +957,7 @@ async def send( name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: - avatar_url = self.bot.guild.icon.url + avatar_url = self.bot.get_guild_icon(guild=self.bot.guild) embed.set_author( name=name, icon_url=avatar_url, From ccc53ea5795ce3affcee9526d4f80a9f17b87c81 Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Mon, 5 Dec 2022 16:11:49 +0530 Subject: [PATCH 155/225] Update bot.py Co-authored-by: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index 01d8a52c11..f060c5e246 100644 --- a/bot.py +++ b/bot.py @@ -92,7 +92,7 @@ def get_guild_icon(self, guild: typing.Optional[discord.Guild]) -> str: guild = self.guild if guild.icon is None: return self.user.display_avatar.url - return guild.icon_url + return guild.icon.url def _resolve_snippet(self, name: str) -> typing.Optional[str]: """ From f0e313c4917d6627e1e0001441a7ec38669fa016 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Thu, 8 Dec 2022 14:24:59 -0800 Subject: [PATCH 156/225] Update changelog, and use default user icon instead of user avatar, so to not leak the user in anon commands --- CHANGELOG.md | 6 ++++++ bot.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cfeec9f8e..74d4ed5115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,8 +15,14 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Fixed +- Not having a guild icon no longer raises an exception. ([PR #3235](https://github.com/kyb3r/modmail/pull/3235)) + - When no icon is set, use the default user icon. - Resolved an issue where `?logs` doesn't work when the thread has no title. ([PR #3201](https://github.com/kyb3r/modmail/pull/3201)) +### Changed + +- Plain messages no longer forces `()` around the respondent text. ([PR #3234](https://github.com/kyb3r/modmail/pull/3234)) + # v4.0.1 This is a hotfix release. diff --git a/bot.py b/bot.py index 3602d37468..77aeb4142b 100644 --- a/bot.py +++ b/bot.py @@ -94,7 +94,7 @@ def get_guild_icon(self, guild: typing.Optional[discord.Guild]) -> str: if guild is None: guild = self.guild if guild.icon is None: - return self.user.display_avatar.url + return "https://cdn.discordapp.com/embed/avatars/0.png" return guild.icon.url def _resolve_snippet(self, name: str) -> typing.Optional[str]: From bb41861cf1e96c6bf8c4d50de99b23493cfc0d06 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Thu, 8 Dec 2022 14:42:08 -0800 Subject: [PATCH 157/225] Replaced discord.BadArgument with TypeError --- CHANGELOG.md | 1 + bot.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74d4ed5115..5bbc6910b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Not having a guild icon no longer raises an exception. ([PR #3235](https://github.com/kyb3r/modmail/pull/3235)) - When no icon is set, use the default user icon. - Resolved an issue where `?logs` doesn't work when the thread has no title. ([PR #3201](https://github.com/kyb3r/modmail/pull/3201)) +- AttributeError raised when failing to forward a reaction. ([GH #3218](https://github.com/kyb3r/modmail/issues/3218)) ### Changed diff --git a/bot.py b/bot.py index 77aeb4142b..2c8b8da73c 100644 --- a/bot.py +++ b/bot.py @@ -876,7 +876,7 @@ async def add_reaction( if reaction != "disable": try: await msg.add_reaction(reaction) - except (discord.HTTPException, discord.BadArgument) as e: + except (discord.HTTPException, TypeError) as e: logger.warning("Failed to add reaction %s: %s.", reaction, e) return False return True @@ -1304,7 +1304,7 @@ async def handle_reaction_events(self, payload): for msg in linked_messages: await msg.remove_reaction(reaction, self.user) await message.remove_reaction(reaction, self.user) - except (discord.HTTPException, discord.BadArgument) as e: + except (discord.HTTPException, TypeError) as e: logger.warning("Failed to remove reaction: %s", e) async def handle_react_to_contact(self, payload): From aed97d5b717e44698d4eb628f791c76dd59e7f1e Mon Sep 17 00:00:00 2001 From: Sattelite <90934664+Satellite-Galaxy@users.noreply.github.com> Date: Mon, 19 Dec 2022 05:15:52 -0500 Subject: [PATCH 158/225] Build and Push docker image to Githubs container registry (#3228) --- .github/workflows/docker-image.yml | 42 ++++++++++++++++++++++++++++++ Dockerfile | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000000..6af8630b38 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,42 @@ + +name: Create and publish a Docker image + +on: + push: + branches: ['master'] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Log in to the Container registry + uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + uses: docker/build-push-action@v3 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile index 2906f4508f..3c88a0e7ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9 as py +FROM python:3.10 as py FROM py as build From 88676e585af54a58e382e86543b5afed6093f3b2 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 19 Dec 2022 03:42:12 -0800 Subject: [PATCH 159/225] Update docker compose, changelog, and installation guide --- CHANGELOG.md | 2 + README.md | 131 ++++++++++++++++++++++++--------------------- docker-compose.yml | 4 +- 3 files changed, 74 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bbc6910b8..83cc9dd697 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Changed - Plain messages no longer forces `()` around the respondent text. ([PR #3234](https://github.com/kyb3r/modmail/pull/3234)) +- Added workflow to automatically build Docker image ([PR #3232](https://github.com/kyb3r/modmail/pull/3228)) +- Updated installation guide to reflect new preferred hosting methods # v4.0.1 diff --git a/README.md b/README.md index 559d49ba65..a6ded0badd 100644 --- a/README.md +++ b/README.md @@ -84,80 +84,89 @@ This list is ever-growing thanks to active development and our exceptional contr ## Installation -Where can I find the Modmail bot invite link? +Q: Where can I find the Modmail bot invite link? + +A: Unfortunately, due to how this bot functions, it cannot be invited. The lack of an invite link is to ensure an individuality to your server and grant you full control over your bot and data. Nonetheless, you can quickly obtain a free copy of Modmail for your server by following one of the methods listed below (roughly takes 15 minutes of your time). + +There are a few options for hosting your very own dedicated Modmail bot. + +1. Patreon hosting +2. Local hosting (VPS, Dedicated Server, RPi, your computer, etc.) +3. PaaS (we provide a guide for Heroku) + +### Patreon Hosting + +If you don't want the trouble of renting and configuring your server to host Modmail, we got a solution for you! We offer hosting and maintenance of your own, private Modmail bot (including a Logviewer) through [**Patreon**](https://patreon.com/kyber). Join our [Modmail Discord Server](https://discord.gg/etJNHCQ) for more info! + +### Local hosting (General Guide) + +Modmail can be hosted on any modern hardware, including your PC. For stability and reliability, we suggest purchasing a cloud server (VPS) for under $10/mo. If you need recommendations on choosing a VPS, join our [Discord server](https://discord.gg/j5e9p8w), and we'll send you a list of non-affiliated hosting providers. Alternatively, we can host Modmail for you when you're subscribed to our [Patreon](https://patreon.com/kyber). + +This guide assumes you've downloaded [`Python 3.10`](https://www.python.org/downloads/release/python-376/) and added python and pip to PATH. + +1. Clone this repo + ```console + $ git clone https://github.com/kyb3r/modmail + $ cd modmail + ``` +2. Create a Discord bot account, grant the necessary intents, and invite the bot ([guide](https://github.com/kyb3r/modmail/wiki/Installation#2-discord-bot-account)) +3. Create a free MongoDB database ([guide](https://github.com/kyb3r/modmail/wiki/Installation-(cont.)#3-create-a-database), follow it carefully!) +4. Rename the file `.env.example` to `.env` and fill it with appropriate values + - If you can't find `.env.example` because it's hidden, create a new text file named `.env`, then copy the contents of [this file](https://raw.githubusercontent.com/kyb3r/modmail/master/.env.example) and replace the placeholders with their values + - If you're on Windows and cannot save the file as `.env`, save it as `.env.` instead (this only applies to Windows!) + - If you do not have a Logviewer yet, leave the `LOG_URL` field as-is +5. Update pip, install pipenv, and install dependencies using pipenv + ```console + $ pip install -U pip + $ pip install pipenv + $ pipenv install + ``` +6. Start the bot + ```console + $ pipenv run bot + ``` +7. Set up the Logviewer, see the [Logviewer installation guide](https://github.com/kyb3r/logviewer) + +### Local Hosting (Docker) + +We provide support for Docker to simplify the deployment of Modmail and Logviewer. +We assume you already have Docker and Docker Compose Plugin installed, if not, see [here](https://docs.docker.com/get-docker/). + +1. Create a Discord bot account, grant the necessary intents, and invite the bot ([guide](https://github.com/kyb3r/modmail/wiki/Installation#2-discord-bot-account)) +2. Create a file named `.env`, then copy the contents of [this file](https://raw.githubusercontent.com/kyb3r/modmail/master/.env.example) and replace the placeholders with their values +3. Create a file named `docker-compose.yml`, then copy the contents of [this file](https://raw.githubusercontent.com/kyb3r/modmail/master/docker-compose.yml), do not change anything! +4. Start the bot + ```console + $ docker compose up -d + ``` + - For older Docker versions, you may need to run `docker-compose up -d` instead +5. View the status of your bot, using `docker ps` and `docker logs [container-id]` + +Our Docker images are hosted on [GitHub Container Registry](ghcr.io), you can build your own image if you wish: +```console +$ docker build --tag=modmail:master . +``` + +Then simply remove `ghcr.io/kyb3r/` from the `docker-compose.yml` file. -Unfortunately, due to how this bot functions, it cannot be invited. The lack of an invite link is to ensure an individuality to your server and grant you full control over your bot and data. Nonetheless, you can quickly obtain a free copy of Modmail for your server by following one of the methods listed below (roughly takes 15 minutes of your time). +### Local Hosting (OS-Specific) -### Heroku +This guide is a WIP. Join our [Discord server](https://discord.gg/j5e9p8w) for more info. -You can host this bot on Heroku. +### Platform as a Service (PaaS) + +You can host this bot on Heroku (no longer free). Installation via Heroku is possible with your web browser alone. The [**installation guide**](https://github.com/kyb3r/modmail/wiki/Installation) (which includes a video tutorial!) will guide you through the entire installation process. If you run into any problems, join our [Modmail Discord Server](https://discord.gg/etJNHCQ) for help and support. -To configure automatic updates: +When using Heroku, you can configure automatic updates: - Login to [GitHub](https://github.com/) and verify your account. - [Fork the repo](https://github.com/kyb3r/modmail/fork). - Install the [Pull app](https://github.com/apps/pull) for your fork. - Then go to the Deploy tab in your [Heroku account](https://dashboard.heroku.com/apps) of your bot app, select GitHub and connect your fork (usually by typing "Modmail"). - Turn on auto-deploy for the `master` branch. -### Hosting for Patreons - -If you don't want to go through the trouble of setting up your very own Modmail bot or wish to support this project, we got a solution for you! We offer the complete installation, hosting, and maintenance of your Modmail with [**Patreon**](https://patreon.com/kyber). Join our [Modmail Discord Server](https://discord.gg/etJNHCQ) for more info! - -### Locally - -Local hosting of Modmail is also possible. First, you will need at least [`Python 3.8`](https://www.python.org/downloads/release/python-376/). - -Follow the [**installation guide**](https://github.com/kyb3r/modmail/wiki/Installation) and disregard deploying the Heroku bot application. If you run into any problems, join our [Modmail Discord Server](https://discord.gg/etJNHCQ) for help and support. - -Clone the repo: - -```console -$ git clone https://github.com/kyb3r/modmail -$ cd modmail -``` - -Install dependencies: - -```console -$ pipenv install -``` - -Rename the `.env.example` to `.env` and fill out the fields. If `.env.example` is nonexistent (hidden), create a text file named `.env` and copy the contents of [`.env.example`](https://raw.githubusercontent.com/kyb3r/modmail/master/.env.example) then modify the values. - -Finally, start Modmail. - -```console -$ pipenv run bot -``` - -#### Docker - -This repo supplies a Dockerfile for simplified deployment. - -You can build your own Docker image: - -```console -$ docker build . --tag=modmail -``` - -Or run directly from a pre-built version from https://hub.docker.com/. - -- Kyber's: - -```console -$ docker pull kyb3rr/modmail -``` - -And to run your docker image: - -```console -$ docker run --env-file .env kyb3rr/modmail -``` -- `.env` should be the path to your env file; you can also supply a path: `/path/to/.env`. - ## Sponsors Special thanks to our sponsors for supporting the project. diff --git a/docker-compose.yml b/docker-compose.yml index d3745c9b4c..0bdd3808bd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.7" services: bot: - image: kyb3rr/modmail + image: ghcr.io/kyb3r/modmail:master restart: always env_file: - .env @@ -10,7 +10,7 @@ services: depends_on: - mongo logviewer: - image: kyb3rr/logviewer + image: ghcr.io/kyb3r/logviewer:master restart: always depends_on: - mongo From 6c690fe73403becbd0c388ebfbc19dfd77b244d9 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 19 Dec 2022 03:45:14 -0800 Subject: [PATCH 160/225] Fix black formatting --- bot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.py b/bot.py index 2c8b8da73c..a79981df5e 100644 --- a/bot.py +++ b/bot.py @@ -70,7 +70,7 @@ def __init__(self): self.config.populate_cache() intents = discord.Intents.all() - if not self.config['enable_presence_intent']: + if not self.config["enable_presence_intent"]: intents.presences = False super().__init__(command_prefix=None, intents=intents) # implemented in `get_prefix` @@ -229,7 +229,7 @@ async def runner(): self._connected = asyncio.Event() self.session = ClientSession(loop=self.loop) - if self.config['enable_presence_intent']: + if self.config["enable_presence_intent"]: logger.info("Starting bot with presence intent.") else: logger.info("Starting bot without presence intent.") From b693b27828437e771ec8496558b8992e7bdb6ee0 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 19 Dec 2022 03:47:39 -0800 Subject: [PATCH 161/225] Bump version to v4.0.2 --- CHANGELOG.md | 2 +- README.md | 2 +- bot.py | 2 +- pyproject.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83cc9dd697..87d32b7f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2. however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. -# [Unreleased] +# v4.0.2 ### Breaking diff --git a/README.md b/README.md index a6ded0badd..0a71061fd0 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ <br> <a href="#"> - <img src="https://img.shields.io/badge/Latest%20Version-v4.0.1-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> + <img src="https://img.shields.io/badge/Latest%20Version-v4.0.2-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> </a> <br> diff --git a/bot.py b/bot.py index a79981df5e..b23b2449b2 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.1" +__version__ = "4.0.2" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 79a3e74f0b..468dc29112 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.1' +version = '4.0.2' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 11eef8b8e25d3b0600b3bdef06a6ad8a98cb85bd Mon Sep 17 00:00:00 2001 From: Stephen <48072084+StephenDaDev@users.noreply.github.com> Date: Mon, 19 Dec 2022 18:14:45 -0500 Subject: [PATCH 162/225] Add alias make/create as an alias to alias add & add to changelog (#3195) --- CHANGELOG.md | 4 ++++ cogs/utility.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87d32b7f60..0450b47c9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html); however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. +# [UNRELEASED] + +### Fixed +- `?alias make/create` as aliases to `?alias add`. This improves continuity between the bot and its command structure. # v4.0.2 diff --git a/cogs/utility.py b/cogs/utility.py index 5c0ea09eb3..ac642d9eb3 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -1115,7 +1115,7 @@ async def make_alias(self, name, value, action): await self.bot.config.update() return embed - @alias.command(name="add") + @alias.command(name="add", aliases=["create", "make"]) @checks.has_permissions(PermissionLevel.MODERATOR) async def alias_add(self, ctx, name: str.lower, *, value): """ From c8b2522173b9923e8bfb009b7972ca7c40f72f43 Mon Sep 17 00:00:00 2001 From: Antonis Tatmichalis <44528553+lidistat67@users.noreply.github.com> Date: Tue, 20 Dec 2022 01:20:09 +0200 Subject: [PATCH 163/225] Fix silently order in help embed (#3215) --- cogs/modmail.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index 376f954cbe..5094e81890 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -483,7 +483,7 @@ async def close( Silently close a thread (no message) - `{prefix}close silently` - - `{prefix}close in 10m silently` + - `{prefix}close silently in 10m` Stop a thread from closing: - `{prefix}close cancel` From 485ab5ab936cb98748ad1f9d8825437dd15fc895 Mon Sep 17 00:00:00 2001 From: khakers <22665282+khakers@users.noreply.github.com> Date: Fri, 20 Jan 2023 16:30:30 -0800 Subject: [PATCH 164/225] Remove user fetching from blocked command (#3242) We already have all the information we need to mention a user (their id) and fetching the information from discord will lead to rate limiting and extremely poor performance on large block lists for no gain. --- cogs/modmail.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index 5094e81890..484eb7aac8 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1665,13 +1665,7 @@ async def blocked(self, ctx): self.bot.blocked_users.pop(str(id_)) logger.debug("No longer blocked, user %s.", id_) continue - - try: - user = await self.bot.get_or_fetch_user(int(id_)) - except discord.NotFound: - users.append((id_, reason)) - else: - users.append((user.mention, reason)) + users.append((f"<@{id_}>", reason)) blocked_roles = list(self.bot.blocked_roles.items()) for id_, reason in blocked_roles: From d6eba12937d4e0024e1c9208d0ac22b365829397 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Fri, 20 Jan 2023 16:34:17 -0800 Subject: [PATCH 165/225] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0450b47c9a..dfb6e3f27d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ however, insignificant breaking changes do not guarantee a major version bump, s # [UNRELEASED] ### Fixed -- `?alias make/create` as aliases to `?alias add`. This improves continuity between the bot and its command structure. +- `?alias make/create` as aliases to `?alias add`. This improves continuity between the bot and its command structure. ([PR #3195](https://github.com/kyb3r/modmail/pull/3195)) +- Loading the blocked list with the `?blocked` command takes a long time when the list is large. ([PR #3242](https://github.com/kyb3r/modmail/pull/3242)) # v4.0.2 From 8d41c1d4b25cdede91f2f18954e15ced9cbf7bb9 Mon Sep 17 00:00:00 2001 From: Sebastian Kuipers <61157793+sebkuip@users.noreply.github.com> Date: Wed, 8 Mar 2023 23:45:11 +0100 Subject: [PATCH 166/225] Added the option for registry_plugins_only (#3247) * Added the option for secure_plugins_only * Change config name * Forgot to update app.json * Forgot a period. Thanks taku :( --- app.json | 4 ++++ cogs/plugins.py | 8 ++++++++ core/config.py | 2 ++ 3 files changed, 14 insertions(+) diff --git a/app.json b/app.json index 66b5c77752..1cf5d107e4 100644 --- a/app.json +++ b/app.json @@ -34,6 +34,10 @@ "GITHUB_TOKEN": { "description": "A github personal access token with the repo scope.", "required": false + }, + "REGISTRY_PLUGINS_ONLY": { + "description": "If set to true, only plugins that are in the registry can be loaded.", + "required": false } } } \ No newline at end of file diff --git a/cogs/plugins.py b/cogs/plugins.py index 2bfac509af..c99f74ef40 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -302,6 +302,14 @@ async def parse_user_input(self, ctx, plugin_name, check_version=False): plugin = Plugin(user, repo, plugin_name, branch) else: + if not self.bot.config.get("registry_plugins_only", False): + embed = discord.Embed( + description="This plugin is not in the registry. " + "To install it, you must set `REGISTRY_PLUGINS_ONLY=false` in your .env file or config settings.", + color=self.bot.error_color, + ) + await ctx.send(embed=embed) + return try: plugin = Plugin.from_string(plugin_name) except InvalidPluginError: diff --git a/core/config.py b/core/config.py index 56db40c7b0..9a033167b7 100644 --- a/core/config.py +++ b/core/config.py @@ -167,6 +167,7 @@ class ConfigManager: "connection_uri": None, # replace mongo uri in the future "owners": None, "enable_presence_intent": False, + "registry_plugins_only": False, # bot "token": None, "enable_plugins": True, @@ -223,6 +224,7 @@ class ConfigManager: "thread_show_join_age", "use_hoisted_top_role", "enable_presence_intent", + "registry_plugins_only", } enums = { From 1f3bd0e9fcecb0be1feb217f174b47bb1d5e2251 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 12 Mar 2023 19:17:37 -0700 Subject: [PATCH 167/225] Update changelog and updated all the links to new repo (#3251) --- .github/CONTRIBUTING.md | 6 +- .github/pull.yml | 4 +- CHANGELOG.md | 236 +++++++++++++++++++++------------------- README.md | 48 ++++---- app.json | 2 +- cogs/modmail.py | 2 +- cogs/plugins.py | 4 +- cogs/utility.py | 6 +- core/changelog.py | 4 +- core/clients.py | 4 +- docker-compose.yml | 4 +- pyproject.toml | 4 +- 12 files changed, 166 insertions(+), 158 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b1309b6402..6c6694b809 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -30,11 +30,11 @@ Pull requests are the best way to propose changes to the codebase. We actively w ## Any contributions you make will be under the GNU Affero General Public License v3.0 In short, when you submit code changes, your submissions are understood to be under the same [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl-3.0.en.html) that covers the project. Feel free to contact the maintainers if that's a concern. -## Report bugs using [Github Issues](https://github.com/kyb3r/modmail/issues) -We use GitHub issues to track public bugs. Report a bug by [opening a new Issue](https://github.com/kyb3r/modmail/issues/new); it's that easy! +## Report bugs using [Github Issues](https://github.com/modmail-dev/modmail/issues) +We use GitHub issues to track public bugs. Report a bug by [opening a new Issue](https://github.com/modmail-dev/modmail/issues/new); it's that easy! ## Find pre-existing issues to tackle -Check out our [unstaged issue tracker](https://github.com/kyb3r/modmail/issues?q=is%3Aissue+is%3Aopen+-label%3Astaged) and start helping out! +Check out our [unstaged issue tracker](https://github.com/modmail-dev/modmail/issues?q=is%3Aissue+is%3Aopen+-label%3Astaged) and start helping out! Ways to help out: - Help out new members diff --git a/.github/pull.yml b/.github/pull.yml index 2fec8bbda0..8a0898a6b7 100644 --- a/.github/pull.yml +++ b/.github/pull.yml @@ -1,8 +1,8 @@ version: "1" rules: - base: master - upstream: kyb3r:master + upstream: modmail-dev:master mergeMethod: hardreset - base: development - upstream: kyb3r:development + upstream: modmail-dev:development mergeMethod: hardreset \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 87d32b7f60..46cf14177c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html); -however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. +however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/modmail-dev/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. +# [UNRELEASED] + +### Added +- New .env config option: `REGISTRY_PLUGINS_ONLY`, restricts to only allow adding registry plugins. ([PR #3247](https://github.com/modmail-dev/modmail/pull/3247)) + +### Changed +- Repo moved to https://github.com/modmail-dev/modmail. + # v4.0.2 ### Breaking @@ -15,15 +23,15 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Fixed -- Not having a guild icon no longer raises an exception. ([PR #3235](https://github.com/kyb3r/modmail/pull/3235)) +- Not having a guild icon no longer raises an exception. ([PR #3235](https://github.com/modmail-dev/modmail/pull/3235)) - When no icon is set, use the default user icon. -- Resolved an issue where `?logs` doesn't work when the thread has no title. ([PR #3201](https://github.com/kyb3r/modmail/pull/3201)) -- AttributeError raised when failing to forward a reaction. ([GH #3218](https://github.com/kyb3r/modmail/issues/3218)) +- Resolved an issue where `?logs` doesn't work when the thread has no title. ([PR #3201](https://github.com/modmail-dev/modmail/pull/3201)) +- AttributeError raised when failing to forward a reaction. ([GH #3218](https://github.com/modmail-dev/modmail/issues/3218)) ### Changed -- Plain messages no longer forces `()` around the respondent text. ([PR #3234](https://github.com/kyb3r/modmail/pull/3234)) -- Added workflow to automatically build Docker image ([PR #3232](https://github.com/kyb3r/modmail/pull/3228)) +- Plain messages no longer forces `()` around the respondent text. ([PR #3234](https://github.com/modmail-dev/modmail/pull/3234)) +- Added workflow to automatically build Docker image ([PR #3232](https://github.com/modmail-dev/modmail/pull/3228)) - Updated installation guide to reflect new preferred hosting methods # v4.0.1 @@ -43,59 +51,59 @@ This is a hotfix release. ### Breaking - Modmail now requires [`Message Content` privileged intent](https://support-dev.discord.com/hc/en-us/articles/4404772028055-Message-Content-Privileged-Intent-for-Verified-Bots). -- Upgraded to discord.py v2.0 ([internal changes](https://discordpy.readthedocs.io/en/latest/migrating.html), [GH #2990](https://github.com/kyb3r/modmail/issues/2990)). +- Upgraded to discord.py v2.0 ([internal changes](https://discordpy.readthedocs.io/en/latest/migrating.html), [GH #2990](https://github.com/modmail-dev/modmail/issues/2990)). - Python 3.8 or higher is required. - Asyncio changes ([gist](https://gist.github.com/Rapptz/6706e1c8f23ac27c98cee4dd985c8120)) - Plugin registry is purged and all developers have to re-apply due to breaking changes. ### Added -- `use_hoisted_top_role` config to use change how default mod tags work, see `v3.10.0#Added` for details. ([PR #3093](https://github.com/kyb3r/modmail/pull/3093)) -- `require_close_reason` config to require a reason to close a thread. ([GH #3107](https://github.com/kyb3r/modmail/issues/3107)) -- `plain_snippets` config to force all snippets to be plain. ([GH #3083](https://github.com/kyb3r/modmail/issues/3083)) +- `use_hoisted_top_role` config to use change how default mod tags work, see `v3.10.0#Added` for details. ([PR #3093](https://github.com/modmail-dev/modmail/pull/3093)) +- `require_close_reason` config to require a reason to close a thread. ([GH #3107](https://github.com/modmail-dev/modmail/issues/3107)) +- `plain_snippets` config to force all snippets to be plain. ([GH #3083](https://github.com/modmail-dev/modmail/issues/3083)) - `?fpareply` and `?fpreply` to reply to messages with variables plainly. -- `use_nickname_channel_name` config to use nicknames instead of usernames for channel names. ([GH #3112](https://github.com/kyb3r/modmail/issues/3112)) -- `use_random_channel_name` config to use random nicknames vaguely tied to user ID. It is unable to be computed in reverse. ([GH #3143](https://github.com/kyb3r/modmail/issues/3143)) -- `show_log_url_button` config to show Log URL button. ([GH #3122](https://github.com/kyb3r/modmail/issues/3122)) +- `use_nickname_channel_name` config to use nicknames instead of usernames for channel names. ([GH #3112](https://github.com/modmail-dev/modmail/issues/3112)) +- `use_random_channel_name` config to use random nicknames vaguely tied to user ID. It is unable to be computed in reverse. ([GH #3143](https://github.com/modmail-dev/modmail/issues/3143)) +- `show_log_url_button` config to show Log URL button. ([GH #3122](https://github.com/modmail-dev/modmail/issues/3122)) - Select menus for certain paginators. -- `Title` field in `?logs`. ([GH #3142](https://github.com/kyb3r/modmail/issues/3142)) -- Snippets can be used in aliases. ([GH #3108](https://github.com/kyb3r/modmail/issues/3108), [PR #3124](https://github.com/kyb3r/modmail/pull/3124)) -- `?snippet make/create` as aliases to `?snippet add`. ([GH #3172](https://github.com/kyb3r/modmail/issues/3173), [PR #3174](https://github.com/kyb3r/modmail/pull/3174)) +- `Title` field in `?logs`. ([GH #3142](https://github.com/modmail-dev/modmail/issues/3142)) +- Snippets can be used in aliases. ([GH #3108](https://github.com/modmail-dev/modmail/issues/3108), [PR #3124](https://github.com/modmail-dev/modmail/pull/3124)) +- `?snippet make/create` as aliases to `?snippet add`. ([GH #3172](https://github.com/modmail-dev/modmail/issues/3173), [PR #3174](https://github.com/modmail-dev/modmail/pull/3174)) ### Improved -- Modmail now uses per-server avatars if applicable. ([GH #3048](https://github.com/kyb3r/modmail/issues/3048)) -- Use discord relative timedeltas. ([GH #3046](https://github.com/kyb3r/modmail/issues/3046)) +- Modmail now uses per-server avatars if applicable. ([GH #3048](https://github.com/modmail-dev/modmail/issues/3048)) +- Use discord relative timedeltas. ([GH #3046](https://github.com/modmail-dev/modmail/issues/3046)) - Use discord native buttons for all paginator sessions. - `?help` and `?blocked` paginator sessions now have better multi-page UI. - Autoupdate now automatically updates pipenv dependencies if possible. ### Fixed -- Several minor typos. ([PR #3095](https://github.com/kyb3r/modmail/pull/3095), [PR #3116](https://github.com/kyb3r/modmail/pull/3116)) -- Certain cases where fallback categories were not working as intended. ([PR #3109](https://github.com/kyb3r/modmail/pull/3109)) -- `?contact` would create in a random category in silent mode. ([GH #3091](https://github.com/kyb3r/modmail/issues/3091), [PR #3092](https://github.com/kyb3r/modmail/pull/3092)) -- Certain cases where `?close` would fail if closer isn't in cache. ([GH #3104](https://github.com/kyb3r/modmail/issues/3104), [PR #3105](https://github.com/kyb3r/modmail/pull/3105)) +- Several minor typos. ([PR #3095](https://github.com/modmail-dev/modmail/pull/3095), [PR #3116](https://github.com/modmail-dev/modmail/pull/3116)) +- Certain cases where fallback categories were not working as intended. ([PR #3109](https://github.com/modmail-dev/modmail/pull/3109)) +- `?contact` would create in a random category in silent mode. ([GH #3091](https://github.com/modmail-dev/modmail/issues/3091), [PR #3092](https://github.com/modmail-dev/modmail/pull/3092)) +- Certain cases where `?close` would fail if closer isn't in cache. ([GH #3104](https://github.com/modmail-dev/modmail/issues/3104), [PR #3105](https://github.com/modmail-dev/modmail/pull/3105)) - Stickers now work in Modmail. -- Large server sizes results in Guild.name == None. ([GH #3088](https://github.com/kyb3r/modmail/issues/3088)) -- Attachments now work on plain replies. ([GH #3102](https://github.com/kyb3r/modmail/issues/3102)) -- Support LOTTIE stickers. ([GH #3119](https://github.com/kyb3r/modmail/issues/3119)) -- Editing notes now work. ([GH #3094](https://github.com/kyb3r/modmail/issues/3094)) +- Large server sizes results in Guild.name == None. ([GH #3088](https://github.com/modmail-dev/modmail/issues/3088)) +- Attachments now work on plain replies. ([GH #3102](https://github.com/modmail-dev/modmail/issues/3102)) +- Support LOTTIE stickers. ([GH #3119](https://github.com/modmail-dev/modmail/issues/3119)) +- Editing notes now work. ([GH #3094](https://github.com/modmail-dev/modmail/issues/3094)) - Commands now work in threads. - Audit log searching now properly works. -- Old data causing `?blocked` to fail. ([GH #3131](https://github.com/kyb3r/modmail/issues/3131)) +- Old data causing `?blocked` to fail. ([GH #3131](https://github.com/modmail-dev/modmail/issues/3131)) - Delete channel auto close functionality now works. -- Improved error handling for autoupdate. ([PR #3161](https://github.com/kyb3r/modmail/pull/3161)) -- Skip loading of already-loaded cog. ([PR #3172](https://github.com/kyb3r/modmail/pull/3172)) -- Respect plugin's `cog_command_error`. ([GH #3170](https://github.com/kyb3r/modmail/issues/3170), [PR #3178](https://github.com/kyb3r/modmail/pull/3178)) -- Use silent as a typing literal for contacting. ([GH #3179](https://github.com/kyb3r/modmail/issues/3179)) +- Improved error handling for autoupdate. ([PR #3161](https://github.com/modmail-dev/modmail/pull/3161)) +- Skip loading of already-loaded cog. ([PR #3172](https://github.com/modmail-dev/modmail/pull/3172)) +- Respect plugin's `cog_command_error`. ([GH #3170](https://github.com/modmail-dev/modmail/issues/3170), [PR #3178](https://github.com/modmail-dev/modmail/pull/3178)) +- Use silent as a typing literal for contacting. ([GH #3179](https://github.com/modmail-dev/modmail/issues/3179)) ### Internal -- Improve regex parsing of channel topics. ([GH #3114](https://github.com/kyb3r/modmail/issues/3114), [PR #3111](https://github.com/kyb3r/modmail/pull/3111)) +- Improve regex parsing of channel topics. ([GH #3114](https://github.com/modmail-dev/modmail/issues/3114), [PR #3111](https://github.com/modmail-dev/modmail/pull/3111)) - Add warning if deploying on a developmental version. - Extensions are now loaded `on_connect`. -- MongoDB v5.0 clients are now supported. ([GH #3126](https://github.com/kyb3r/modmail/issues/3126)) +- MongoDB v5.0 clients are now supported. ([GH #3126](https://github.com/modmail-dev/modmail/issues/3126)) - Bump python-dotenv to v0.20.0, support for python 3.10 - Bump emoji to v1.7.0 - Bump aiohttp to v3.8.1 @@ -155,37 +163,37 @@ v3.10 adds group conversations while resolving other bugs and QOL changes. It is ### Added -- Ability to have group conversations with up to 5 users. ([GH #143](https://github.com/kyb3r/modmail/issues/143)) -- Snippets are invoked case insensitively. ([GH #3077](https://github.com/kyb3r/modmail/issues/3077), [PR #3080](https://github.com/kyb3r/modmail/pull/3080)) -- Default tags now use top hoisted role. ([GH #3014](https://github.com/kyb3r/modmail/issues/3014)) -- New thread-related config - `thread_show_roles`, `thread_show_account_age`, `thread_show_join_age`, `thread_cancelled`, `thread_creation_contact_title`, `thread_creation_self_contact_response`, `thread_creation_contact_response`. ([GH #3072](https://github.com/kyb3r/modmail/issues/3072)) +- Ability to have group conversations with up to 5 users. ([GH #143](https://github.com/modmail-dev/modmail/issues/143)) +- Snippets are invoked case insensitively. ([GH #3077](https://github.com/modmail-dev/modmail/issues/3077), [PR #3080](https://github.com/modmail-dev/modmail/pull/3080)) +- Default tags now use top hoisted role. ([GH #3014](https://github.com/modmail-dev/modmail/issues/3014)) +- New thread-related config - `thread_show_roles`, `thread_show_account_age`, `thread_show_join_age`, `thread_cancelled`, `thread_creation_contact_title`, `thread_creation_self_contact_response`, `thread_creation_contact_response`. ([GH #3072](https://github.com/modmail-dev/modmail/issues/3072)) - `use_timestamp_channel_name` config to create thread channels by timestamp. ### Improved -- `?contact` now accepts a role or multiple users (creates a group conversation). ([GH #3082](https://github.com/kyb3r/modmail/issues/3082)) -- Aliases are now supported in autotrigger. ([GH #3081](https://github.com/kyb3r/modmail/pull/3081)) +- `?contact` now accepts a role or multiple users (creates a group conversation). ([GH #3082](https://github.com/modmail-dev/modmail/issues/3082)) +- Aliases are now supported in autotrigger. ([GH #3081](https://github.com/modmail-dev/modmail/pull/3081)) ### Fixed -- Certain situations where the internal thread cache breaks and spams new channels. ([GH #3022](https://github.com/kyb3r/modmail/issues/3022), [PR #3028](https://github.com/kyb3r/modmail/pull/3028)) -- Blocked users are now no longer allowed to use `?contact` and react to contact. ([COMMENT #819004157](https://github.com/kyb3r/modmail/issues/2969#issuecomment-819004157), [PR #3027](https://github.com/kyb3r/modmail/pull/3027)) -- UnicodeEncodeError will no longer be raised on Windows. ([PR #3043](https://github.com/kyb3r/modmail/pull/3043)) -- Notifications are no longer duplicated when using both `?notify` and `subscribe`. ([PR #3015](https://github.com/kyb3r/modmail/pull/3015)) -- `?contact` now works properly with both category and silent. ([GH #3076](https://github.com/kyb3r/modmail/issues/3076)) -- `close_on_leave_reason` now works properly when `close_on_leave` is enabled. ([GH #3075](https://github.com/kyb3r/modmail/issues/3075)) +- Certain situations where the internal thread cache breaks and spams new channels. ([GH #3022](https://github.com/modmail-dev/modmail/issues/3022), [PR #3028](https://github.com/modmail-dev/modmail/pull/3028)) +- Blocked users are now no longer allowed to use `?contact` and react to contact. ([COMMENT #819004157](https://github.com/modmail-dev/modmail/issues/2969#issuecomment-819004157), [PR #3027](https://github.com/modmail-dev/modmail/pull/3027)) +- UnicodeEncodeError will no longer be raised on Windows. ([PR #3043](https://github.com/modmail-dev/modmail/pull/3043)) +- Notifications are no longer duplicated when using both `?notify` and `subscribe`. ([PR #3015](https://github.com/modmail-dev/modmail/pull/3015)) +- `?contact` now works properly with both category and silent. ([GH #3076](https://github.com/modmail-dev/modmail/issues/3076)) +- `close_on_leave_reason` now works properly when `close_on_leave` is enabled. ([GH #3075](https://github.com/modmail-dev/modmail/issues/3075)) - Invalid arguments are now properly catched and a proper error message is sent. -- Update database after resetting/purging all plugins. ([GH #3011](https://github.com/kyb3r/modmail/pull/3011)) -- `thread_auto_close` timer now only resets on non-note and replies from mods. ([GH #3030](https://github.com/kyb3r/modmail/issues/3030)) -- Deleted messages are now deleted on both ends. ([GH #3041](https://github.com/kyb3r/modmail/issues/3041), [@JerrieAries](https://github.com/kyb3r/modmail/commit/20b31f8e8b5497943513997fef788d72ae668438)) -- Persistent notes are now properly deleted from the database. ([GH #3013](https://github.com/kyb3r/modmail/issues/3013)) +- Update database after resetting/purging all plugins. ([GH #3011](https://github.com/modmail-dev/modmail/pull/3011)) +- `thread_auto_close` timer now only resets on non-note and replies from mods. ([GH #3030](https://github.com/modmail-dev/modmail/issues/3030)) +- Deleted messages are now deleted on both ends. ([GH #3041](https://github.com/modmail-dev/modmail/issues/3041), [@JerrieAries](https://github.com/modmail-dev/modmail/commit/20b31f8e8b5497943513997fef788d72ae668438)) +- Persistent notes are now properly deleted from the database. ([GH #3013](https://github.com/modmail-dev/modmail/issues/3013)) - Modmail Bot is now recognized to have `OWNER` permission level. This affects what can be run in autotriggers. ### Internal -- Fix return types, type hints and unresolved references ([PR #3009](https://github.com/kyb3r/modmail/pull/3009)) -- Reload thread cache only when it's the first on_ready trigger. ([GH #3037](https://github.com/kyb3r/modmail/issues/3037)) -- `format_channel_name` is now extendable to plugins. Modify `Bot.format_channel_name(bot, author, exclude_channel=None, force_null=False):`. ([GH #2982](https://github.com/kyb3r/modmail/issues/2982)) +- Fix return types, type hints and unresolved references ([PR #3009](https://github.com/modmail-dev/modmail/pull/3009)) +- Reload thread cache only when it's the first on_ready trigger. ([GH #3037](https://github.com/modmail-dev/modmail/issues/3037)) +- `format_channel_name` is now extendable to plugins. Modify `Bot.format_channel_name(bot, author, exclude_channel=None, force_null=False):`. ([GH #2982](https://github.com/modmail-dev/modmail/issues/2982)) # v3.9.5 @@ -199,17 +207,17 @@ v3.10 adds group conversations while resolving other bugs and QOL changes. It is ### Fixed -- Certain cases where fallback categories were not working as intended. ([GH #3002](https://github.com/kyb3r/modmail/issues/3002), [PR #3003](https://github.com/kyb3r/modmail/pull/3003)) +- Certain cases where fallback categories were not working as intended. ([GH #3002](https://github.com/modmail-dev/modmail/issues/3002), [PR #3003](https://github.com/modmail-dev/modmail/pull/3003)) - There is now a proper message when trying to contact a bot. ### Improved -- `?mention` can now be disabled with `?mention disable`. ([PR #2993](https://github.com/kyb3r/modmail/pull/2993/files)) -- `?mention` now allows vague entries such as `everyone` or `all`. ([PR #2993](https://github.com/kyb3r/modmail/pull/2993/files)) +- `?mention` can now be disabled with `?mention disable`. ([PR #2993](https://github.com/modmail-dev/modmail/pull/2993/files)) +- `?mention` now allows vague entries such as `everyone` or `all`. ([PR #2993](https://github.com/modmail-dev/modmail/pull/2993/files)) ### Internal -- Change heroku python version to 3.9.4 ([PR #3001](https://github.com/kyb3r/modmail/pull/3001)) +- Change heroku python version to 3.9.4 ([PR #3001](https://github.com/modmail-dev/modmail/pull/3001)) # v3.9.3 @@ -228,7 +236,7 @@ v3.10 adds group conversations while resolving other bugs and QOL changes. It is ### Improved -- Additional HostingMethods (i.e. DOCKER, PM2, SCREEN). Autoupdates are now disabled on all docker instances. ([GH #2977](https://github.com/kyb3r/modmail/issues/2977), [PR #2988](https://github.com/kyb3r/modmail/pull/2988)) +- Additional HostingMethods (i.e. DOCKER, PM2, SCREEN). Autoupdates are now disabled on all docker instances. ([GH #2977](https://github.com/modmail-dev/modmail/issues/2977), [PR #2988](https://github.com/modmail-dev/modmail/pull/2988)) ### Fixed @@ -249,8 +257,8 @@ v3.10 adds group conversations while resolving other bugs and QOL changes. It is ### Fixed -- `confirm_thread_creation` now properly works when a user opens a thread using react to contact. ([GH #2930](https://github.com/kyb3r/modmail/issues/2930), [PR #2971](https://github.com/kyb3r/modmail/pull/2971)) -- `?disable all/new` now disables react to contact threads. ([GH #2969](https://github.com/kyb3r/modmail/issues/2969), [PR #2971](https://github.com/kyb3r/modmail/pull/2971)) +- `confirm_thread_creation` now properly works when a user opens a thread using react to contact. ([GH #2930](https://github.com/modmail-dev/modmail/issues/2930), [PR #2971](https://github.com/modmail-dev/modmail/pull/2971)) +- `?disable all/new` now disables react to contact threads. ([GH #2969](https://github.com/modmail-dev/modmail/issues/2969), [PR #2971](https://github.com/modmail-dev/modmail/pull/2971)) - Ghost errors are no longer raised when threads are created using non-organic methods. ### Internal @@ -269,13 +277,13 @@ v3.10 adds group conversations while resolving other bugs and QOL changes. It is ### Added -- `?msglink <message id>`, allows you to obtain channel + message ID for T&S reports. ([GH #2963](https://github.com/kyb3r/modmail/issues/2963), [PR #2964](https://github.com/kyb3r/modmail/pull/2964)) -- `?mention disable/reset`, disables or resets mention on thread creation. ([PR #2951](https://github.com/kyb3r/modmail/pull/2951)) +- `?msglink <message id>`, allows you to obtain channel + message ID for T&S reports. ([GH #2963](https://github.com/modmail-dev/modmail/issues/2963), [PR #2964](https://github.com/modmail-dev/modmail/pull/2964)) +- `?mention disable/reset`, disables or resets mention on thread creation. ([PR #2951](https://github.com/modmail-dev/modmail/pull/2951)) ### Fixed - Non-master/development branch deployments no longer cause errors to be raised. -- Autotriggers now can search for roles/channels in guild context. ([GH #2961](https://github.com/kyb3r/modmail/issues/2961)) +- Autotriggers now can search for roles/channels in guild context. ([GH #2961](https://github.com/modmail-dev/modmail/issues/2961)) # v3.8.4 @@ -289,28 +297,28 @@ This update is a quick hotfix for a weird behaviour experienced on 1 Feb 2021 wh ### Fixed -- Retry with `null-discrim` if channel could not be created. ([GH #2934](https://github.com/kyb3r/modmail/issues/2934)) +- Retry with `null-discrim` if channel could not be created. ([GH #2934](https://github.com/modmail-dev/modmail/issues/2934)) - Fix update notifications. -- Retrieve user from Discord API if user has left the server, resolving issues in `?block`. ([GH #2935](https://github.com/kyb3r/modmail/issues/2935), [PR #2936](https://github.com/kyb3r/modmail/pull/2936)) +- Retrieve user from Discord API if user has left the server, resolving issues in `?block`. ([GH #2935](https://github.com/modmail-dev/modmail/issues/2935), [PR #2936](https://github.com/modmail-dev/modmail/pull/2936)) - IDs in `<member>` commands work now. # v3.8.1 ### Fixed -- Additional image uploads now render properly. ([PR #2933](https://github.com/kyb3r/modmail/pull/2933)) -- `confirm_thread_creation` no longer raises unnecessary errors. ([GH #2931](https://github.com/kyb3r/modmail/issues/2931), [PR #2933](https://github.com/kyb3r/modmail/pull/2933)) -- Autotriggers no longer sends attachments back. ([GH #2932](https://github.com/kyb3r/modmail/issues/2932)) +- Additional image uploads now render properly. ([PR #2933](https://github.com/modmail-dev/modmail/pull/2933)) +- `confirm_thread_creation` no longer raises unnecessary errors. ([GH #2931](https://github.com/modmail-dev/modmail/issues/2931), [PR #2933](https://github.com/modmail-dev/modmail/pull/2933)) +- Autotriggers no longer sends attachments back. ([GH #2932](https://github.com/modmail-dev/modmail/issues/2932)) # v3.8.0 ### Added -- `update_notifications` configuration option to toggle bot autoupdate notifications. ([GH #2896](https://github.com/kyb3r/modmail/issues/2896)) +- `update_notifications` configuration option to toggle bot autoupdate notifications. ([GH #2896](https://github.com/modmail-dev/modmail/issues/2896)) - `?fareply`, anonymously reply with variables. -- `anonymous_snippets` config variable to toggle if snippets should be anonymous. ([GH #2905](https://github.com/kyb3r/modmail/issues/2905)) +- `anonymous_snippets` config variable to toggle if snippets should be anonymous. ([GH #2905](https://github.com/modmail-dev/modmail/issues/2905)) - `disable_updates` config variable to control if the update command should be disabled or not. -- `silent_alert_on_mention` to alert mods silently. ([GH #2907](https://github.com/kyb3r/modmail/issues/2907)) +- `silent_alert_on_mention` to alert mods silently. ([GH #2907](https://github.com/modmail-dev/modmail/issues/2907)) - Support for only the "Server Members" intent. ### Improved @@ -321,17 +329,17 @@ This update is a quick hotfix for a weird behaviour experienced on 1 Feb 2021 wh ### Fixed -- Mentioned `competing` as an activity type. ([PR #2902](https://github.com/kyb3r/modmail/pull/2902)) +- Mentioned `competing` as an activity type. ([PR #2902](https://github.com/modmail-dev/modmail/pull/2902)) - Level permissions were not checked if command permissions were set. - Regex autotriggers were not working if term was in the middle of strings. - `?blocked` now no longers show blocks that have expired. - Blocked roles will no longer trigger an error during unblock. -- Custom emojis are now supported in `confirm_thread_creation_deny`. ([GH #2916](https://github.com/kyb3r/modmail/issues/2916)) -- Finding linked messages in replies work now. ([GH #2920](https://github.com/kyb3r/modmail/issues/2920), [Jerrie-Aries](https://github.com/kyb3r/modmail/issues/2920#issuecomment-751530495)) -- Sending files in threads (non-images) now work. ([GH #2926](https://github.com/kyb3r/modmail/issues/2926)) -- Deleting messages no longer shows a false error. ([GH #2910](https://github.com/kyb3r/modmail/issues/2910), [Jerrie-Aries](https://github.com/kyb3r/modmail/issues/2910#issuecomment-753557313)) +- Custom emojis are now supported in `confirm_thread_creation_deny`. ([GH #2916](https://github.com/modmail-dev/modmail/issues/2916)) +- Finding linked messages in replies work now. ([GH #2920](https://github.com/modmail-dev/modmail/issues/2920), [Jerrie-Aries](https://github.com/modmail-dev/modmail/issues/2920#issuecomment-751530495)) +- Sending files in threads (non-images) now work. ([GH #2926](https://github.com/modmail-dev/modmail/issues/2926)) +- Deleting messages no longer shows a false error. ([GH #2910](https://github.com/modmail-dev/modmail/issues/2910), [Jerrie-Aries](https://github.com/modmail-dev/modmail/issues/2910#issuecomment-753557313)) - Display an error on [Lottie](https://airbnb.io/lottie/#/) stickers, instead of failing the send. -- `?perms get` now shows role/user names. ([PR #2927](https://github.com/kyb3r/modmail/pull/2927)) +- `?perms get` now shows role/user names. ([PR #2927](https://github.com/modmail-dev/modmail/pull/2927)) ### Internal @@ -370,13 +378,13 @@ This update is a quick hotfix for a weird behaviour experienced on 1 Feb 2021 wh ### Added - Added `update_channel_id` to specify which channel autoupdate notifications were being sent to. -- Added `show_timestamp` to specify if timestamps should be displayed in message embeds. ([GH #2885](https://github.com/kyb3r/modmail/issues/2885)) +- Added `show_timestamp` to specify if timestamps should be displayed in message embeds. ([GH #2885](https://github.com/modmail-dev/modmail/issues/2885)) # v3.7.9 ### Fixed -- `perms add/remove` with permission levels should now work again. ([GH #2892](https://github.com/kyb3r/modmail/issues/2892), [PR #2893](https://github.com/kyb3r/modmail/pull/2893)) +- `perms add/remove` with permission levels should now work again. ([GH #2892](https://github.com/modmail-dev/modmail/issues/2892), [PR #2893](https://github.com/modmail-dev/modmail/pull/2893)) ### Improved @@ -386,7 +394,7 @@ This update is a quick hotfix for a weird behaviour experienced on 1 Feb 2021 wh ### Added -- Added `thread_contact_silently` to allow opening threads silently by default. ([PR #2887](https://github.com/kyb3r/modmail/pull/2887)) +- Added `thread_contact_silently` to allow opening threads silently by default. ([PR #2887](https://github.com/modmail-dev/modmail/pull/2887)) ### Fixed - Permission levels were not respected. @@ -412,7 +420,7 @@ This update is a quick hotfix for a weird behaviour experienced on 1 Feb 2021 wh ### Fixed - Autoupdate persists despite errors. -- Mention when normal thread created was not working. ([GH #2883](https://github.com/kyb3r/modmail/issues/2883)) +- Mention when normal thread created was not working. ([GH #2883](https://github.com/modmail-dev/modmail/issues/2883)) # v3.7.5 @@ -424,13 +432,13 @@ This update is a quick hotfix for a weird behaviour experienced on 1 Feb 2021 wh ### Fixed -- React to contact threads were treated like normal contact threads. ([GH #2881](https://github.com/kyb3r/modmail/issues/2881)) +- React to contact threads were treated like normal contact threads. ([GH #2881](https://github.com/modmail-dev/modmail/issues/2881)) # v3.7.2 ### Added -- Added `mention_channel_id` to specify which channel `alert_on_mention` was being sent to. ([GH #2880](https://github.com/kyb3r/modmail/issues/2880)) +- Added `mention_channel_id` to specify which channel `alert_on_mention` was being sent to. ([GH #2880](https://github.com/modmail-dev/modmail/issues/2880)) ### Fixed @@ -447,31 +455,31 @@ This update is a quick hotfix for a weird behaviour experienced on 1 Feb 2021 wh ### Added -- Plain replies functionality. Added commands `preply`, `pareply` and config `plain_reply_without_command`. ([GH #2872](https://github.com/kyb3r/modmail/issues/2872)) +- Plain replies functionality. Added commands `preply`, `pareply` and config `plain_reply_without_command`. ([GH #2872](https://github.com/modmail-dev/modmail/issues/2872)) - Added `react_to_contact_message`, `react_to_contact_emoji` to allow users to create threads by reacting to a message. -- Added `thread_move_notify_mods` to mention all mods again after moving thread. ([GH #215](https://github.com/kyb3r/modmail/issues/215)) -- Added `transfer_reactions` to link reactions between mods and users. ([GH #2763](https://github.com/kyb3r/modmail/issues/2763)) -- Added `close_on_leave`, `close_on_leave_reason` to automatically close threads upon recipient leaving the server. ([GH #2757](https://github.com/kyb3r/modmail/issues/2757)) -- Added `alert_on_mention` to mention mods upon a bot mention. ([GH #2833](https://github.com/kyb3r/modmail/issues/2833)) -- Added `confirm_thread_creation`, `confirm_thread_creation_title`, `confirm_thread_response`, `confirm_thread_creation_accept`, `confirm_thread_creation_deny` to allow users to confirm that they indeed want to create a new thread. ([GH #2773](https://github.com/kyb3r/modmail/issues/2773)) -- Support Gyazo image links in message embeds. ([GH #282](https://github.com/kyb3r/modmail/issues/282)) +- Added `thread_move_notify_mods` to mention all mods again after moving thread. ([GH #215](https://github.com/modmail-dev/modmail/issues/215)) +- Added `transfer_reactions` to link reactions between mods and users. ([GH #2763](https://github.com/modmail-dev/modmail/issues/2763)) +- Added `close_on_leave`, `close_on_leave_reason` to automatically close threads upon recipient leaving the server. ([GH #2757](https://github.com/modmail-dev/modmail/issues/2757)) +- Added `alert_on_mention` to mention mods upon a bot mention. ([GH #2833](https://github.com/modmail-dev/modmail/issues/2833)) +- Added `confirm_thread_creation`, `confirm_thread_creation_title`, `confirm_thread_response`, `confirm_thread_creation_accept`, `confirm_thread_creation_deny` to allow users to confirm that they indeed want to create a new thread. ([GH #2773](https://github.com/modmail-dev/modmail/issues/2773)) +- Support Gyazo image links in message embeds. ([GH #282](https://github.com/modmail-dev/modmail/issues/282)) - Added `silent` argument to `?contact` to restore old behaviour. -- Added new functionality: If `?help` is sent, bot does checks on every command, `?help all` restores old behaviour. ([GH #2847](https://github.com/kyb3r/modmail/issues/2847)) -- Added a way to block roles. ([GH #2753](https://github.com/kyb3r/modmail/issues/2753)) -- Added `cooldown_thread_title`, `cooldown_thread_response` to customise message sent when user is on a creating thread cooldown. ([GH #2865](https://github.com/kyb3r/modmail/issues/2865)) -- Added `?selfcontact` to allow users to open a thread. ([GH #2762](https://github.com/kyb3r/modmail/issues/2762)) +- Added new functionality: If `?help` is sent, bot does checks on every command, `?help all` restores old behaviour. ([GH #2847](https://github.com/modmail-dev/modmail/issues/2847)) +- Added a way to block roles. ([GH #2753](https://github.com/modmail-dev/modmail/issues/2753)) +- Added `cooldown_thread_title`, `cooldown_thread_response` to customise message sent when user is on a creating thread cooldown. ([GH #2865](https://github.com/modmail-dev/modmail/issues/2865)) +- Added `?selfcontact` to allow users to open a thread. ([GH #2762](https://github.com/modmail-dev/modmail/issues/2762)) - Support stickers and reject non-messages. (i.e. pin_add) -- Added support for thread titles, `?title`. ([GH #2838](https://github.com/kyb3r/modmail/issues/2838)) +- Added support for thread titles, `?title`. ([GH #2838](https://github.com/modmail-dev/modmail/issues/2838)) - Added `data_collection` to specify if bot metadata should be collected by Modmail developers. -- Added `?autotrigger`, `use_regex_autotrigger` config to specify keywords to trigger commands. ([GH #130](https://github.com/kyb3r/modmail/issues/130), [GH #649](https://github.com/kyb3r/modmail/issues/649)) -- Added `?note persistent` that creates notes that are persistent for a user. ([GH #2842](https://github.com/kyb3r/modmail/issues/2842), [PR #2878](https://github.com/kyb3r/modmail/pull/2878)) +- Added `?autotrigger`, `use_regex_autotrigger` config to specify keywords to trigger commands. ([GH #130](https://github.com/modmail-dev/modmail/issues/130), [GH #649](https://github.com/modmail-dev/modmail/issues/649)) +- Added `?note persistent` that creates notes that are persistent for a user. ([GH #2842](https://github.com/modmail-dev/modmail/issues/2842), [PR #2878](https://github.com/modmail-dev/modmail/pull/2878)) - Autoupdates and `?update` which was removed in v3.0.0 ### Fixed - `?contact` now sends members a DM. -- `level_permissions` and `command_permissions` would sometimes be reset. ([GH #2856](https://github.com/kyb3r/modmail/issues/2856)) -- Command truncated after && in alias. ([GH #2870](https://github.com/kyb3r/modmail/issues/2870)) +- `level_permissions` and `command_permissions` would sometimes be reset. ([GH #2856](https://github.com/modmail-dev/modmail/issues/2856)) +- Command truncated after && in alias. ([GH #2870](https://github.com/modmail-dev/modmail/issues/2870)) - `on_plugins_ready` event for plugins works now. ### Improved @@ -480,7 +488,7 @@ This update is a quick hotfix for a weird behaviour experienced on 1 Feb 2021 wh - `?move` now does not require exact category names, accepts case-insensitive and startswith names. ### Internal -- Use enums in config. ([GH #2821](https://github.com/kyb3r/modmail/issues/2821)) +- Use enums in config. ([GH #2821](https://github.com/modmail-dev/modmail/issues/2821)) - `on_thread_close` event for plugins. - `on_thread_reply` event for plugins. @@ -503,14 +511,14 @@ This update is a quick hotfix for a weird behaviour experienced on 1 Feb 2021 wh ### Added - Added `thread_move_title` to specify title of thread moved embed. -- Mark NSFW logs in log message. ([GH #2792](https://github.com/kyb3r/modmail/issues/2792)) -- Icon for moderator that closed the thread in log message. ([GH #2828](https://github.com/kyb3r/modmail/issues/2828)) -- Ability to set mentions via user/role ID. ([GH #2796](https://github.com/kyb3r/modmail/issues/2796)) +- Mark NSFW logs in log message. ([GH #2792](https://github.com/modmail-dev/modmail/issues/2792)) +- Icon for moderator that closed the thread in log message. ([GH #2828](https://github.com/modmail-dev/modmail/issues/2828)) +- Ability to set mentions via user/role ID. ([GH #2796](https://github.com/modmail-dev/modmail/issues/2796)) ### Changed - `?move` now consumes rest in category name, which means `?move Long Category Name` works without quotes! -- `?help` shows "No command description" if no description provided. ([PR #2845](https://github.com/kyb3r/modmail/pull/2845)) +- `?help` shows "No command description" if no description provided. ([PR #2845](https://github.com/modmail-dev/modmail/pull/2845)) ### Fixed - Unicode errors raised during windows selfhosting @@ -519,7 +527,7 @@ This update is a quick hotfix for a weird behaviour experienced on 1 Feb 2021 wh - Bump discord.py version to 1.5.1 - Explicitly state intents used for connection -- Use `--diff` for black CI instead of `--check` ([GH #2816](https://github.com/kyb3r/modmail/issues/2816)) +- Use `--diff` for black CI instead of `--check` ([GH #2816](https://github.com/modmail-dev/modmail/issues/2816)) # v3.5.0 @@ -529,7 +537,7 @@ Fixed discord.py issue. ### Added - A confirmation when you manually delete a thread message embed. -- Config var `enable_eval` defaults true, set `enable_eval=no` to disable the eval command. ([GH #2803](https://github.com/kyb3r/modmail/issues/2803)) +- Config var `enable_eval` defaults true, set `enable_eval=no` to disable the eval command. ([GH #2803](https://github.com/modmail-dev/modmail/issues/2803)) - Added `?plugins reset` command to completely reset everything related to plugins. This will fix some problems caused by broken plugins in the file system. - Support private GitHub repos for plugins (thanks to @officialpiyush pr#2767) @@ -838,7 +846,7 @@ Security update! - Removed auto-update functionality and the `?update` command in favor of the [Pull app](https://github.com/apps/pull). -Read more about updating your bot [here](https://github.com/kyb3r/modmail/wiki/updating) +Read more about updating your bot [here](https://github.com/modmail-dev/modmail/wiki/updating) ### Changed - Channel names now can contain Unicode characters. @@ -883,7 +891,7 @@ Added a ๐Ÿ›‘ reaction to the paginators to delete the embed. ### Fixed -`?blocked` is now paginated using reactions. This fixes [#249](https://github.com/kyb3r/modmail/issues/249) +`?blocked` is now paginated using reactions. This fixes [#249](https://github.com/modmail-dev/modmail/issues/249) # v2.21.0 @@ -922,7 +930,7 @@ This update contains mostly internal changes. ### What's new? -New `?oauth whitelist` command, which allows you to whitelist users so they can log in via discord to view logs. To set up oauth login for your logviewer app, check the logviewer [repo](https://github.com/kyb3r/logviewer). +New `?oauth whitelist` command, which allows you to whitelist users so they can log in via discord to view logs. To set up oauth login for your logviewer app, check the logviewer [repo](https://github.com/modmail-dev/logviewer). # v2.19.1 @@ -1207,7 +1215,7 @@ Added image link in title in case discord fails to embed an image. ### What's new? - Plugins: - Think of it like addons! Anyone (with the skills) can create a plugin, make it public and distribute it. Add a welcome message to Modmail, or moderation commands? It's all up to your imagination! Have a niche feature request that you think only your server would benefit? Plugins are your go-to! - - [Creating Plugins Documentation](https://github.com/kyb3r/modmail/wiki/Plugins). + - [Creating Plugins Documentation](https://github.com/modmail-dev/modmail/wiki/Plugins). # v2.12.5 @@ -1218,7 +1226,7 @@ Added image link in title in case discord fails to embed an image. # v2.12.4 ### What's new? -- Named colors are now supported! Over 900 different common color names are recognized. A list of color names can be found in [core/_color_data.py](https://github.com/kyb3r/modmail/blob/master/core/_color_data.py). +- Named colors are now supported! Over 900 different common color names are recognized. A list of color names can be found in [core/_color_data.py](https://github.com/modmail-dev/modmail/blob/master/core/_color_data.py). - Named colors can be set the same way as hex. But this can only be done through `config set`, which means database modifications will not work. - For example: `config set main_color yellowish green`. - New config var `main_color` allows you to customize the main Modmail color (as requested by many). Defaults to Discord `blurple`. @@ -1412,7 +1420,7 @@ Thread channels will now default to being private (`@everyone`'s read message pe ### Background - Bots hosted by Heroku restart at least once every 27 hours. - During this period, local caches will be deleted, which results in the inability to set the scheduled close time to longer than 24 hours. This update resolves this issue. -- [PR #135](https://github.com/kyb3r/modmail/pull/135) +- [PR #135](https://github.com/modmail-dev/modmail/pull/135) ### Changed - Created a new internal config var: `closures`. @@ -1450,7 +1458,7 @@ Fixed a bug in the `?activity` command where it would fail to set the activity o ### What's new? - Added the `?activity` command for setting the activity -- [PR #131](https://github.com/kyb3r/modmail/pull/131#issue-244686818) this supports multiple activity types (`playing`, `watching`, `listening`, and `streaming`). +- [PR #131](https://github.com/modmail-dev/modmail/pull/131#issue-244686818) this supports multiple activity types (`playing`, `watching`, `listening`, and `streaming`). ### Removed - Removed the deprecated `status` command. @@ -1583,9 +1591,9 @@ Fixed a bug in the `?activity` command where it would fail to set the activity o # v2.0.0 -This release introduces the use of our centralized [API service](https://github.com/kyb3r/webserver) to enable dynamic configuration, auto-updates, and thread logs. +This release introduces the use of our centralized [API service](https://github.com/modmail-dev/webserver) to enable dynamic configuration, auto-updates, and thread logs. To use this release, you must acquire an API token from https://modmail.tk. -Read the updated installation guide [here](https://github.com/kyb3r/modmail/wiki/installation). +Read the updated installation guide [here](https://github.com/modmail-dev/modmail/wiki/installation). ### Changed - Stability improvements through synchronization primitives. diff --git a/README.md b/README.md index 0a71061fd0..062bf6d8a4 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,16 @@ <br> - <a href="https://heroku.com/deploy?template=https://github.com/kyb3r/modmail"> + <a href="https://heroku.com/deploy?template=https://github.com/modmail-dev/modmail"> <img src="https://img.shields.io/badge/deploy_to-heroku-997FBC.svg?style=for-the-badge&logo=Heroku"> </a> - <a href="https://github.com/kyb3r/modmail/"> + <a href="https://github.com/modmail-dev/modmail/"> <img src="https://api.modmail.dev/badges/instances.svg" alt="Bot instances"> </a> - <a href="https://discord.gg/j5e9p8w"> - <img src="https://img.shields.io/discord/515071617815019520.svg?label=Discord&logo=Discord&colorB=7289da&style=for-the-badge" alt="Support"> + <a href="https://discord.gg/cnUpwrnpYb"> + <img src="https://img.shields.io/discord/1079074933008781362.svg?label=Discord&logo=Discord&colorB=7289da&style=for-the-badge" alt="Support"> </a> <a href="https://patreon.com/kyber"> @@ -35,7 +35,7 @@ <img src="https://img.shields.io/badge/Code%20Style-Black-black?style=for-the-badge"> </a> - <a href="https://github.com/kyb3r/modmail/blob/master/LICENSE"> + <a href="https://github.com/modmail-dev/modmail/blob/master/LICENSE"> <img src="https://img.shields.io/badge/license-agpl-e74c3c.svg?style=for-the-badge" alt="MIT License"> </a> @@ -96,23 +96,23 @@ There are a few options for hosting your very own dedicated Modmail bot. ### Patreon Hosting -If you don't want the trouble of renting and configuring your server to host Modmail, we got a solution for you! We offer hosting and maintenance of your own, private Modmail bot (including a Logviewer) through [**Patreon**](https://patreon.com/kyber). Join our [Modmail Discord Server](https://discord.gg/etJNHCQ) for more info! +If you don't want the trouble of renting and configuring your server to host Modmail, we got a solution for you! We offer hosting and maintenance of your own, private Modmail bot (including a Logviewer) through [**Patreon**](https://patreon.com/kyber). Join our [Modmail Discord Server](https://discord.gg/cnUpwrnpYb) for more info! ### Local hosting (General Guide) -Modmail can be hosted on any modern hardware, including your PC. For stability and reliability, we suggest purchasing a cloud server (VPS) for under $10/mo. If you need recommendations on choosing a VPS, join our [Discord server](https://discord.gg/j5e9p8w), and we'll send you a list of non-affiliated hosting providers. Alternatively, we can host Modmail for you when you're subscribed to our [Patreon](https://patreon.com/kyber). +Modmail can be hosted on any modern hardware, including your PC. For stability and reliability, we suggest purchasing a cloud server (VPS) for under $10/mo. If you need recommendations on choosing a VPS, join our [Discord server](https://discord.gg/cnUpwrnpYb), and we'll send you a list of non-affiliated hosting providers. Alternatively, we can host Modmail for you when you're subscribed to our [Patreon](https://patreon.com/kyber). This guide assumes you've downloaded [`Python 3.10`](https://www.python.org/downloads/release/python-376/) and added python and pip to PATH. 1. Clone this repo ```console - $ git clone https://github.com/kyb3r/modmail + $ git clone https://github.com/modmail-dev/modmail $ cd modmail ``` -2. Create a Discord bot account, grant the necessary intents, and invite the bot ([guide](https://github.com/kyb3r/modmail/wiki/Installation#2-discord-bot-account)) -3. Create a free MongoDB database ([guide](https://github.com/kyb3r/modmail/wiki/Installation-(cont.)#3-create-a-database), follow it carefully!) +2. Create a Discord bot account, grant the necessary intents, and invite the bot ([guide](https://github.com/modmail-dev/modmail/wiki/Installation#2-discord-bot-account)) +3. Create a free MongoDB database ([guide](https://github.com/modmail-dev/modmail/wiki/Installation-(cont.)#3-create-a-database), follow it carefully!) 4. Rename the file `.env.example` to `.env` and fill it with appropriate values - - If you can't find `.env.example` because it's hidden, create a new text file named `.env`, then copy the contents of [this file](https://raw.githubusercontent.com/kyb3r/modmail/master/.env.example) and replace the placeholders with their values + - If you can't find `.env.example` because it's hidden, create a new text file named `.env`, then copy the contents of [this file](https://raw.githubusercontent.com/modmail-dev/modmail/master/.env.example) and replace the placeholders with their values - If you're on Windows and cannot save the file as `.env`, save it as `.env.` instead (this only applies to Windows!) - If you do not have a Logviewer yet, leave the `LOG_URL` field as-is 5. Update pip, install pipenv, and install dependencies using pipenv @@ -125,16 +125,16 @@ This guide assumes you've downloaded [`Python 3.10`](https://www.python.org/down ```console $ pipenv run bot ``` -7. Set up the Logviewer, see the [Logviewer installation guide](https://github.com/kyb3r/logviewer) +7. Set up the Logviewer, see the [Logviewer installation guide](https://github.com/modmail-dev/logviewer) ### Local Hosting (Docker) We provide support for Docker to simplify the deployment of Modmail and Logviewer. We assume you already have Docker and Docker Compose Plugin installed, if not, see [here](https://docs.docker.com/get-docker/). -1. Create a Discord bot account, grant the necessary intents, and invite the bot ([guide](https://github.com/kyb3r/modmail/wiki/Installation#2-discord-bot-account)) -2. Create a file named `.env`, then copy the contents of [this file](https://raw.githubusercontent.com/kyb3r/modmail/master/.env.example) and replace the placeholders with their values -3. Create a file named `docker-compose.yml`, then copy the contents of [this file](https://raw.githubusercontent.com/kyb3r/modmail/master/docker-compose.yml), do not change anything! +1. Create a Discord bot account, grant the necessary intents, and invite the bot ([guide](https://github.com/modmail-dev/modmail/wiki/Installation#2-discord-bot-account)) +2. Create a file named `.env`, then copy the contents of [this file](https://raw.githubusercontent.com/modmail-dev/modmail/master/.env.example) and replace the placeholders with their values +3. Create a file named `docker-compose.yml`, then copy the contents of [this file](https://raw.githubusercontent.com/modmail-dev/modmail/master/docker-compose.yml), do not change anything! 4. Start the bot ```console $ docker compose up -d @@ -147,22 +147,22 @@ Our Docker images are hosted on [GitHub Container Registry](ghcr.io), you can bu $ docker build --tag=modmail:master . ``` -Then simply remove `ghcr.io/kyb3r/` from the `docker-compose.yml` file. +Then simply remove `ghcr.io/modmail-dev/` from the `docker-compose.yml` file. ### Local Hosting (OS-Specific) -This guide is a WIP. Join our [Discord server](https://discord.gg/j5e9p8w) for more info. +This guide is a WIP. Join our [Discord server](https://discord.gg/cnUpwrnpYb) for more info. ### Platform as a Service (PaaS) You can host this bot on Heroku (no longer free). Installation via Heroku is possible with your web browser alone. -The [**installation guide**](https://github.com/kyb3r/modmail/wiki/Installation) (which includes a video tutorial!) will guide you through the entire installation process. If you run into any problems, join our [Modmail Discord Server](https://discord.gg/etJNHCQ) for help and support. +The [**installation guide**](https://github.com/modmail-dev/modmail/wiki/Installation) (which includes a video tutorial!) will guide you through the entire installation process. If you run into any problems, join our [Modmail Discord Server](https://discord.gg/cnUpwrnpYb) for help and support. When using Heroku, you can configure automatic updates: - Login to [GitHub](https://github.com/) and verify your account. - - [Fork the repo](https://github.com/kyb3r/modmail/fork). + - [Fork the repo](https://github.com/modmail-dev/modmail/fork). - Install the [Pull app](https://github.com/apps/pull) for your fork. - Then go to the Deploy tab in your [Heroku account](https://dashboard.heroku.com/apps) of your bot app, select GitHub and connect your fork (usually by typing "Modmail"). - Turn on auto-deploy for the `master` branch. @@ -213,20 +213,20 @@ Become a sponsor on [Patreon](https://patreon.com/kyber). Modmail supports the use of third-party plugins to extend or add functionalities to the bot. Plugins allow niche features as well as anything else outside of the scope of the core functionality of Modmail. -You can find a list of third-party plugins using the `?plugins registry` command or visit the [Unofficial List of Plugins](https://github.com/kyb3r/modmail/wiki/Unofficial-List-of-Plugins) for a list of plugins contributed by the community. +You can find a list of third-party plugins using the `?plugins registry` command or visit the [Unofficial List of Plugins](https://github.com/modmail-dev/modmail/wiki/Unofficial-List-of-Plugins) for a list of plugins contributed by the community. -To develop your own, check out the [plugins documentation](https://github.com/kyb3r/modmail/wiki/Plugins). +To develop your own, check out the [plugins documentation](https://github.com/modmail-dev/modmail/wiki/Plugins). -Plugins requests and support are available in our [Modmail Support Server](https://discord.gg/j5e9p8w). +Plugins requests and support are available in our [Modmail Support Server](https://discord.gg/cnUpwrnpYb). ## Contributing -Contributions to Modmail are always welcome, whether it be improvements to the documentation or new functionality, please feel free to make the change. Check out our [contributing guidelines](https://github.com/kyb3r/modmail/blob/master/.github/CONTRIBUTING.md) before you get started. +Contributions to Modmail are always welcome, whether it be improvements to the documentation or new functionality, please feel free to make the change. Check out our [contributing guidelines](https://github.com/modmail-dev/modmail/blob/master/.github/CONTRIBUTING.md) before you get started. If you like this project and would like to show your appreciation, support us on **[Patreon](https://www.patreon.com/kyber)**! ## Beta Testing -Our [development](https://github.com/kyb3r/modmail/tree/development) branch is where most of our features are tested before public release. Be warned that there could be bugs in various commands so keep it away from any large servers you manage. +Our [development](https://github.com/modmail-dev/modmail/tree/development) branch is where most of our features are tested before public release. Be warned that there could be bugs in various commands so keep it away from any large servers you manage. If you wish to test the new features and play around with them, feel free to join our [Public Test Server](https://discord.gg/v5hTjKC). Bugs can be raised within that server or in our Github issues (state that you are using the development branch though). diff --git a/app.json b/app.json index 1cf5d107e4..eee99b54bf 100644 --- a/app.json +++ b/app.json @@ -1,7 +1,7 @@ { "name": "Modmail", "description": "An easy to install Modmail bot for Discord - DM to contact mods!", - "repository": "https://github.com/kyb3r/modmail", + "repository": "https://github.com/modmail-dev/modmail", "env": { "TOKEN": { "description": "Your discord bot's token.", diff --git a/cogs/modmail.py b/cogs/modmail.py index 376f954cbe..d620520487 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -94,7 +94,7 @@ async def setup(self, ctx): embed.add_field( name="Thanks for using our bot!", value="If you like what you see, consider giving the " - "[repo a star](https://github.com/kyb3r/modmail) :star: and if you are " + "[repo a star](https://github.com/modmail-dev/modmail) :star: and if you are " "feeling extra generous, buy us coffee on [Patreon](https://patreon.com/kyber) :heart:!", ) diff --git a/cogs/plugins.py b/cogs/plugins.py index c99f74ef40..f225d90caa 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -114,7 +114,7 @@ class Plugins(commands.Cog): These addons could have a range of features from moderation to simply making your life as a moderator easier! Learn how to create a plugin yourself here: - https://github.com/kyb3r/modmail/wiki/Plugins + https://github.com/modmail-dev/modmail/wiki/Plugins """ def __init__(self, bot): @@ -131,7 +131,7 @@ async def cog_load(self): logger.info("Plugins not loaded since ENABLE_PLUGINS=false.") async def populate_registry(self): - url = "https://raw.githubusercontent.com/kyb3r/modmail/master/plugins/registry.json" + url = "https://raw.githubusercontent.com/modmail-dev/modmail/master/plugins/registry.json" async with self.bot.session.get(url) as resp: self.registry = json.loads(await resp.text()) diff --git a/cogs/utility.py b/cogs/utility.py index 5c0ea09eb3..bcc1ea951a 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -351,7 +351,7 @@ async def about(self, ctx): embed.add_field( name="Want Modmail in Your Server?", - value="Follow the installation guide on [GitHub](https://github.com/kyb3r/modmail/) " + value="Follow the installation guide on [GitHub](https://github.com/modmail-dev/modmail/) " "and join our [Discord server](https://discord.gg/F34cRU8)!", inline=False, ) @@ -380,7 +380,7 @@ async def sponsors(self, ctx): """Shows the sponsors of this project.""" async with self.bot.session.get( - "https://raw.githubusercontent.com/kyb3r/modmail/master/SPONSORS.json" + "https://raw.githubusercontent.com/modmail-dev/modmail/master/SPONSORS.json" ) as resp: data = loads(await resp.text()) @@ -1941,7 +1941,7 @@ async def update(self, ctx, *, flag: str = ""): desc = ( f"The latest version is [`{self.bot.version}`]" - "(https://github.com/kyb3r/modmail/blob/master/bot.py#L1)" + "(https://github.com/modmail-dev/modmail/blob/master/bot.py#L1)" ) if self.bot.version >= parse_version(latest.version) and flag.lower() != "force": diff --git a/core/changelog.py b/core/changelog.py index a4f88ed323..06f141fce1 100644 --- a/core/changelog.py +++ b/core/changelog.py @@ -53,7 +53,7 @@ def __init__(self, bot, branch: str, version: str, lines: str): self.version = version.lstrip("vV") self.lines = lines.strip() self.fields = {} - self.changelog_url = f"https://github.com/kyb3r/modmail/blob/{branch}/CHANGELOG.md" + self.changelog_url = f"https://github.com/modmail-dev/modmail/blob/{branch}/CHANGELOG.md" self.description = "" self.parse() @@ -186,7 +186,7 @@ async def from_url(cls, bot, url: str = "") -> "Changelog": if branch not in ("master", "development"): branch = "master" - url = url or f"https://raw.githubusercontent.com/kyb3r/modmail/{branch}/CHANGELOG.md" + url = url or f"https://raw.githubusercontent.com/modmail-dev/modmail/{branch}/CHANGELOG.md" async with await bot.session.get(url) as resp: return cls(bot, branch, await resp.text()) diff --git a/core/clients.py b/core/clients.py index eebe3bcff6..f504b7051d 100644 --- a/core/clients.py +++ b/core/clients.py @@ -63,10 +63,10 @@ class GitHub: """ BASE = "https://api.github.com" - REPO = BASE + "/repos/kyb3r/modmail" + REPO = BASE + "/repos/modmail-dev/modmail" MERGE_URL = BASE + "/repos/{username}/modmail/merges" FORK_URL = REPO + "/forks" - STAR_URL = BASE + "/user/starred/kyb3r/modmail" + STAR_URL = BASE + "/user/starred/modmail-dev/modmail" def __init__(self, bot, access_token: str = "", username: str = "", **kwargs): self.bot = bot diff --git a/docker-compose.yml b/docker-compose.yml index 0bdd3808bd..fcb0e1b32f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.7" services: bot: - image: ghcr.io/kyb3r/modmail:master + image: ghcr.io/modmail-dev/modmail:master restart: always env_file: - .env @@ -10,7 +10,7 @@ services: depends_on: - mongo logviewer: - image: ghcr.io/kyb3r/logviewer:master + image: ghcr.io/modmail-dev/logviewer:master restart: always depends_on: - mongo diff --git a/pyproject.toml b/pyproject.toml index 468dc29112..751cc5a75a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,8 +30,8 @@ authors = [ 'Taki <noemail@example.com>' ] readme = 'README.md' -repository = 'https://github.com/kyb3r/modmail' -homepage = 'https://github.com/kyb3r/modmail' +repository = 'https://github.com/modmail-dev/modmail' +homepage = 'https://github.com/modmail-dev/modmail' keywords = ['discord', 'modmail'] [tool.pylint.format] From 960a36ea04774ab449f1b2c51a24f8fb8822ae7e Mon Sep 17 00:00:00 2001 From: Spencer C <109806759+SpencerIsGiddy@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:00:23 -0400 Subject: [PATCH 168/225] Lints: update to setup Python v4 (#3243) * Update lints.yml * Update lints.yml --------- Co-authored-by: Spencer Comfort <109806759+GiddyGoatGaming@users.noreply.github.com> Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- .github/workflows/lints.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 21bf39368e..0f254d2980 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} architecture: x64 From e91930440aebfedc425b067791b5e92f2533bdfe Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Tue, 14 Mar 2023 04:00:54 -0700 Subject: [PATCH 169/225] Remove python 3.8 and windows/macos lint check. (#3258) Signed-off-by: Taku <45324516+Taaku18@users.noreply.github.com> --- .github/workflows/lints.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 0f254d2980..eaad52221f 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -4,13 +4,12 @@ on: [push, pull_request] jobs: code-style: - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest strategy: matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] - python-version: ['3.8', '3.9', '3.10'] + python-version: ['3.9', '3.10'] - name: Python ${{ matrix.python-version }} on ${{ matrix.os }} + name: Python ${{ matrix.python-version }} on ubuntu-latest steps: - uses: actions/checkout@v3 From f2a434b0f0c32f7f61cdde0e16c2cd3b7b1b9d07 Mon Sep 17 00:00:00 2001 From: Cyrus Yip <54488650+RealCyGuy@users.noreply.github.com> Date: Tue, 14 Mar 2023 04:21:00 -0700 Subject: [PATCH 170/225] Fix replies in dms not being sent (#3239) * Fix replies not being sent * Use a list instead of a set --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.py b/bot.py index b23b2449b2..46eb00cb5c 100644 --- a/bot.py +++ b/bot.py @@ -888,7 +888,7 @@ async def process_dm_modmail(self, message: discord.Message) -> None: return sent_emoji, blocked_emoji = await self.retrieve_emoji() - if message.type != discord.MessageType.default: + if message.type not in [discord.MessageType.default, discord.MessageType.reply]: return thread = await self.threads.find(recipient=message.author) From 726fb0cedb930cf77f6b31a3dae1e854303c1268 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Tue, 14 Mar 2023 04:22:12 -0700 Subject: [PATCH 171/225] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfb6e3f27d..0c1631dec1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Fixed - `?alias make/create` as aliases to `?alias add`. This improves continuity between the bot and its command structure. ([PR #3195](https://github.com/kyb3r/modmail/pull/3195)) - Loading the blocked list with the `?blocked` command takes a long time when the list is large. ([PR #3242](https://github.com/kyb3r/modmail/pull/3242)) +- Reply not being forwarded from DM. (PR [#3239](https://github.com/modmail-dev/modmail/pull/3239)) # v4.0.2 From b21037cbd794a962569de6240c1d95c13009a64e Mon Sep 17 00:00:00 2001 From: Martin <box152535@gmail.com> Date: Tue, 14 Mar 2023 13:26:18 +0100 Subject: [PATCH 172/225] Reminder Plugin (#3254) * Reminder Plugin Created a reminder plugin * Fix indentations --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- plugins/registry.json | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/plugins/registry.json b/plugins/registry.json index 8b6d26bf5f..fe175ea58a 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -35,6 +35,15 @@ "icon_url": "https://i.imgur.com/qtE7AH8.png", "thumbnail_url": "https://i.imgur.com/qtE7AH8.png" }, + "reminder": { + "repository": "martinbndr/kyb3r-modmail-plugins", + "branch": "master", + "description": "Letยดs you create reminders.", + "bot_version": "4.0.0", + "title": "Reminder", + "icon_url": "https://raw.githubusercontent.com/martinbndr/kyb3r-modmail-plugins/master/reminder/logo.png", + "thumbnail_url": "https://raw.githubusercontent.com/martinbndr/kyb3r-modmail-plugins/master/reminder/logo.png" + }, "welcomer": { "repository": "fourjr/modmail-plugins", "branch": "v4", @@ -66,43 +75,43 @@ "repository": "fourjr/modmail-plugins", "branch": "v4", "description": "Allows managing server emotes via ?emoji", - "bot_version": "4.0.0", + "bot_version": "4.0.0", "title": "Emote Manager", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, - "gen-log": { + "gen-log": { "repository": "fourjr/modmail-plugins", "branch": "v4", "description": "Outputs a text log of a thread in a specified channel", - "bot_version": "4.0.0", + "bot_version": "4.0.0", "title": "Log Generator", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, - "media-logger": { + "media-logger": { "repository": "fourjr/modmail-plugins", "branch": "v4", "description": "Re-posts detected media from all visible channels into a specified logging channel", - "bot_version": "4.0.0", + "bot_version": "4.0.0", "title": "Media Logger", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, - "report": { + "report": { "repository": "fourjr/modmail-plugins", "branch": "v4", "description": "Specify an emoji to react with on messages. Generates a 'report' in specified logging channel upon react.", - "bot_version": "4.0.0", + "bot_version": "4.0.0", "title": "Report", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" }, - "top-supporters": { + "top-supporters": { "repository": "fourjr/modmail-plugins", "branch": "v4", "description": "Gathers and prints the top supporters of handling threads.", - "bot_version": "4.0.0", + "bot_version": "4.0.0", "title": "Top Supporters", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" From a7a7ce1390e6717bf41d82f8febc35a8a7c4147a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Serba?= <radoslaw@serba.ovh> Date: Thu, 18 May 2023 08:50:02 +0200 Subject: [PATCH 173/225] feat(build): drop root privileges, update .dockerignore --- .dockerignore | 5 +++++ Dockerfile | 3 +++ 2 files changed, 8 insertions(+) diff --git a/.dockerignore b/.dockerignore index 74003e7e30..4b3d7b8274 100644 --- a/.dockerignore +++ b/.dockerignore @@ -138,13 +138,18 @@ temp/ test.py # Other stuff +.dockerignore .env.example .gitignore .github/ app.json CHANGELOG.md +docker-compose.yml +LICENSE +PRIVACY.md Procfile pyproject.toml README.md Pipfile Pipfile.lock +SPONSORS.json diff --git a/Dockerfile b/Dockerfile index 3c88a0e7ca..2729a24826 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,3 +14,6 @@ COPY --from=build /inst /usr/local WORKDIR /modmailbot CMD ["python", "bot.py"] COPY . /modmailbot +RUN adduser --disabled-password --gecos '' app && \ + chown -R app /modmailbot +USER app From eb7995d90652345fd5521603ca25fbddb3e57549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Serba?= <radoslaw@serba.ovh> Date: Thu, 18 May 2023 08:57:55 +0200 Subject: [PATCH 174/225] feat(build): add Dockerfile to .dockerignore --- .dockerignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.dockerignore b/.dockerignore index 4b3d7b8274..27f3de980f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -144,6 +144,7 @@ test.py .github/ app.json CHANGELOG.md +Dockerfile docker-compose.yml LICENSE PRIVACY.md From fa1a9494e8f51542eb55b7ad986239a9f8c36cf0 Mon Sep 17 00:00:00 2001 From: lorenzo132 <50767078+lorenzo132@users.noreply.github.com> Date: Sun, 9 Jul 2023 06:35:01 +0200 Subject: [PATCH 175/225] Remove modmail_guild_id from env examples (#3281) * Update .env.example The removal of `modmail_guild_id` since its causing more confusion to people then it helps them. Features relying on this never were made. Signed-off-by: lorenzo132 <50767078+lorenzo132@users.noreply.github.com> * Update app.json --------- Signed-off-by: lorenzo132 <50767078+lorenzo132@users.noreply.github.com> --- .env.example | 1 - app.json | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.env.example b/.env.example index 44c91c59c7..14bdf060bf 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,5 @@ TOKEN=MyBotToken LOG_URL=https://logviewername.herokuapp.com/ GUILD_ID=1234567890 -MODMAIL_GUILD_ID=1234567890 OWNERS=Owner1ID,Owner2ID,Owner3ID CONNECTION_URI=mongodb+srv://mongodburi diff --git a/app.json b/app.json index eee99b54bf..decd58695c 100644 --- a/app.json +++ b/app.json @@ -11,10 +11,6 @@ "description": "The id for the server you are hosting this bot for.", "required": true }, - "MODMAIL_GUILD_ID": { - "description": "The ID of the discord server where the threads channels should be created (receiving server). Default to GUILD_ID.", - "required": false - }, "OWNERS": { "description": "Comma separated user IDs of people that are allowed to use owner only commands. (eval).", "required": true @@ -40,4 +36,4 @@ "required": false } } -} \ No newline at end of file +} From 319000b6b4c5e4523cb0de4e2a57c1cbd6f383f8 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 9 Jul 2023 10:34:13 +0000 Subject: [PATCH 176/225] Renamed user from app to modmail - Rename the user from 'app' to 'modmail', and made it a system user instead. - Moved user creation to a higher layer in the Dockerfile. Signed-off-by: Taku <45324516+Taaku18@users.noreply.github.com> --- Dockerfile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2729a24826..96a398fad4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,17 +3,18 @@ FROM python:3.10 as py FROM py as build RUN apt update && apt install -y g++ git + COPY requirements.txt / RUN pip install --prefix=/inst -U -r /requirements.txt FROM py -ENV USING_DOCKER yes COPY --from=build /inst /usr/local +ENV USING_DOCKER yes +RUN useradd --system --no-create-home modmail +USER modmail + WORKDIR /modmailbot CMD ["python", "bot.py"] -COPY . /modmailbot -RUN adduser --disabled-password --gecos '' app && \ - chown -R app /modmailbot -USER app +COPY --chown=modmail:modmail . /modmailbot From 8a68f42ea0c7c3df051d8e9f68b232f6c466abcc Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 9 Jul 2023 10:38:09 +0000 Subject: [PATCH 177/225] Added .git to .dockerignore and unignored some files Removed LICENSE, PRIVACY.md, and SPONSORS.json from .dockerignore. Although they don't affect the functionalities of the bot, we prefer to include them due to their respective purposes. Signed-off-by: Taku <45324516+Taaku18@users.noreply.github.com> --- .dockerignore | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.dockerignore b/.dockerignore index 27f3de980f..a3de147db4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -140,17 +140,15 @@ test.py # Other stuff .dockerignore .env.example +.git/ .gitignore .github/ app.json CHANGELOG.md Dockerfile docker-compose.yml -LICENSE -PRIVACY.md Procfile pyproject.toml README.md Pipfile Pipfile.lock -SPONSORS.json From fa572eed29fa9551c52ffc0897b8df5f4f33c394 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Thu, 13 Jul 2023 20:16:40 -0700 Subject: [PATCH 178/225] Fixed unset registry_plugins_only causing non-registry plugins to fail to install --- cogs/plugins.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cogs/plugins.py b/cogs/plugins.py index f225d90caa..4fb8341c70 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -302,10 +302,10 @@ async def parse_user_input(self, ctx, plugin_name, check_version=False): plugin = Plugin(user, repo, plugin_name, branch) else: - if not self.bot.config.get("registry_plugins_only", False): + if self.bot.config.get("registry_plugins_only"): embed = discord.Embed( - description="This plugin is not in the registry. " - "To install it, you must set `REGISTRY_PLUGINS_ONLY=false` in your .env file or config settings.", + description="This plugin is not in the registry. To install this plugin, " + "you must set `REGISTRY_PLUGINS_ONLY=no` or remove this key in your .env file.", color=self.bot.error_color, ) await ctx.send(embed=embed) From 389dfb68648c1616aafe611c0e2bde5321042070 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Thu, 13 Jul 2023 20:19:28 -0700 Subject: [PATCH 179/225] To avoid confusion, config.get() only accepts one pos argument now --- CHANGELOG.md | 3 +++ core/config.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46cf14177c..e191fafb5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Changed - Repo moved to https://github.com/modmail-dev/modmail. +### Internal +- `ConfigManager.get` no longer accepts two positional arguments: the `convert` argument is now keyword-only. + # v4.0.2 ### Breaking diff --git a/core/config.py b/core/config.py index 9a033167b7..9476352573 100644 --- a/core/config.py +++ b/core/config.py @@ -301,7 +301,7 @@ def __getitem__(self, key: str) -> typing.Any: def __delitem__(self, key: str) -> None: return self.remove(key) - def get(self, key: str, convert=True) -> typing.Any: + def get(self, key: str, *, convert: bool = True) -> typing.Any: key = key.lower() if key not in self.all_keys: raise InvalidConfigError(f'Configuration "{key}" is invalid.') From 5ddb4e0444c1195e730924f8b9471e87ac330198 Mon Sep 17 00:00:00 2001 From: Baptiste Girardeau <contact@bgirardeau.me> Date: Sat, 15 Jul 2023 13:36:18 +0200 Subject: [PATCH 180/225] Set smaller size for guild icons urls on embed icons (#3261) * Set size for guild icons on embeds * Update changelog * Format with black * Fixed incorrect function return type --------- Signed-off-by: Taku <45324516+Taaku18@users.noreply.github.com> Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- CHANGELOG.md | 3 +-- bot.py | 14 +++++++++----- cogs/modmail.py | 8 ++++---- cogs/utility.py | 9 ++++++--- core/thread.py | 8 +++++--- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index adee789203..bf75ef37d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,12 +13,11 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Loading the blocked list with the `?blocked` command takes a long time when the list is large. ([PR #3242](https://github.com/kyb3r/modmail/pull/3242)) - Reply not being forwarded from DM. (PR [#3239](https://github.com/modmail-dev/modmail/pull/3239)) -# [UNRELEASED] - ### Added - New .env config option: `REGISTRY_PLUGINS_ONLY`, restricts to only allow adding registry plugins. ([PR #3247](https://github.com/modmail-dev/modmail/pull/3247)) ### Changed +- Guild icons in embed footers and author urls now have a fixed size of 128. ([PR #3261](https://github.com/modmail-dev/modmail/pull/3261)) - Repo moved to https://github.com/modmail-dev/modmail. # v4.0.2 diff --git a/bot.py b/bot.py index 46eb00cb5c..8f2f74e00c 100644 --- a/bot.py +++ b/bot.py @@ -90,12 +90,16 @@ def __init__(self): self.plugin_db = PluginDatabaseClient(self) # Deprecated self.startup() - def get_guild_icon(self, guild: typing.Optional[discord.Guild]) -> str: + def get_guild_icon( + self, guild: typing.Optional[discord.Guild], *, size: typing.Optional[int] = None + ) -> str: if guild is None: guild = self.guild if guild.icon is None: return "https://cdn.discordapp.com/embed/avatars/0.png" - return guild.icon.url + if size is None: + return guild.icon.url + return guild.icon.with_size(size).url def _resolve_snippet(self, name: str) -> typing.Optional[str]: """ @@ -912,7 +916,7 @@ async def process_dm_modmail(self, message: discord.Message) -> None: ) embed.set_footer( text=self.config["disabled_new_thread_footer"], - icon_url=self.get_guild_icon(guild=message.guild), + icon_url=self.get_guild_icon(guild=message.guild, size=128), ) logger.info("A new thread was blocked from %s due to disabled Modmail.", message.author) await self.add_reaction(message, blocked_emoji) @@ -928,7 +932,7 @@ async def process_dm_modmail(self, message: discord.Message) -> None: ) embed.set_footer( text=self.config["disabled_current_thread_footer"], - icon_url=self.get_guild_icon(guild=message.guild), + icon_url=self.get_guild_icon(guild=message.guild, size=128), ) logger.info("A message was blocked from %s due to disabled Modmail.", message.author) await self.add_reaction(message, blocked_emoji) @@ -1335,7 +1339,7 @@ async def handle_react_to_contact(self, payload): ) embed.set_footer( text=self.config["disabled_new_thread_footer"], - icon_url=self.get_guild_icon(guild=channel.guild), + icon_url=self.get_guild_icon(guild=channel.guild, size=128), ) logger.info( "A new thread using react to contact was blocked from %s due to disabled Modmail.", diff --git a/cogs/modmail.py b/cogs/modmail.py index d95b74d465..21ee536dab 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -160,7 +160,7 @@ async def snippet(self, ctx, *, name: str.lower = None): color=self.bot.error_color, description="You dont have any snippets at the moment." ) embed.set_footer(text=f'Check "{self.bot.prefix}help snippet add" to add a snippet.') - embed.set_author(name="Snippets", icon_url=self.bot.get_guild_icon(guild=ctx.guild)) + embed.set_author(name="Snippets", icon_url=self.bot.get_guild_icon(guild=ctx.guild, size=128)) return await ctx.send(embed=embed) embeds = [] @@ -168,7 +168,7 @@ async def snippet(self, ctx, *, name: str.lower = None): for i, names in enumerate(zip_longest(*(iter(sorted(self.bot.snippets)),) * 15)): description = format_description(i, names) embed = discord.Embed(color=self.bot.main_color, description=description) - embed.set_author(name="Snippets", icon_url=self.bot.get_guild_icon(guild=ctx.guild)) + embed.set_author(name="Snippets", icon_url=self.bot.get_guild_icon(guild=ctx.guild, size=128)) embeds.append(embed) session = EmbedPaginatorSession(ctx, *embeds) @@ -1031,7 +1031,7 @@ async def anonadduser(self, ctx, *users_arg: Union[discord.Member, discord.Role, name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: - avatar_url = self.bot.get_guild_icon(guild=ctx.guild) + avatar_url = self.bot.get_guild_icon(guild=ctx.guild, size=128) em.set_footer(text=name, icon_url=avatar_url) for u in users: @@ -1120,7 +1120,7 @@ async def anonremoveuser(self, ctx, *users_arg: Union[discord.Member, discord.Ro name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: - avatar_url = self.bot.get_guild_icon(guild=ctx.guild) + avatar_url = self.bot.get_guild_icon(guild=ctx.guild, size=128) em.set_footer(text=name, icon_url=avatar_url) for u in users: diff --git a/cogs/utility.py b/cogs/utility.py index 245060c22b..b3a6d49aeb 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -1020,7 +1020,7 @@ async def alias(self, ctx, *, name: str.lower = None): color=self.bot.error_color, description="You dont have any aliases at the moment." ) embed.set_footer(text=f'Do "{self.bot.prefix}help alias" for more commands.') - embed.set_author(name="Aliases", icon_url=self.bot.get_guild_icon(guild=ctx.guild)) + embed.set_author(name="Aliases", icon_url=self.bot.get_guild_icon(guild=ctx.guild, size=128)) return await ctx.send(embed=embed) embeds = [] @@ -1028,7 +1028,9 @@ async def alias(self, ctx, *, name: str.lower = None): for i, names in enumerate(zip_longest(*(iter(sorted(self.bot.aliases)),) * 15)): description = utils.format_description(i, names) embed = discord.Embed(color=self.bot.main_color, description=description) - embed.set_author(name="Command Aliases", icon_url=self.bot.get_guild_icon(guild=ctx.guild)) + embed.set_author( + name="Command Aliases", icon_url=self.bot.get_guild_icon(guild=ctx.guild, size=128) + ) embeds.append(embed) session = EmbedPaginatorSession(ctx, *embeds) @@ -1612,7 +1614,8 @@ async def permissions_get( ) embed = discord.Embed(color=self.bot.main_color, description=description) embed.set_author( - name="Permission Overrides", icon_url=self.bot.get_guild_icon(guild=ctx.guild) + name="Permission Overrides", + icon_url=self.bot.get_guild_icon(guild=ctx.guild, size=128), ) embeds.append(embed) diff --git a/core/thread.py b/core/thread.py index 53cdd1d202..0d2fb6408c 100644 --- a/core/thread.py +++ b/core/thread.py @@ -228,7 +228,9 @@ async def send_recipient_genesis_message(): else: footer = self.bot.config["thread_creation_footer"] - embed.set_footer(text=footer, icon_url=self.bot.get_guild_icon(guild=self.bot.modmail_guild)) + embed.set_footer( + text=footer, icon_url=self.bot.get_guild_icon(guild=self.bot.modmail_guild, size=128) + ) embed.title = self.bot.config["thread_creation_title"] if creator is None or creator == recipient: @@ -521,7 +523,7 @@ async def _close(self, closer, silent=False, delete_channel=True, message=None, embed.description = message footer = self.bot.config["thread_close_footer"] - embed.set_footer(text=footer, icon_url=self.bot.get_guild_icon(guild=self.bot.guild)) + embed.set_footer(text=footer, icon_url=self.bot.get_guild_icon(guild=self.bot.guild, size=128)) if not silent: for user in self.recipients: @@ -957,7 +959,7 @@ async def send( name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: - avatar_url = self.bot.get_guild_icon(guild=self.bot.guild) + avatar_url = self.bot.get_guild_icon(guild=self.bot.guild, size=128) embed.set_author( name=name, icon_url=avatar_url, From b1f3645a830dd914158315af1daea47f6479b9f5 Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Sat, 15 Jul 2023 17:10:51 +0530 Subject: [PATCH 181/225] `logs id` command (#3196) * Update modmail.py * Update clients.py * Formatting * Change log id to log key, added id as an alias * Print the log even if it is closed and fix bug * Update modmail.py * Added a missing period * Updated changelog --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- CHANGELOG.md | 1 + cogs/modmail.py | 22 ++++++++++++++++++++++ core/clients.py | 10 ++++++++++ 3 files changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf75ef37d3..fad0639ae3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Added - New .env config option: `REGISTRY_PLUGINS_ONLY`, restricts to only allow adding registry plugins. ([PR #3247](https://github.com/modmail-dev/modmail/pull/3247)) +- `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196)) ### Changed - Guild icons in embed footers and author urls now have a fixed size of 128. ([PR #3261](https://github.com/modmail-dev/modmail/pull/3261)) diff --git a/cogs/modmail.py b/cogs/modmail.py index 21ee536dab..d72ea78cd5 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1212,6 +1212,28 @@ async def logs_closed_by(self, ctx, *, user: User = None): session = EmbedPaginatorSession(ctx, *embeds) await session.run() + @logs.command(name="key", aliases=["id"]) + @checks.has_permissions(PermissionLevel.SUPPORTER) + async def logs_key(self, ctx, key: str): + """ + Get the log link for the specified log key. + """ + icon_url = ctx.author.avatar.url + + logs = await self.bot.api.find_log_entry(key) + + if not logs: + embed = discord.Embed( + color=self.bot.error_color, + description=f"Log entry `{key}` not found.", + ) + return await ctx.send(embed=embed) + + embeds = self.format_log_embeds(logs, avatar_url=icon_url) + + session = EmbedPaginatorSession(ctx, *embeds) + await session.run() + @logs.command(name="delete", aliases=["wipe"]) @checks.has_permissions(PermissionLevel.OWNER) async def logs_delete(self, ctx, key_or_link: str): diff --git a/core/clients.py b/core/clients.py index f504b7051d..61c39fdd4b 100644 --- a/core/clients.py +++ b/core/clients.py @@ -356,6 +356,9 @@ async def validate_database_connection(self): async def get_user_logs(self, user_id: Union[str, int]) -> list: return NotImplemented + async def find_log_entry(self, key: str) -> list: + return NotImplemented + async def get_latest_user_logs(self, user_id: Union[str, int]): return NotImplemented @@ -529,6 +532,13 @@ async def get_user_logs(self, user_id: Union[str, int]) -> list: return await self.logs.find(query, projection).to_list(None) + async def find_log_entry(self, key: str) -> list: + query = {"key": key} + projection = {"messages": {"$slice": 5}} + logger.debug(f"Retrieving log ID {key}.") + + return await self.logs.find(query, projection).to_list(None) + async def get_latest_user_logs(self, user_id: Union[str, int]): query = {"recipient.id": str(user_id), "guild_id": str(self.bot.guild_id), "open": False} projection = {"messages": {"$slice": 5}} From 43fbc312cfe9f1f8d8222f3e80a39ea5394038ea Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Sat, 15 Jul 2023 19:45:36 +0800 Subject: [PATCH 182/225] Enable discord.py logger by default. (#3216) * Enable `discord.py` logger by default. * Revert: - Restore import orders - Logging stuff is now completely handled in `core.models.configure_logging` * Update logging configurations * Updated changelog * Fix overflow characters in logs when using `?debug` command. * Update changelog --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- CHANGELOG.md | 9 +- bot.py | 41 +------- cogs/utility.py | 23 +---- core/config.py | 1 + core/config_help.json | 9 ++ core/models.py | 214 +++++++++++++++++++++++++++++++----------- 6 files changed, 185 insertions(+), 112 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fad0639ae3..d90473d40d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,12 +14,17 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Reply not being forwarded from DM. (PR [#3239](https://github.com/modmail-dev/modmail/pull/3239)) ### Added -- New .env config option: `REGISTRY_PLUGINS_ONLY`, restricts to only allow adding registry plugins. ([PR #3247](https://github.com/modmail-dev/modmail/pull/3247)) - `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196)) +- `REGISTRY_PLUGINS_ONLY`, environment variable, when set, restricts to only allow adding registry plugins. ([PR #3247](https://github.com/modmail-dev/modmail/pull/3247)) +- `DISCORD_LOG_LEVEL` environment variable to set the log level of discord.py. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) ### Changed -- Guild icons in embed footers and author urls now have a fixed size of 128. ([PR #3261](https://github.com/modmail-dev/modmail/pull/3261)) - Repo moved to https://github.com/modmail-dev/modmail. +- Guild icons in embed footers and author urls now have a fixed size of 128. ([PR #3261](https://github.com/modmail-dev/modmail/pull/3261)) +- Discord.py internal logging is now enabled by default. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) + +### Internal +- Renamed `Bot.log_file_name` to `Bot.log_file_path`. Log files are now created at `temp/logs/modmail.log`. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) # v4.0.2 diff --git a/bot.py b/bot.py index 8f2f74e00c..45530a908f 100644 --- a/bot.py +++ b/bot.py @@ -52,7 +52,6 @@ logger = getLogger(__name__) - temp_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "temp") if not os.path.exists(temp_dir): os.mkdir(temp_dir) @@ -84,8 +83,11 @@ def __init__(self): self.threads = ThreadManager(self) - self.log_file_name = os.path.join(temp_dir, f"{self.token.split('.')[0]}.log") - self._configure_logging() + log_dir = os.path.join(temp_dir, "logs") + if not os.path.exists(log_dir): + os.mkdir(log_dir) + self.log_file_path = os.path.join(log_dir, "modmail.log") + configure_logging(self) self.plugin_db = PluginDatabaseClient(self) # Deprecated self.startup() @@ -182,29 +184,6 @@ async def load_extensions(self): logger.exception("Failed to load %s.", cog) logger.line("debug") - def _configure_logging(self): - level_text = self.config["log_level"].upper() - logging_levels = { - "CRITICAL": logging.CRITICAL, - "ERROR": logging.ERROR, - "WARNING": logging.WARNING, - "INFO": logging.INFO, - "DEBUG": logging.DEBUG, - } - logger.line() - - log_level = logging_levels.get(level_text) - if log_level is None: - log_level = self.config.remove("log_level") - logger.warning("Invalid logging level set: %s.", level_text) - logger.warning("Using default logging level: INFO.") - else: - logger.info("Logging level: %s", level_text) - - logger.info("Log file: %s", self.log_file_name) - configure_logging(self.log_file_name, log_level) - logger.debug("Successfully configured logging.") - @property def version(self): return parse_version(__version__) @@ -1801,16 +1780,6 @@ def main(): ) sys.exit(0) - # Set up discord.py internal logging - if os.environ.get("LOG_DISCORD"): - logger.debug(f"Discord logging enabled: {os.environ['LOG_DISCORD'].upper()}") - d_logger = logging.getLogger("discord") - - d_logger.setLevel(os.environ["LOG_DISCORD"].upper()) - handler = logging.FileHandler(filename="discord.log", encoding="utf-8", mode="w") - handler.setFormatter(logging.Formatter("%(asctime)s:%(levelname)s:%(name)s: %(message)s")) - d_logger.addHandler(handler) - bot = ModmailBot() bot.run() diff --git a/cogs/utility.py b/cogs/utility.py index b3a6d49aeb..47889c2c93 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -401,13 +401,7 @@ async def sponsors(self, ctx): async def debug(self, ctx): """Shows the recent application logs of the bot.""" - log_file_name = self.bot.token.split(".")[0] - - with open( - os.path.join(os.path.dirname(os.path.abspath(__file__)), f"../temp/{log_file_name}.log"), - "r+", - encoding="utf-8", - ) as f: + with open(self.bot.log_file_path, "r+", encoding="utf-8") as f: logs = f.read().strip() if not logs: @@ -433,7 +427,7 @@ async def debug(self, ctx): msg = "```Haskell\n" msg += line if len(msg) + 3 > 2000: - msg = msg[:1993] + "[...]```" + msg = msg[:1992] + "[...]```" messages.append(msg) msg = "```Haskell\n" @@ -455,12 +449,8 @@ async def debug_hastebin(self, ctx): """Posts application-logs to Hastebin.""" haste_url = os.environ.get("HASTE_URL", "https://hastebin.cc") - log_file_name = self.bot.token.split(".")[0] - with open( - os.path.join(os.path.dirname(os.path.abspath(__file__)), f"../temp/{log_file_name}.log"), - "rb+", - ) as f: + with open(self.bot.log_file_path, "rb+") as f: logs = BytesIO(f.read().strip()) try: @@ -491,12 +481,7 @@ async def debug_hastebin(self, ctx): async def debug_clear(self, ctx): """Clears the locally cached logs.""" - log_file_name = self.bot.token.split(".")[0] - - with open( - os.path.join(os.path.dirname(os.path.abspath(__file__)), f"../temp/{log_file_name}.log"), - "w", - ): + with open(self.bot.log_file_path, "w"): pass await ctx.send( embed=discord.Embed(color=self.bot.main_color, description="Cached logs are now cleared.") diff --git a/core/config.py b/core/config.py index 9a033167b7..fa48864aed 100644 --- a/core/config.py +++ b/core/config.py @@ -178,6 +178,7 @@ class ConfigManager: "disable_updates": False, # Logging "log_level": "INFO", + "discord_log_level": "INFO", # data collection "data_collection": True, } diff --git a/core/config_help.json b/core/config_help.json index e7ebb9590d..f5b08d64ad 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -1129,6 +1129,15 @@ "This configuration can only to be set through `.env` file or environment (config) variables." ] }, + "discord_log_level": { + "default": "INFO", + "description": "The `discord.py` library logging level for logging to stdout.", + "examples": [ + ], + "notes": [ + "This configuration can only to be set through `.env` file or environment (config) variables." + ] + }, "enable_plugins": { "default": "Yes", "description": "Whether plugins should be enabled and loaded into Modmail.", diff --git a/core/models.py b/core/models.py index 2eab1ceebb..29f6af71bb 100644 --- a/core/models.py +++ b/core/models.py @@ -1,16 +1,19 @@ import logging +import os import re import sys -import os +import _string + from difflib import get_close_matches from enum import IntEnum +from logging import FileHandler, StreamHandler, Handler from logging.handlers import RotatingFileHandler from string import Formatter +from typing import Optional import discord from discord.ext import commands -import _string try: from colorama import Fore, Style @@ -23,29 +26,6 @@ Fore = Style = type("Dummy", (object,), {"__getattr__": lambda self, item: ""})() -class PermissionLevel(IntEnum): - OWNER = 5 - ADMINISTRATOR = 4 - ADMIN = 4 - MODERATOR = 3 - MOD = 3 - SUPPORTER = 2 - RESPONDER = 2 - REGULAR = 1 - INVALID = -1 - - -class InvalidConfigError(commands.BadArgument): - def __init__(self, msg, *args): - super().__init__(msg, *args) - self.msg = msg - - @property - def embed(self): - # Single reference of Color.red() - return discord.Embed(title="Error", description=self.msg, color=discord.Color.red()) - - class ModmailLogger(logging.Logger): @staticmethod def _debug_(*msgs): @@ -94,18 +74,92 @@ def line(self, level="info"): ) -logging.setLoggerClass(ModmailLogger) -log_level = logging.INFO -loggers = set() +class FileFormatter(logging.Formatter): + ansi_escape = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]") + + def format(self, record): + record.msg = self.ansi_escape.sub("", record.msg) + return super().format(record) + -ch = logging.StreamHandler(stream=sys.stdout) -ch.setLevel(log_level) -formatter = logging.Formatter( +log_stream_formatter = logging.Formatter( "%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s", datefmt="%m/%d/%y %H:%M:%S" ) -ch.setFormatter(formatter) +log_file_formatter = FileFormatter( + "%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", +) -ch_debug = None + +def create_log_handler( + filename: Optional[str] = None, + *, + rotating: bool = False, + level: int = logging.DEBUG, + mode: str = "a+", + encoding: str = "utf-8", + maxBytes: int = 28000000, + backupCount: int = 1, + **kwargs, +) -> Handler: + """ + Creates a pre-configured log handler. This function is made for consistency's sake with + pre-defined default values for parameters and formatters to pass to handler class. + Additional keyword arguments also can be specified, just in case. + + Plugin developers should not use this and use `models.getLogger` instead. + + Parameters + ---------- + filename : Optional[Path] + Specifies that a `FileHandler` or `RotatingFileHandler` be created, using the specified filename, + rather than a `StreamHandler`. Defaults to `None`. + rotating : bool + Whether the file handler should be the `RotatingFileHandler`. Defaults to `False`. Note, this + argument only compatible if the `filename` is specified, otherwise `ValueError` will be raised. + level : int + The root logger level for the handler. Defaults to `logging.DEBUG`. + mode : str + If filename is specified, open the file in this mode. Defaults to 'a+'. + encoding : str + If this keyword argument is specified along with filename, its value is used when the `FileHandler` is created, + and thus used when opening the output file. Defaults to 'utf-8'. + maxBytes : int + The max file size before the rollover occurs. Defaults to 28000000 (28MB). Rollover occurs whenever the current + log file is nearly `maxBytes` in length; but if either of `maxBytes` or `backupCount` is zero, + rollover never occurs, so you generally want to set `backupCount` to at least 1. + backupCount : int + Max number of backup files. Defaults to 1. If this is set to zero, rollover will never occur. + + Returns + ------- + `StreamHandler` when `filename` is `None`, otherwise `FileHandler` or `RotatingFileHandler` + depending on the `rotating` value. + """ + if filename is None and rotating: + raise ValueError("`filename` must be set to instantiate a `RotatingFileHandler`.") + + if filename is None: + handler = StreamHandler(stream=sys.stdout, **kwargs) + handler.setFormatter(log_stream_formatter) + elif not rotating: + handler = FileHandler(filename, mode=mode, encoding=encoding, **kwargs) + handler.setFormatter(log_file_formatter) + else: + handler = RotatingFileHandler( + filename, mode=mode, encoding=encoding, maxBytes=maxBytes, backupCount=backupCount, **kwargs + ) + handler.setFormatter(log_file_formatter) + + handler.setLevel(level) + return handler + + +logging.setLoggerClass(ModmailLogger) +log_level = logging.INFO +loggers = set() +ch = create_log_handler(level=log_level) +ch_debug: Optional[RotatingFileHandler] = None def getLogger(name=None) -> ModmailLogger: @@ -118,33 +172,71 @@ def getLogger(name=None) -> ModmailLogger: return logger -class FileFormatter(logging.Formatter): - ansi_escape = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]") - - def format(self, record): - record.msg = self.ansi_escape.sub("", record.msg) - return super().format(record) - - -def configure_logging(name, level=None): +def configure_logging(bot) -> None: global ch_debug, log_level - ch_debug = RotatingFileHandler(name, mode="a+", maxBytes=48000, backupCount=1, encoding="utf-8") - formatter_debug = FileFormatter( - "%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", - ) - ch_debug.setFormatter(formatter_debug) - ch_debug.setLevel(logging.DEBUG) + logger = getLogger(__name__) + level_text = bot.config["log_level"].upper() + logging_levels = { + "CRITICAL": logging.CRITICAL, + "ERROR": logging.ERROR, + "WARNING": logging.WARNING, + "INFO": logging.INFO, + "DEBUG": logging.DEBUG, + } + logger.line() + + level = logging_levels.get(level_text) + if level is None: + level = bot.config.remove("log_level") + logger.warning("Invalid logging level set: %s.", level_text) + logger.warning("Using default logging level: %s.", level) + level = logging_levels[level] + else: + logger.info("Logging level: %s", level_text) + log_level = level + + logger.info("Log file: %s", bot.log_file_path) + ch_debug = create_log_handler(bot.log_file_path, rotating=True) + ch.setLevel(log_level) - if level is not None: - log_level = level + for log in loggers: + log.setLevel(log_level) + log.addHandler(ch_debug) + + # Set up discord.py logging + d_level_text = bot.config["discord_log_level"].upper() + d_level = logging_levels.get(d_level_text) + if d_level is None: + d_level = bot.config.remove("discord_log_level") + logger.warning("Invalid discord logging level set: %s.", d_level_text) + logger.warning("Using default discord logging level: %s.", d_level) + d_level = logging_levels[d_level] + d_logger = logging.getLogger("discord") + d_logger.setLevel(d_level) + + non_verbose_log_level = max(d_level, logging.INFO) + stream_handler = create_log_handler(level=non_verbose_log_level) + if non_verbose_log_level != d_level: + logger.info("Discord logging level (stdout): %s.", logging.getLevelName(non_verbose_log_level)) + logger.info("Discord logging level (logfile): %s.", logging.getLevelName(d_level)) + else: + logger.info("Discord logging level: %s.", logging.getLevelName(d_level)) + d_logger.addHandler(stream_handler) + d_logger.addHandler(ch_debug) + + logger.debug("Successfully configured logging.") - ch.setLevel(log_level) - for logger in loggers: - logger.setLevel(log_level) - logger.addHandler(ch_debug) +class InvalidConfigError(commands.BadArgument): + def __init__(self, msg, *args): + super().__init__(msg, *args) + self.msg = msg + + @property + def embed(self): + # Single reference of Color.red() + return discord.Embed(title="Error", description=self.msg, color=discord.Color.red()) class _Default: @@ -271,6 +363,18 @@ async def ack(self): return +class PermissionLevel(IntEnum): + OWNER = 5 + ADMINISTRATOR = 4 + ADMIN = 4 + MODERATOR = 3 + MOD = 3 + SUPPORTER = 2 + RESPONDER = 2 + REGULAR = 1 + INVALID = -1 + + class DMDisabled(IntEnum): NONE = 0 NEW_THREADS = 1 From a784f8299d023428e9a9d5a6fde0e06aab4d4feb Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Sat, 15 Jul 2023 19:48:33 +0800 Subject: [PATCH 183/225] Cleanup after unloading extension. (#3226) * Cleanup after unloading extension, resolve #3223. * Remove leftover modules loaded from `plugins` path when purging. --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- CHANGELOG.md | 1 + cogs/plugins.py | 37 ++++++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d90473d40d..68502a05a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `?alias make/create` as aliases to `?alias add`. This improves continuity between the bot and its command structure. ([PR #3195](https://github.com/kyb3r/modmail/pull/3195)) - Loading the blocked list with the `?blocked` command takes a long time when the list is large. ([PR #3242](https://github.com/kyb3r/modmail/pull/3242)) - Reply not being forwarded from DM. (PR [#3239](https://github.com/modmail-dev/modmail/pull/3239)) +- Cleanup imports after removing/unloading a plugin. ([PR #3226](https://github.com/modmail-dev/Modmail/pull/3226)) ### Added - `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196)) diff --git a/cogs/plugins.py b/cogs/plugins.py index f225d90caa..b4d7ca415c 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -264,6 +264,17 @@ async def load_plugin(self, plugin): logger.error("Plugin load failure: %s", plugin.ext_string, exc_info=True) raise InvalidPluginError("Cannot load extension, plugin invalid.") from exc + async def unload_plugin(self, plugin: Plugin) -> None: + try: + await self.bot.unload_extension(plugin.ext_string) + except commands.ExtensionError as exc: + raise exc + + ext_parent = ".".join(plugin.ext_string.split(".")[:-1]) + for module in list(sys.modules.keys()): + if module == ext_parent or module.startswith(ext_parent + "."): + del sys.modules[module] + async def parse_user_input(self, ctx, plugin_name, check_version=False): if not self.bot.config["enable_plugins"]: @@ -378,7 +389,7 @@ async def plugins_add(self, ctx, *, plugin_name: str): logger.warning("Unable to download plugin %s.", plugin, exc_info=True) embed = discord.Embed( - description=f"Failed to download plugin, check logs for error.\n{type(e)}: {e}", + description=f"Failed to download plugin, check logs for error.\n{type(e).__name__}: {e}", color=self.bot.error_color, ) @@ -397,7 +408,7 @@ async def plugins_add(self, ctx, *, plugin_name: str): logger.warning("Unable to load plugin %s.", plugin, exc_info=True) embed = discord.Embed( - description=f"Failed to download plugin, check logs for error.\n{type(e)}: {e}", + description=f"Failed to load plugin, check logs for error.\n{type(e).__name__}: {e}", color=self.bot.error_color, ) @@ -438,7 +449,7 @@ async def plugins_remove(self, ctx, *, plugin_name: str): if self.bot.config.get("enable_plugins"): try: - await self.bot.unload_extension(plugin.ext_string) + await self.unload_plugin(plugin) self.loaded_plugins.remove(plugin) except (commands.ExtensionNotLoaded, KeyError): logger.warning("Plugin was never loaded.") @@ -480,9 +491,10 @@ async def update_plugin(self, ctx, plugin_name): await self.download_plugin(plugin, force=True) if self.bot.config.get("enable_plugins"): try: - await self.bot.unload_extension(plugin.ext_string) + await self.unload_plugin(plugin) except commands.ExtensionError: logger.warning("Plugin unload fail.", exc_info=True) + try: await self.load_plugin(plugin) except Exception: @@ -529,17 +541,20 @@ async def plugins_reset(self, ctx): for ext in list(self.bot.extensions): if not ext.startswith("plugins."): continue + logger.error("Unloading plugin: %s.", ext) try: - logger.error("Unloading plugin: %s.", ext) - await self.bot.unload_extension(ext) - except Exception: - logger.error("Failed to unload plugin: %s.", ext) - else: - if not self.loaded_plugins: - continue plugin = next((p for p in self.loaded_plugins if p.ext_string == ext), None) if plugin: + await self.unload_plugin(plugin) self.loaded_plugins.remove(plugin) + else: + await self.bot.unload_extension(ext) + except Exception: + logger.error("Failed to unload plugin: %s.", ext) + + for module in list(sys.modules.keys()): + if module.startswith("plugins."): + del sys.modules[module] self.bot.config["plugins"].clear() await self.bot.config.update() From cc21725f2ff31a0566c7efe691a6bf87e4174bbd Mon Sep 17 00:00:00 2001 From: Cordila <49218334+Cordila@users.noreply.github.com> Date: Sat, 15 Jul 2023 17:23:46 +0530 Subject: [PATCH 184/225] Fix typo #3210 (#3233) * Fix typo * Rephrase the silently close messsage * Update changelog --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- CHANGELOG.md | 1 + cogs/modmail.py | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68502a05a0..e69f0f1849 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Loading the blocked list with the `?blocked` command takes a long time when the list is large. ([PR #3242](https://github.com/kyb3r/modmail/pull/3242)) - Reply not being forwarded from DM. (PR [#3239](https://github.com/modmail-dev/modmail/pull/3239)) - Cleanup imports after removing/unloading a plugin. ([PR #3226](https://github.com/modmail-dev/Modmail/pull/3226)) +- Fixed a syntactic error in the close message when a thread is closed after a certain duration. ([PR #3233](https://github.com/modmail-dev/Modmail/pull/3233)) ### Added - `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196)) diff --git a/cogs/modmail.py b/cogs/modmail.py index d72ea78cd5..33086116c5 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -444,11 +444,9 @@ async def move(self, ctx, *, arguments): async def send_scheduled_close_message(self, ctx, after, silent=False): human_delta = human_timedelta(after.dt) - silent = "*silently* " if silent else "" - embed = discord.Embed( title="Scheduled close", - description=f"This thread will close {silent}{human_delta}.", + description=f"This thread will{' silently' if silent else ''} close in {human_delta}.", color=self.bot.error_color, ) From 1adbacfad21f12691d9b170d1c52ad61fad2ec9f Mon Sep 17 00:00:00 2001 From: Cyrus Yip <cyruscmyip1@gmail.com> Date: Sat, 15 Jul 2023 04:56:33 -0700 Subject: [PATCH 185/225] Strip whitespace in help command titles (#3271) * strip help command title * Update changelog --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- CHANGELOG.md | 1 + cogs/utility.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e69f0f1849..3feb557449 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Reply not being forwarded from DM. (PR [#3239](https://github.com/modmail-dev/modmail/pull/3239)) - Cleanup imports after removing/unloading a plugin. ([PR #3226](https://github.com/modmail-dev/Modmail/pull/3226)) - Fixed a syntactic error in the close message when a thread is closed after a certain duration. ([PR #3233](https://github.com/modmail-dev/Modmail/pull/3233)) +- Removed an extra space in the help command title when the command has no parameters. ([PR #3271](https://github.com/modmail-dev/Modmail/pull/3271)) ### Added - `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196)) diff --git a/cogs/utility.py b/cogs/utility.py index 47889c2c93..5386a86770 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -142,7 +142,7 @@ async def _get_help_embed(self, topic): perm_level = "NONE" embed = discord.Embed( - title=f"`{self.get_command_signature(topic)}`", + title=f"`{self.get_command_signature(topic).strip()}`", color=self.context.bot.main_color, description=self.process_help_msg(topic.help), ) From 77fbb6937b09d8994fbafea74dd34535ba767ed0 Mon Sep 17 00:00:00 2001 From: Martin <box152535@gmail.com> Date: Sat, 15 Jul 2023 13:59:26 +0200 Subject: [PATCH 186/225] confirm_thread_creation Buttons instead of reactions (#3273) * Reminder Plugin Created a reminder plugin * Fix indentations * confirm_thread_creation Buttons instead of reactions * Changelog+Small fixes * Updated the react to confirm message, and removed changelog entry * Code linting with black * Update changelog --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- CHANGELOG.md | 1 + core/config.py | 2 +- core/config_help.json | 4 ++-- core/thread.py | 51 +++++++++++++++---------------------------- core/utils.py | 29 ++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3feb557449..35cabb1e58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Repo moved to https://github.com/modmail-dev/modmail. - Guild icons in embed footers and author urls now have a fixed size of 128. ([PR #3261](https://github.com/modmail-dev/modmail/pull/3261)) - Discord.py internal logging is now enabled by default. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) +- The confirm-thread-creation dialog now uses buttons instead of reactions. ([PR #3273](https://github.com/modmail-dev/Modmail/pull/3273)) ### Internal - Renamed `Bot.log_file_name` to `Bot.log_file_path`. Log files are now created at `temp/logs/modmail.log`. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) diff --git a/core/config.py b/core/config.py index fa48864aed..9e4cf949de 100644 --- a/core/config.py +++ b/core/config.py @@ -123,7 +123,7 @@ class ConfigManager: # confirm thread creation "confirm_thread_creation": False, "confirm_thread_creation_title": "Confirm thread creation", - "confirm_thread_response": "React to confirm thread creation which will directly contact the moderators", + "confirm_thread_response": "Click the button to confirm thread creation which will directly contact the moderators.", "confirm_thread_creation_accept": "\N{WHITE HEAVY CHECK MARK}", "confirm_thread_creation_deny": "\N{NO ENTRY SIGN}", # regex diff --git a/core/config_help.json b/core/config_help.json index f5b08d64ad..4fafd7a3a6 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -1014,10 +1014,10 @@ ] }, "confirm_thread_response": { - "default": "React to confirm thread creation which will directly contact the moderators", + "default": "Click the button to confirm thread creation which will directly contact the moderators.", "description": "Description for the embed message sent to users to confirm a thread creation", "examples":[ - "`{prefix}config set confirm_thread_response React to confirm`" + "`{prefix}config set confirm_thread_response Click to confirm`" ], "notes": [ "See also: `confirm_thread_creation`, `confirm_thread_creation_title`, `confirm_thread_creation_accept`, `confirm_thread_creation_deny`" diff --git a/core/thread.py b/core/thread.py index 0d2fb6408c..46be932c1a 100644 --- a/core/thread.py +++ b/core/thread.py @@ -29,6 +29,9 @@ get_top_role, create_thread_channel, get_joint_id, + AcceptButton, + DenyButton, + ConfirmThreadCreationView, ) logger = getLogger(__name__) @@ -1418,30 +1421,19 @@ async def create( destination = recipient else: destination = message.channel + view = ConfirmThreadCreationView() + view.add_item(AcceptButton(self.bot.config["confirm_thread_creation_accept"])) + view.add_item(DenyButton(self.bot.config["confirm_thread_creation_deny"])) confirm = await destination.send( embed=discord.Embed( title=self.bot.config["confirm_thread_creation_title"], description=self.bot.config["confirm_thread_response"], color=self.bot.main_color, - ) + ), + view=view, ) - accept_emoji = self.bot.config["confirm_thread_creation_accept"] - deny_emoji = self.bot.config["confirm_thread_creation_deny"] - emojis = [accept_emoji, deny_emoji] - for emoji in emojis: - await confirm.add_reaction(emoji) - await asyncio.sleep(0.2) - - try: - r, _ = await self.bot.wait_for( - "reaction_add", - check=lambda r, u: u.id == recipient.id - and r.message.id == confirm.id - and r.message.channel.id == confirm.channel.id - and str(r.emoji) in (accept_emoji, deny_emoji), - timeout=20, - ) - except asyncio.TimeoutError: + await view.wait() + if view.value is None: thread.cancelled = True self.bot.loop.create_task( destination.send( @@ -1452,23 +1444,16 @@ async def create( ) ) ) - else: - if str(r.emoji) == deny_emoji: - thread.cancelled = True - self.bot.loop.create_task( - destination.send( - embed=discord.Embed( - title=self.bot.config["thread_cancelled"], color=self.bot.error_color - ) + await confirm.edit(view=None) + if view.value is False: + thread.cancelled = True + self.bot.loop.create_task( + destination.send( + embed=discord.Embed( + title=self.bot.config["thread_cancelled"], color=self.bot.error_color ) ) - - async def remove_reactions(): - for emoji in emojis: - await confirm.remove_reaction(emoji, self.bot.user) - await asyncio.sleep(0.2) - - self.bot.loop.create_task(remove_reactions()) + ) if thread.cancelled: del self.cache[recipient.id] return thread diff --git a/core/utils.py b/core/utils.py index d8046ade5f..0e9f090d12 100644 --- a/core/utils.py +++ b/core/utils.py @@ -39,6 +39,9 @@ "get_top_role", "get_joint_id", "extract_block_timestamp", + "AcceptButton", + "DenyButton", + "ConfirmThreadCreationView", ] @@ -559,3 +562,29 @@ def extract_block_timestamp(reason, id_): raise return end_time, after + + +class AcceptButton(discord.ui.Button): + def __init__(self, emoji): + super().__init__(style=discord.ButtonStyle.gray, emoji=emoji) + + async def callback(self, interaction: discord.Interaction): + self.view.value = True + await interaction.response.edit_message(view=None) + self.view.stop() + + +class DenyButton(discord.ui.Button): + def __init__(self, emoji): + super().__init__(style=discord.ButtonStyle.gray, emoji=emoji) + + async def callback(self, interaction: discord.Interaction): + self.view.value = False + await interaction.response.edit_message(view=None) + self.view.stop() + + +class ConfirmThreadCreationView(discord.ui.View): + def __init__(self): + super().__init__(timeout=20) + self.value = None From 48bf245c24833c36a986ab670b50b1d999dc05cb Mon Sep 17 00:00:00 2001 From: Sebastian Kuipers <61157793+sebkuip@users.noreply.github.com> Date: Sat, 15 Jul 2023 14:01:48 +0200 Subject: [PATCH 187/225] Fixed the description of some config help descriptions having copy-paste errors (#3277) * Added the option for secure_plugins_only * Change config name * Forgot to update app.json * Forgot a period. Thanks taku :( * Fixed some copy-paste errors in descriptions * Update changelog --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- CHANGELOG.md | 1 + core/config_help.json | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35cabb1e58..2f27da4d1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Cleanup imports after removing/unloading a plugin. ([PR #3226](https://github.com/modmail-dev/Modmail/pull/3226)) - Fixed a syntactic error in the close message when a thread is closed after a certain duration. ([PR #3233](https://github.com/modmail-dev/Modmail/pull/3233)) - Removed an extra space in the help command title when the command has no parameters. ([PR #3271](https://github.com/modmail-dev/Modmail/pull/3271)) +- Corrected some incorrect config help descriptions. ([PR #3277](https://github.com/modmail-dev/Modmail/pull/3277)) ### Added - `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196)) diff --git a/core/config_help.json b/core/config_help.json index 4fafd7a3a6..f909d27821 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -131,7 +131,7 @@ "`{prefix}config set use_nickname_channel_name no`" ], "notes": [ - "This config is suitable for servers in Server Discovery to comply with channel name restrictions.", + "This config is NOT suitable for servers in Server Discovery to comply with channel name restrictions.", "This cannot be applied with `use_timestamp_channel_name`, `use_random_channel_name` or `use_user_id_channel_name`.", "See also: `use_timestamp_channel_name`, `use_user_id_channel_name`, `use_random_channel_name`." ] @@ -864,7 +864,7 @@ "default": "\"{{moderator.name}} has added you to a Modmail thread.\"", "description": "This is the message embed content sent to the recipient that is just added to a thread.", "examples": [ - "`{prefix}config set private_added_to_group_description Any message sent here will be sent to all otherthread recipients.`" + "`{prefix}config set private_added_to_group_response Any message sent here will be sent to all other thread recipients.`" ], "notes": [ "You may use the `{{moderator}}` variable for access to the [Member](https://discordpy.readthedocs.io/en/latest/api.html#discord.Member) that added the user.", @@ -936,7 +936,7 @@ "default": "\"{{moderator.name}} has removed you from the Modmail thread.\"", "description": "This is the message embed content sent to the recipient that is just removed from a thread.", "examples": [ - "`{prefix}config set private_removed_from_group_description Bye`" + "`{prefix}config set private_removed_from_group_response Bye`" ], "notes": [ "You may use the `{{moderator}}` variable for access to the [Member](https://discordpy.readthedocs.io/en/latest/api.html#discord.Member) that added the user.", From d4ec13ed058dddd6c4a84c7bf47f4c516618f526 Mon Sep 17 00:00:00 2001 From: Martin <box152535@gmail.com> Date: Sat, 15 Jul 2023 14:04:53 +0200 Subject: [PATCH 188/225] [Fix] disable new command not updating db config (#3278) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Fix] disable new command not updating ``disable new`` command didnยดt update db config if modmail was already disabled for all threads. * Update changelog --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- CHANGELOG.md | 1 + cogs/modmail.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f27da4d1c..c13d8a757d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Guild icons in embed footers and author urls now have a fixed size of 128. ([PR #3261](https://github.com/modmail-dev/modmail/pull/3261)) - Discord.py internal logging is now enabled by default. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) - The confirm-thread-creation dialog now uses buttons instead of reactions. ([PR #3273](https://github.com/modmail-dev/Modmail/pull/3273)) +- `?disable all` no longer overrides `?disable new`. ([PR #3278](https://github.com/modmail-dev/Modmail/pull/3278)) ### Internal - Renamed `Bot.log_file_name` to `Bot.log_file_path`. Log files are now created at `temp/logs/modmail.log`. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) diff --git a/cogs/modmail.py b/cogs/modmail.py index 33086116c5..445015e4de 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -2152,7 +2152,7 @@ async def disable_new(self, ctx): description="Modmail will not create any new threads.", color=self.bot.main_color, ) - if self.bot.config["dm_disabled"] < DMDisabled.NEW_THREADS: + if self.bot.config["dm_disabled"] != DMDisabled.NEW_THREADS: self.bot.config["dm_disabled"] = DMDisabled.NEW_THREADS await self.bot.config.update() From f405aedf4af009ffa9f5502aa13c99d86e48e506 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sat, 15 Jul 2023 05:11:21 -0700 Subject: [PATCH 189/225] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c13d8a757d..158eb63a91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Discord.py internal logging is now enabled by default. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) - The confirm-thread-creation dialog now uses buttons instead of reactions. ([PR #3273](https://github.com/modmail-dev/Modmail/pull/3273)) - `?disable all` no longer overrides `?disable new`. ([PR #3278](https://github.com/modmail-dev/Modmail/pull/3278)) +- Dropped root privileges for Modmail running under Docker. ([PR #3284](https://github.com/modmail-dev/Modmail/pull/3284)) ### Internal - Renamed `Bot.log_file_name` to `Bot.log_file_path`. Log files are now created at `temp/logs/modmail.log`. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) From d891ad18ca0983f344a8c7da083c559e9bd96112 Mon Sep 17 00:00:00 2001 From: Stephen <48072084+StephenDaDev@users.noreply.github.com> Date: Sat, 15 Jul 2023 08:12:30 -0400 Subject: [PATCH 190/225] Remove Heroku Reference from Debug Command (#3292) * Very few users are still using Heroku for hosting, so this comment could cause confusion. * Fix mistake --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- cogs/utility.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cogs/utility.py b/cogs/utility.py index 5386a86770..d0ecbeda22 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -410,7 +410,7 @@ async def debug(self, ctx): title="Debug Logs:", description="You don't have any logs at the moment.", ) - embed.set_footer(text="Go to Heroku to see your logs.") + embed.set_footer(text="Go to your console to see your logs.") return await ctx.send(embed=embed) messages = [] @@ -472,7 +472,7 @@ async def debug_hastebin(self, ctx): color=self.bot.main_color, description="Something's wrong. We're unable to upload your logs to hastebin.", ) - embed.set_footer(text="Go to Heroku to see your logs.") + embed.set_footer(text="Go to your console to see your logs.") await ctx.send(embed=embed) @debug.command(name="clear", aliases=["wipe"]) From 5170035df47e5f5571d94f1cb3f2175f1e70db62 Mon Sep 17 00:00:00 2001 From: Martin <box152535@gmail.com> Date: Sat, 15 Jul 2023 14:22:21 +0200 Subject: [PATCH 191/225] Added Autoreact plugin (#3285) * Added Autoreact plugin * Update changelog * black format (from a different pr's mistake) --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- CHANGELOG.md | 3 +-- cogs/plugins.py | 2 +- plugins/registry.json | 9 +++++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75553acc79..9830415b10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196)) - `REGISTRY_PLUGINS_ONLY`, environment variable, when set, restricts to only allow adding registry plugins. ([PR #3247](https://github.com/modmail-dev/modmail/pull/3247)) - `DISCORD_LOG_LEVEL` environment variable to set the log level of discord.py. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) +- New registry plugin: [`autoreact`](https://github.com/martinbndr/kyb3r-modmail-plugins/tree/master/autoreact). ### Changed - Repo moved to https://github.com/modmail-dev/modmail. @@ -32,8 +33,6 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Internal - Renamed `Bot.log_file_name` to `Bot.log_file_path`. Log files are now created at `temp/logs/modmail.log`. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) - -### Internal - `ConfigManager.get` no longer accepts two positional arguments: the `convert` argument is now keyword-only. # v4.0.2 diff --git a/cogs/plugins.py b/cogs/plugins.py index 6922a1c79c..6bae7738c6 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -316,7 +316,7 @@ async def parse_user_input(self, ctx, plugin_name, check_version=False): if self.bot.config.get("registry_plugins_only"): embed = discord.Embed( description="This plugin is not in the registry. To install this plugin, " - "you must set `REGISTRY_PLUGINS_ONLY=no` or remove this key in your .env file.", + "you must set `REGISTRY_PLUGINS_ONLY=no` or remove this key in your .env file.", color=self.bot.error_color, ) await ctx.send(embed=embed) diff --git a/plugins/registry.json b/plugins/registry.json index fe175ea58a..be138a30b2 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -17,6 +17,15 @@ "icon_url": "https://github.com/Jerrie-Aries.png", "thumbnail_url": "https://raw.githubusercontent.com/Jerrie-Aries/modmail-plugins/master/.static/announcement.jpg" }, + "autoreact": { + "repository": "martinbndr/kyb3r-modmail-plugins", + "branch": "master", + "description": "Automatically reacts with emojis in certain channels.", + "bot_version": "4.0.0", + "title": "Autoreact", + "icon_url": "https://raw.githubusercontent.com/martinbndr/kyb3r-modmail-plugins/master/autoreact/logo.png", + "thumbnail_url": "https://raw.githubusercontent.com/martinbndr/kyb3r-modmail-plugins/master/autoreact/logo.png" + }, "giveaway": { "repository": "Jerrie-Aries/modmail-plugins", "branch": "master", From 2b667102e95354fbdf07f88c3c88e95d802be0b7 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 17 Jul 2023 15:55:37 -0700 Subject: [PATCH 192/225] Fix #3291: Resolve code scanning alert for URL sanitization --- core/utils.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/core/utils.py b/core/utils.py index 0e9f090d12..60a1d654fd 100644 --- a/core/utils.py +++ b/core/utils.py @@ -147,13 +147,17 @@ def is_image_url(url: str, **kwargs) -> str: bool Whether the URL is a valid image URL. """ - if url.startswith("https://gyazo.com") or url.startswith("http://gyazo.com"): - # gyazo support - url = re.sub( - r"(http[s]?:\/\/)((?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)", - r"\1i.\2.png", - url, - ) + try: + result = parse.urlparse(url) + if result.netloc == 'gyazo.com' and result.scheme in ['http', 'https']: + # gyazo support + url = re.sub( + r"(https?://)((?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|%[0-9a-fA-F][0-9a-fA-F])+)", + r"\1i.\2.png", + url, + ) + except ValueError: + pass return parse_image_url(url, **kwargs) From f0c469ed1905ade9492f31dcd80e344de04f023b Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 17 Jul 2023 16:24:02 -0700 Subject: [PATCH 193/225] Implement #3187: Enhance bot join/leave logs across servers --- bot.py | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/bot.py b/bot.py index 45530a908f..5c8edd0843 100644 --- a/bot.py +++ b/bot.py @@ -48,7 +48,7 @@ ) from core.thread import ThreadManager from core.time import human_timedelta -from core.utils import extract_block_timestamp, normalize_alias, parse_alias, truncate, tryint +from core.utils import extract_block_timestamp, normalize_alias, parse_alias, truncate, tryint, human_join logger = getLogger(__name__) @@ -1380,28 +1380,44 @@ async def on_guild_channel_delete(self, channel): await thread.close(closer=mod, silent=True, delete_channel=False) async def on_member_remove(self, member): - if member.guild != self.guild: - return thread = await self.threads.find(recipient=member) if thread: - if self.config["close_on_leave"]: + if member.guild == self.guild and self.config["close_on_leave"]: await thread.close( closer=member.guild.me, message=self.config["close_on_leave_reason"], silent=True, ) else: - embed = discord.Embed( - description=self.config["close_on_leave_reason"], color=self.error_color - ) + if len(self.guilds) > 1: + guild_left = member.guild + remaining_guilds = member.mutual_guilds + + if remaining_guilds: + remaining_guild_names = [guild.name for guild in remaining_guilds] + leave_message = ( + f"The recipient has left {guild_left}. " + f"They are still in {human_join(remaining_guild_names, final='and')}." + ) + else: + leave_message = ( + f"The recipient has left {guild_left}. We no longer share any mutual servers." + ) + else: + leave_message = "The recipient has left the server." + + embed = discord.Embed(description=leave_message, color=self.error_color) await thread.channel.send(embed=embed) async def on_member_join(self, member): - if member.guild != self.guild: - return thread = await self.threads.find(recipient=member) if thread: - embed = discord.Embed(description="The recipient has joined the server.", color=self.mod_color) + if len(self.guilds) > 1: + guild_joined = member.guild + join_message = f"The recipient has joined {guild_joined}." + else: + join_message = "The recipient has joined the server." + embed = discord.Embed(description=join_message, color=self.mod_color) await thread.channel.send(embed=embed) async def on_message_delete(self, message): From 7508d524a5e3c6d2df3eabad5ec7d551a5edd4e6 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:23:32 -0700 Subject: [PATCH 194/225] Update readme with new documentation links, python version, and removed obsolete installion steps --- README.md | 119 +++++++++++++----------------------------------------- 1 file changed, 28 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index 062bf6d8a4..319a9742cf 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ </a> <a href="https://www.python.org/downloads/"> - <img src="https://img.shields.io/badge/Made%20With-Python%203.8-blue.svg?style=for-the-badge&logo=Python" alt="Made with Python 3.8"> + <img src="https://img.shields.io/badge/Made%20With-Python%203.10-blue.svg?style=for-the-badge&logo=Python" alt="Made with Python 3.10"> </a> <a href="https://github.com/ambv/black"> @@ -50,11 +50,13 @@ Modmail is similar to Reddit's Modmail, both in functionality and purpose. It se This bot is free for everyone and always will be. If you like this project and would like to show your appreciation, you can support us on **[Patreon](https://www.patreon.com/kyber)**, cool benefits included! +For up-to-date setup instructions, please visit our [**documentation**](https://docs.modmail.dev/installation) page. + ## How does it work? When a member sends a direct message to the bot, Modmail will create a channel or "thread" into a designated category. All further DM messages will automatically relay to that channel; any available staff can respond within the channel. -Our Logviewer will save the threads so you can view previous threads through their corresponding log link. Here is an [**example**](https://logs.modmail.dev/example). +Our Logviewer will save the threads so you can view previous threads through their corresponding log link. ~~Here is an [**example**](https://logs.modmail.dev/example)~~ (demo not available at the moment). ## Features @@ -67,7 +69,7 @@ Our Logviewer will save the threads so you can view previous threads through the * Minimum length for members to be in the guild before allowed to contact Modmail (`guild_age`). * **Advanced Logging Functionality:** - * When you close a thread, Modmail will generate a [log link](https://logs.modmail.dev/example) and post it to your log channel. + * When you close a thread, Modmail will generate a log link and post it to your log channel. * Native Discord dark-mode feel. * Markdown/formatting support. * Login via Discord to protect your logs ([premium Patreon feature](https://patreon.com/kyber)). @@ -84,88 +86,34 @@ This list is ever-growing thanks to active development and our exceptional contr ## Installation -Q: Where can I find the Modmail bot invite link? +There are a number of options for hosting your very own dedicated Modmail bot. + +Visit our [**documentation**](https://docs.modmail.dev/installation) page for detailed guidance on how to deploy your Modmail bot. -A: Unfortunately, due to how this bot functions, it cannot be invited. The lack of an invite link is to ensure an individuality to your server and grant you full control over your bot and data. Nonetheless, you can quickly obtain a free copy of Modmail for your server by following one of the methods listed below (roughly takes 15 minutes of your time). +### Patreon Hosting -There are a few options for hosting your very own dedicated Modmail bot. +If you don't want the trouble of renting and configuring your server to host Modmail, we got a solution for you! We offer hosting and maintenance of your own, private Modmail bot (including a Logviewer) through [**Patreon**](https://patreon.com/kyber). -1. Patreon hosting -2. Local hosting (VPS, Dedicated Server, RPi, your computer, etc.) -3. PaaS (we provide a guide for Heroku) +## FAQ -### Patreon Hosting +**Q: Where can I find the Modmail bot invite link?** + +**A:** Unfortunately, due to how this bot functions, it cannot be invited. The lack of an invite link is to ensure an individuality to your server and grant you full control over your bot and data. Nonetheless, you can quickly obtain a free copy of Modmail for your server by following our [**documentation**](https://docs.modmail.dev/installation) steps or subscribe to [**Patreon**](https://patreon.com/kyber). + +**Q: Where can I find out more info about Modmail?** + +**A:** You can find more info about Modmail on our [**documentation**](https://docs.modmail.dev) page. If you run into any problems, join our [Modmail Discord Server](https://discord.gg/cnUpwrnpYb) for help and support. + +## Plugins + +Modmail supports the use of third-party plugins to extend or add functionalities to the bot. +Plugins allow niche features as well as anything else outside of the scope of the core functionality of Modmail. + +You can find a list of third-party plugins using the `?plugins registry` command or visit the [Unofficial List of Plugins](https://github.com/modmail-dev/modmail/wiki/Unofficial-List-of-Plugins) for a list of plugins contributed by the community. -If you don't want the trouble of renting and configuring your server to host Modmail, we got a solution for you! We offer hosting and maintenance of your own, private Modmail bot (including a Logviewer) through [**Patreon**](https://patreon.com/kyber). Join our [Modmail Discord Server](https://discord.gg/cnUpwrnpYb) for more info! - -### Local hosting (General Guide) - -Modmail can be hosted on any modern hardware, including your PC. For stability and reliability, we suggest purchasing a cloud server (VPS) for under $10/mo. If you need recommendations on choosing a VPS, join our [Discord server](https://discord.gg/cnUpwrnpYb), and we'll send you a list of non-affiliated hosting providers. Alternatively, we can host Modmail for you when you're subscribed to our [Patreon](https://patreon.com/kyber). - -This guide assumes you've downloaded [`Python 3.10`](https://www.python.org/downloads/release/python-376/) and added python and pip to PATH. - -1. Clone this repo - ```console - $ git clone https://github.com/modmail-dev/modmail - $ cd modmail - ``` -2. Create a Discord bot account, grant the necessary intents, and invite the bot ([guide](https://github.com/modmail-dev/modmail/wiki/Installation#2-discord-bot-account)) -3. Create a free MongoDB database ([guide](https://github.com/modmail-dev/modmail/wiki/Installation-(cont.)#3-create-a-database), follow it carefully!) -4. Rename the file `.env.example` to `.env` and fill it with appropriate values - - If you can't find `.env.example` because it's hidden, create a new text file named `.env`, then copy the contents of [this file](https://raw.githubusercontent.com/modmail-dev/modmail/master/.env.example) and replace the placeholders with their values - - If you're on Windows and cannot save the file as `.env`, save it as `.env.` instead (this only applies to Windows!) - - If you do not have a Logviewer yet, leave the `LOG_URL` field as-is -5. Update pip, install pipenv, and install dependencies using pipenv - ```console - $ pip install -U pip - $ pip install pipenv - $ pipenv install - ``` -6. Start the bot - ```console - $ pipenv run bot - ``` -7. Set up the Logviewer, see the [Logviewer installation guide](https://github.com/modmail-dev/logviewer) - -### Local Hosting (Docker) - -We provide support for Docker to simplify the deployment of Modmail and Logviewer. -We assume you already have Docker and Docker Compose Plugin installed, if not, see [here](https://docs.docker.com/get-docker/). - -1. Create a Discord bot account, grant the necessary intents, and invite the bot ([guide](https://github.com/modmail-dev/modmail/wiki/Installation#2-discord-bot-account)) -2. Create a file named `.env`, then copy the contents of [this file](https://raw.githubusercontent.com/modmail-dev/modmail/master/.env.example) and replace the placeholders with their values -3. Create a file named `docker-compose.yml`, then copy the contents of [this file](https://raw.githubusercontent.com/modmail-dev/modmail/master/docker-compose.yml), do not change anything! -4. Start the bot - ```console - $ docker compose up -d - ``` - - For older Docker versions, you may need to run `docker-compose up -d` instead -5. View the status of your bot, using `docker ps` and `docker logs [container-id]` - -Our Docker images are hosted on [GitHub Container Registry](ghcr.io), you can build your own image if you wish: -```console -$ docker build --tag=modmail:master . -``` - -Then simply remove `ghcr.io/modmail-dev/` from the `docker-compose.yml` file. - -### Local Hosting (OS-Specific) - -This guide is a WIP. Join our [Discord server](https://discord.gg/cnUpwrnpYb) for more info. - -### Platform as a Service (PaaS) - -You can host this bot on Heroku (no longer free). - -Installation via Heroku is possible with your web browser alone. -The [**installation guide**](https://github.com/modmail-dev/modmail/wiki/Installation) (which includes a video tutorial!) will guide you through the entire installation process. If you run into any problems, join our [Modmail Discord Server](https://discord.gg/cnUpwrnpYb) for help and support. - -When using Heroku, you can configure automatic updates: - - Login to [GitHub](https://github.com/) and verify your account. - - [Fork the repo](https://github.com/modmail-dev/modmail/fork). - - Install the [Pull app](https://github.com/apps/pull) for your fork. - - Then go to the Deploy tab in your [Heroku account](https://dashboard.heroku.com/apps) of your bot app, select GitHub and connect your fork (usually by typing "Modmail"). - - Turn on auto-deploy for the `master` branch. +To develop your own, check out the [plugins documentation](https://github.com/modmail-dev/modmail/wiki/Plugins). + +Plugins requests and support are available in our [Modmail Support Server](https://discord.gg/cnUpwrnpYb). ## Sponsors @@ -208,17 +156,6 @@ Discord Advice Center: Become a sponsor on [Patreon](https://patreon.com/kyber). -## Plugins - -Modmail supports the use of third-party plugins to extend or add functionalities to the bot. -Plugins allow niche features as well as anything else outside of the scope of the core functionality of Modmail. - -You can find a list of third-party plugins using the `?plugins registry` command or visit the [Unofficial List of Plugins](https://github.com/modmail-dev/modmail/wiki/Unofficial-List-of-Plugins) for a list of plugins contributed by the community. - -To develop your own, check out the [plugins documentation](https://github.com/modmail-dev/modmail/wiki/Plugins). - -Plugins requests and support are available in our [Modmail Support Server](https://discord.gg/cnUpwrnpYb). - ## Contributing Contributions to Modmail are always welcome, whether it be improvements to the documentation or new functionality, please feel free to make the change. Check out our [contributing guidelines](https://github.com/modmail-dev/modmail/blob/master/.github/CONTRIBUTING.md) before you get started. From 6d61cf29ff0d9e8a3b984eb44a6337402246bff0 Mon Sep 17 00:00:00 2001 From: Amy <git@amyerskine.me> Date: Sun, 19 Nov 2023 05:45:13 +0000 Subject: [PATCH 195/225] Add JSON logging support (#3305) * Add JSON logging support This adds support for JSON logging, along with the relevant options required. This does not change the default log behaviour, so should be backwards compatible. It is opt in via the LOG_FORMAT option, which can be 'json' to use the new logger, or anything else to fallback to the old behaviour. This is implemented in terms of a custom formatter, which is optionally applied to the stdout stream. The debug stream is unaffected by this. * Allow JSON to be selected when creating handlers * Allow different formats to be selected for streams/files * Remove old / unused code * Add new config opts to helpfile * Formatting, basic typing and reorder for consistency in project. --------- Co-authored-by: Jerrie-Aries <hidzrie@gmail.com> Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- core/config.py | 2 + core/config_help.json | 18 +++++++ core/models.py | 110 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 125 insertions(+), 5 deletions(-) diff --git a/core/config.py b/core/config.py index 527b2dc19f..a9e16a0df1 100644 --- a/core/config.py +++ b/core/config.py @@ -178,6 +178,8 @@ class ConfigManager: "disable_updates": False, # Logging "log_level": "INFO", + "stream_log_format": "plain", + "file_log_format": "plain", "discord_log_level": "INFO", # data collection "data_collection": True, diff --git a/core/config_help.json b/core/config_help.json index f909d27821..501c265827 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -1129,6 +1129,24 @@ "This configuration can only to be set through `.env` file or environment (config) variables." ] }, + "stream_log_format": { + "default": "plain", + "description": "The logging format when through a stream, can be 'plain' or 'json'", + "examples": [ + ], + "notes": [ + "This configuration can only to be set through `.env` file or environment (config) variables." + ] + }, + "file_log_format": { + "default": "plain", + "description": "The logging format when logging to a file, can be 'plain' or 'json'", + "examples": [ + ], + "notes": [ + "This configuration can only to be set through `.env` file or environment (config) variables." + ] + }, "discord_log_level": { "default": "INFO", "description": "The `discord.py` library logging level for logging to stdout.", diff --git a/core/models.py b/core/models.py index 29f6af71bb..2a397541c1 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,4 @@ +import json import logging import os import re @@ -9,7 +10,7 @@ from logging import FileHandler, StreamHandler, Handler from logging.handlers import RotatingFileHandler from string import Formatter -from typing import Optional +from typing import Dict, Optional import discord from discord.ext import commands @@ -74,6 +75,71 @@ def line(self, level="info"): ) +class JsonFormatter(logging.Formatter): + """ + Formatter that outputs JSON strings after parsing the LogRecord. + + Parameters + ---------- + fmt_dict : Optional[Dict[str, str]] + {key: logging format attribute} pairs. Defaults to {"message": "message"}. + time_format: str + time.strftime() format string. Default: "%Y-%m-%dT%H:%M:%S" + msec_format: str + Microsecond formatting. Appended at the end. Default: "%s.%03dZ" + """ + + def __init__( + self, + fmt_dict: Optional[Dict[str, str]] = None, + time_format: str = "%Y-%m-%dT%H:%M:%S", + msec_format: str = "%s.%03dZ", + ): + self.fmt_dict: Dict[str, str] = fmt_dict if fmt_dict is not None else {"message": "message"} + self.default_time_format: str = time_format + self.default_msec_format: str = msec_format + self.datefmt: Optional[str] = None + + def usesTime(self) -> bool: + """ + Overwritten to look for the attribute in the format dict values instead of the fmt string. + """ + return "asctime" in self.fmt_dict.values() + + def formatMessage(self, record) -> Dict[str, str]: + """ + Overwritten to return a dictionary of the relevant LogRecord attributes instead of a string. + KeyError is raised if an unknown attribute is provided in the fmt_dict. + """ + return {fmt_key: record.__dict__[fmt_val] for fmt_key, fmt_val in self.fmt_dict.items()} + + def format(self, record) -> str: + """ + Mostly the same as the parent's class method, the difference being that a dict is manipulated and dumped as JSON + instead of a string. + """ + record.message = record.getMessage() + + if self.usesTime(): + record.asctime = self.formatTime(record, self.datefmt) + + message_dict = self.formatMessage(record) + + if record.exc_info: + # Cache the traceback text to avoid converting it multiple times + # (it's constant anyway) + if not record.exc_text: + record.exc_text = self.formatException(record.exc_info) + + if record.exc_text: + message_dict["exc_info"] = record.exc_text + + if record.stack_info: + message_dict["stack_info"] = self.formatStack(record.stack_info) + + return json.dumps(message_dict, default=str) + + class FileFormatter(logging.Formatter): ansi_escape = re.compile(r"\x1B\[[0-?]*[ -/]*[@-~]") @@ -85,11 +151,25 @@ def format(self, record): log_stream_formatter = logging.Formatter( "%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s", datefmt="%m/%d/%y %H:%M:%S" ) + log_file_formatter = FileFormatter( "%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) +json_formatter = JsonFormatter( + { + "level": "levelname", + "message": "message", + "loggerName": "name", + "processName": "processName", + "processID": "process", + "threadName": "threadName", + "threadID": "thread", + "timestamp": "asctime", + } +) + def create_log_handler( filename: Optional[str] = None, @@ -98,6 +178,7 @@ def create_log_handler( level: int = logging.DEBUG, mode: str = "a+", encoding: str = "utf-8", + format: str = "plain", maxBytes: int = 28000000, backupCount: int = 1, **kwargs, @@ -124,6 +205,9 @@ def create_log_handler( encoding : str If this keyword argument is specified along with filename, its value is used when the `FileHandler` is created, and thus used when opening the output file. Defaults to 'utf-8'. + format : str + The format to output with, can either be 'json' or 'plain'. Will apply to whichever handler is created, + based on other conditional logic. maxBytes : int The max file size before the rollover occurs. Defaults to 28000000 (28MB). Rollover occurs whenever the current log file is nearly `maxBytes` in length; but if either of `maxBytes` or `backupCount` is zero, @@ -141,23 +225,28 @@ def create_log_handler( if filename is None: handler = StreamHandler(stream=sys.stdout, **kwargs) - handler.setFormatter(log_stream_formatter) + formatter = log_stream_formatter elif not rotating: handler = FileHandler(filename, mode=mode, encoding=encoding, **kwargs) - handler.setFormatter(log_file_formatter) + formatter = log_file_formatter else: handler = RotatingFileHandler( filename, mode=mode, encoding=encoding, maxBytes=maxBytes, backupCount=backupCount, **kwargs ) - handler.setFormatter(log_file_formatter) + formatter = log_file_formatter + + if format == "json": + formatter = json_formatter handler.setLevel(level) + handler.setFormatter(formatter) return handler logging.setLoggerClass(ModmailLogger) log_level = logging.INFO loggers = set() + ch = create_log_handler(level=log_level) ch_debug: Optional[RotatingFileHandler] = None @@ -173,7 +262,11 @@ def getLogger(name=None) -> ModmailLogger: def configure_logging(bot) -> None: - global ch_debug, log_level + global ch_debug, log_level, ch + + stream_log_format, file_log_format = bot.config["stream_log_format"], bot.config["file_log_format"] + if stream_log_format == "json": + ch.setFormatter(json_formatter) logger = getLogger(__name__) level_text = bot.config["log_level"].upper() @@ -198,8 +291,15 @@ def configure_logging(bot) -> None: logger.info("Log file: %s", bot.log_file_path) ch_debug = create_log_handler(bot.log_file_path, rotating=True) + + if file_log_format == "json": + ch_debug.setFormatter(json_formatter) + ch.setLevel(log_level) + logger.info("Stream log format: %s", stream_log_format) + logger.info("File log format: %s", file_log_format) + for log in loggers: log.setLevel(log_level) log.addHandler(ch_debug) From 5c710596c870121d2df864ceec8d86f0333fbb49 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sat, 18 Nov 2023 21:47:34 -0800 Subject: [PATCH 196/225] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9830415b10..0b3a61943a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `REGISTRY_PLUGINS_ONLY`, environment variable, when set, restricts to only allow adding registry plugins. ([PR #3247](https://github.com/modmail-dev/modmail/pull/3247)) - `DISCORD_LOG_LEVEL` environment variable to set the log level of discord.py. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) - New registry plugin: [`autoreact`](https://github.com/martinbndr/kyb3r-modmail-plugins/tree/master/autoreact). +- `STREAM_LOG_FORMAT` and `FILE_LOG_FORMAT` for settings the log format of the stream and file handlers respectively. Possible options are `json` and `plain` (default). ([PR #3305](https://github.com/modmail-dev/Modmail/pull/3305)) ### Changed - Repo moved to https://github.com/modmail-dev/modmail. From ae99060a3fe4a0afcd2d2fa35af85e8fce5b8aaa Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Sun, 19 Nov 2023 16:38:42 +0800 Subject: [PATCH 197/225] Fix rate limit issue on raw reaction add/remove events. (#3306) * Fix rate limit issue on raw reaction add/remove events. * Pasd message object to `find_linked_messages` since it is already fetched. --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- bot.py | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/bot.py b/bot.py index 45530a908f..3701d826ea 100644 --- a/bot.py +++ b/bot.py @@ -1222,25 +1222,36 @@ async def handle_reaction_events(self, payload): return channel = self.get_channel(payload.channel_id) - if not channel: # dm channel not in internal cache - _thread = await self.threads.find(recipient=user) - if not _thread: + thread = None + # dm channel not in internal cache + if not channel: + thread = await self.threads.find(recipient=user) + if not thread: + return + channel = await thread.recipient.create_dm() + if channel.id != payload.channel_id: + return + + from_dm = isinstance(channel, discord.DMChannel) + from_txt = isinstance(channel, discord.TextChannel) + if not from_dm and not from_txt: + return + + if not thread: + params = {"recipient": user} if from_dm else {"channel": channel} + thread = await self.threads.find(**params) + if not thread: return - channel = await _thread.recipient.create_dm() + # thread must exist before doing this API call try: message = await channel.fetch_message(payload.message_id) except (discord.NotFound, discord.Forbidden): return reaction = payload.emoji - close_emoji = await self.convert_emoji(self.config["close_emoji"]) - - if isinstance(channel, discord.DMChannel): - thread = await self.threads.find(recipient=user) - if not thread: - return + if from_dm: if ( payload.event_type == "REACTION_ADD" and message.embeds @@ -1248,7 +1259,7 @@ async def handle_reaction_events(self, payload): and self.config.get("recipient_thread_close") ): ts = message.embeds[0].timestamp - if thread and ts == thread.channel.created_at: + if ts == thread.channel.created_at: # the reacted message is the corresponding thread creation embed # closing thread return await thread.close(closer=user) @@ -1268,11 +1279,10 @@ async def handle_reaction_events(self, payload): logger.warning("Failed to find linked message for reactions: %s", e) return else: - thread = await self.threads.find(channel=channel) - if not thread: - return try: - _, *linked_messages = await thread.find_linked_messages(message.id, either_direction=True) + _, *linked_messages = await thread.find_linked_messages( + message1=message, either_direction=True + ) except ValueError as e: logger.warning("Failed to find linked message for reactions: %s", e) return From a8d7c26d8cfd863c13b4862ffae1cb998a13fda8 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 19 Nov 2023 02:21:42 -0800 Subject: [PATCH 198/225] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b3a61943a..76a929b178 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Fixed a syntactic error in the close message when a thread is closed after a certain duration. ([PR #3233](https://github.com/modmail-dev/Modmail/pull/3233)) - Removed an extra space in the help command title when the command has no parameters. ([PR #3271](https://github.com/modmail-dev/Modmail/pull/3271)) - Corrected some incorrect config help descriptions. ([PR #3277](https://github.com/modmail-dev/Modmail/pull/3277)) +- Rate limit issue when fetch the messages due to reaction linking. ([PR #3306](https://github.com/modmail-dev/Modmail/pull/3306)) ### Added - `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196)) From 54f7b1cd916db6a8490544748318e007def52699 Mon Sep 17 00:00:00 2001 From: Atharv Agarwal <49218334+Atharv-Agarwal@users.noreply.github.com> Date: Mon, 20 Nov 2023 02:20:42 +0530 Subject: [PATCH 199/225] Add config to manage how long logs are stored (#3257) * Add config to change how long logs are stored * Optimize deleting logs * Update core/config_help.json Co-authored-by: khakers <22665282+khakers@users.noreply.github.com> Signed-off-by: Cordila <49218334+Cordila@users.noreply.github.com> * Testing changes * Update core/config_help.json (Fix copy paste) Co-authored-by: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Signed-off-by: Cordila <49218334+Cordila@users.noreply.github.com> --------- Signed-off-by: Cordila <49218334+Cordila@users.noreply.github.com> Co-authored-by: Cordila <49218334+Cordila@users.noreply.github.com> Co-authored-by: khakers <22665282+khakers@users.noreply.github.com> Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> Co-authored-by: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> --- bot.py | 18 ++++++++++++++---- cogs/plugins.py | 2 -- cogs/utility.py | 1 - core/config.py | 4 ++-- core/config_help.json | 11 +++++++++++ core/models.py | 1 - core/thread.py | 2 -- 7 files changed, 27 insertions(+), 12 deletions(-) diff --git a/bot.py b/bot.py index 3701d826ea..5e8854faa8 100644 --- a/bot.py +++ b/bot.py @@ -12,7 +12,7 @@ import sys import platform import typing -from datetime import datetime, timezone +from datetime import datetime, timezone, timedelta from subprocess import PIPE from types import SimpleNamespace @@ -616,6 +616,7 @@ async def on_ready(self): self.post_metadata.start() self.autoupdate.start() + self.log_expiry.start() self._started = True async def convert_emoji(self, name: str) -> str: @@ -640,7 +641,6 @@ async def get_or_fetch_user(self, id: int) -> discord.User: return self.get_user(id) or await self.fetch_user(id) async def retrieve_emoji(self) -> typing.Tuple[str, str]: - sent_emoji = self.config["sent_emoji"] blocked_emoji = self.config["blocked_emoji"] @@ -714,7 +714,6 @@ def check_manual_blocked_roles(self, author: discord.Member) -> bool: if isinstance(author, discord.Member): for r in author.roles: if str(r.id) in self.blocked_roles: - blocked_reason = self.blocked_roles.get(str(r.id)) or "" try: @@ -773,7 +772,6 @@ async def is_blocked( channel: discord.TextChannel = None, send_message: bool = False, ) -> bool: - member = self.guild.get_member(author.id) if member is None: # try to find in other guilds @@ -1707,6 +1705,18 @@ async def before_autoupdate(self): self.autoupdate.cancel() return + @tasks.loop(hours=1, reconnect=False) + async def log_expiry(self): + log_expire_after = self.config.get("log_expiration") + if log_expire_after == isodate.Duration(): + return self.log_expiry.stop() + + now = discord.utils.utcnow() + expiration_datetime = now - log_expire_after + expired_logs = await self.db.logs.delete_many({"closed_at": {"$lte": str(expiration_datetime)}}) + + logger.info(f"Deleted {expired_logs.deleted_count} expired logs.") + def format_channel_name(self, author, exclude_channel=None, force_null=False): """Sanitises a username for use with text channel names diff --git a/cogs/plugins.py b/cogs/plugins.py index 6bae7738c6..59a2c9d24d 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -276,7 +276,6 @@ async def unload_plugin(self, plugin: Plugin) -> None: del sys.modules[module] async def parse_user_input(self, ctx, plugin_name, check_version=False): - if not self.bot.config["enable_plugins"]: embed = discord.Embed( description="Plugins are disabled, enable them by setting `ENABLE_PLUGINS=true`", @@ -399,7 +398,6 @@ async def plugins_add(self, ctx, *, plugin_name: str): await self.bot.config.update() if self.bot.config.get("enable_plugins"): - invalidate_caches() try: diff --git a/cogs/utility.py b/cogs/utility.py index d0ecbeda22..749cf3e160 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -584,7 +584,6 @@ async def status(self, ctx, *, status_type: str.lower): return await ctx.send(embed=embed) async def set_presence(self, *, status=None, activity_type=None, activity_message=None): - if status is None: status = self.bot.config.get("status") diff --git a/core/config.py b/core/config.py index a9e16a0df1..5c6b0dd09d 100644 --- a/core/config.py +++ b/core/config.py @@ -21,7 +21,6 @@ class ConfigManager: - public_keys = { # activity "twitch_url": "https://www.twitch.tv/discordmodmail/", @@ -37,6 +36,7 @@ class ConfigManager: "account_age": isodate.Duration(), "guild_age": isodate.Duration(), "thread_cooldown": isodate.Duration(), + "log_expiration": isodate.Duration(), "reply_without_command": False, "anon_reply_without_command": False, "plain_reply_without_command": False, @@ -187,7 +187,7 @@ class ConfigManager: colors = {"mod_color", "recipient_color", "main_color", "error_color"} - time_deltas = {"account_age", "guild_age", "thread_auto_close", "thread_cooldown"} + time_deltas = {"account_age", "guild_age", "thread_auto_close", "thread_cooldown", "log_expiration"} booleans = { "use_user_id_channel_name", diff --git a/core/config_help.json b/core/config_help.json index 501c265827..d301763fe4 100644 --- a/core/config_help.json +++ b/core/config_help.json @@ -373,6 +373,17 @@ "To disable thread cooldown, do `{prefix}config del thread_cooldown`." ] }, + "log_expiration": { + "default": "Never", + "description": "The duration closed threads will be stored within the database before deletion. Logs that have been closed for longer than this duration will be deleted automatically.", + "examples": [ + "`{prefix}config set log_expiration P12DT3H` (stands for 12 days and 3 hours in [ISO-8601 Duration Format](https://en.wikipedia.org/wiki/ISO_8601#Durations))", + "`{prefix}config set log_expiration 3 days and 5 hours` (accepted readable time)" + ], + "notes": [ + "To disable log expiration, do `{prefix}config del log_expiration`." + ] + }, "thread_cancelled": { "default": "\"Cancelled\"", "description": "This is the message to display when a thread times out and creation is cancelled.", diff --git a/core/models.py b/core/models.py index 2a397541c1..611db375f0 100644 --- a/core/models.py +++ b/core/models.py @@ -394,7 +394,6 @@ async def convert(self, ctx, argument): try: return await super().convert(ctx, argument) except commands.ChannelNotFound: - if guild: categories = {c.name.casefold(): c for c in guild.categories} else: diff --git a/core/thread.py b/core/thread.py index 46be932c1a..09c5df46ee 100644 --- a/core/thread.py +++ b/core/thread.py @@ -721,7 +721,6 @@ async def delete_message( async def find_linked_message_from_dm( self, message, either_direction=False, get_thread_channel=False ) -> typing.List[discord.Message]: - joint_id = None if either_direction: joint_id = get_joint_id(message) @@ -914,7 +913,6 @@ async def send( persistent_note: bool = False, thread_creation: bool = False, ) -> None: - if not note and from_mod: self.bot.loop.create_task(self._restart_close_timer()) # Start or restart thread auto close From 2bc51e8f9eb34758e7c997d7eb6d23338867a83a Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 19 Nov 2023 12:54:53 -0800 Subject: [PATCH 200/225] Update changelog and added a note for comparing dates by string --- CHANGELOG.md | 3 ++- bot.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76a929b178..3e5d335e44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,8 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `REGISTRY_PLUGINS_ONLY`, environment variable, when set, restricts to only allow adding registry plugins. ([PR #3247](https://github.com/modmail-dev/modmail/pull/3247)) - `DISCORD_LOG_LEVEL` environment variable to set the log level of discord.py. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) - New registry plugin: [`autoreact`](https://github.com/martinbndr/kyb3r-modmail-plugins/tree/master/autoreact). -- `STREAM_LOG_FORMAT` and `FILE_LOG_FORMAT` for settings the log format of the stream and file handlers respectively. Possible options are `json` and `plain` (default). ([PR #3305](https://github.com/modmail-dev/Modmail/pull/3305)) +- `STREAM_LOG_FORMAT` and `FILE_LOG_FORMAT` environment variable to set the log format of the stream and file handlers respectively. Possible options are `json` and `plain` (default). ([PR #3305](https://github.com/modmail-dev/Modmail/pull/3305)) +- `LOG_EXPIRATION` environment variable to set the expiration time of logs. ([PR #3257](https://github.com/modmail-dev/Modmail/pull/3257)) ### Changed - Repo moved to https://github.com/modmail-dev/modmail. diff --git a/bot.py b/bot.py index 5e8854faa8..f36ecc8351 100644 --- a/bot.py +++ b/bot.py @@ -1713,6 +1713,8 @@ async def log_expiry(self): now = discord.utils.utcnow() expiration_datetime = now - log_expire_after + # WARNING: comparison is done lexicographically, not by date. + # This is fine as long as the date is in zero-padded ISO format, which it should be. expired_logs = await self.db.logs.delete_many({"closed_at": {"$lte": str(expiration_datetime)}}) logger.info(f"Deleted {expired_logs.deleted_count} expired logs.") From c6f87cdb0cffec3d88a0c75f003f95f30bd7980d Mon Sep 17 00:00:00 2001 From: Nicklaus <100449899+Nicklaus-s@users.noreply.github.com> Date: Sun, 19 Nov 2023 14:58:52 -0600 Subject: [PATCH 201/225] Add `rename` to `registry.json` (#3276) * Add `rename` to `registry.json` Signed-off-by: Nicklaus <100449899+Nicklaus-s@users.noreply.github.com> * Change icon Signed-off-by: Nicklaus <100449899+Nicklaus-s@users.noreply.github.com> --------- Signed-off-by: Nicklaus <100449899+Nicklaus-s@users.noreply.github.com> --- plugins/registry.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/registry.json b/plugins/registry.json index be138a30b2..4079001a50 100644 --- a/plugins/registry.json +++ b/plugins/registry.json @@ -124,5 +124,14 @@ "title": "Top Supporters", "icon_url": "https://i.imgur.com/Mo60CdK.png", "thumbnail_url": "https://i.imgur.com/Mo60CdK.png" + }, + "rename": { + "repository": "Nicklaus-s/modmail-plugins", + "branch": "master", + "description": "Set a thread channel name.", + "bot_version": "4.0.0", + "title": "Rename", + "icon_url": "https://i.imgur.com/A1auJ95.png", + "thumbnail_url": "https://i.imgur.com/A1auJ95.png" } } From 5b2770caf2c8277f1de50d70db1407e1b5fdbb8b Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 19 Nov 2023 13:00:23 -0800 Subject: [PATCH 202/225] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e5d335e44..1b7910bfff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,9 +22,9 @@ however, insignificant breaking changes do not guarantee a major version bump, s - `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196)) - `REGISTRY_PLUGINS_ONLY`, environment variable, when set, restricts to only allow adding registry plugins. ([PR #3247](https://github.com/modmail-dev/modmail/pull/3247)) - `DISCORD_LOG_LEVEL` environment variable to set the log level of discord.py. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) -- New registry plugin: [`autoreact`](https://github.com/martinbndr/kyb3r-modmail-plugins/tree/master/autoreact). - `STREAM_LOG_FORMAT` and `FILE_LOG_FORMAT` environment variable to set the log format of the stream and file handlers respectively. Possible options are `json` and `plain` (default). ([PR #3305](https://github.com/modmail-dev/Modmail/pull/3305)) - `LOG_EXPIRATION` environment variable to set the expiration time of logs. ([PR #3257](https://github.com/modmail-dev/Modmail/pull/3257)) +- New registry plugins: [`autoreact`](https://github.com/martinbndr/kyb3r-modmail-plugins/tree/master/autoreact) and [`rename`](https://github.com/Nicklaus-s/modmail-plugins/tree/main/rename). ### Changed - Repo moved to https://github.com/modmail-dev/modmail. From a94e7a984172801c03e9a316e93ea1a5b47df9fd Mon Sep 17 00:00:00 2001 From: Jerrie <70805800+Jerrie-Aries@users.noreply.github.com> Date: Mon, 20 Nov 2023 05:26:12 +0800 Subject: [PATCH 203/225] Fix bug with `?plugin update`. (#3295) --- cogs/plugins.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cogs/plugins.py b/cogs/plugins.py index 59a2c9d24d..d5787956f1 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -500,12 +500,12 @@ async def update_plugin(self, ctx, plugin_name): description=f"Failed to update {plugin.name}. This plugin will now be removed from your bot.", color=self.bot.error_color, ) - self.bot.config["plugins"].remove(plugin_name) - logger.debug("Failed to update %s. Removed plugin from config.", plugin_name) + self.bot.config["plugins"].remove(str(plugin)) + logger.debug("Failed to update %s. Removed plugin from config.", plugin) else: - logger.debug("Updated %s.", plugin_name) + logger.debug("Updated %s.", plugin) else: - logger.debug("Updated %s.", plugin_name) + logger.debug("Updated %s.", plugin) return await ctx.send(embed=embed) @plugins.command(name="update") From 8bd30dc90760b5e5a6581abae0a72126b092da44 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 19 Nov 2023 13:27:48 -0800 Subject: [PATCH 204/225] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b7910bfff..f79f46c491 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s - Removed an extra space in the help command title when the command has no parameters. ([PR #3271](https://github.com/modmail-dev/Modmail/pull/3271)) - Corrected some incorrect config help descriptions. ([PR #3277](https://github.com/modmail-dev/Modmail/pull/3277)) - Rate limit issue when fetch the messages due to reaction linking. ([PR #3306](https://github.com/modmail-dev/Modmail/pull/3306)) +- Update command fails when the plugin is invalid. ([PR #3295](https://github.com/modmail-dev/Modmail/pull/3295)) ### Added - `?log key <key>` to retrieve the log link and view a preview using a log key. ([PR #3196](https://github.com/modmail-dev/Modmail/pull/3196)) From 53d40e0585919eadba97e7d0abcb822d1ebcbb34 Mon Sep 17 00:00:00 2001 From: lorenzo132 <50767078+lorenzo132@users.noreply.github.com> Date: Sun, 19 Nov 2023 22:41:29 +0100 Subject: [PATCH 205/225] fix: discord invite ( new server ) (#3307) * fix: discord invite ( new server ) Signed-off-by: lorenzo132 <50767078+lorenzo132@users.noreply.github.com> * Update link Signed-off-by: Taku <45324516+Taaku18@users.noreply.github.com> --------- Signed-off-by: lorenzo132 <50767078+lorenzo132@users.noreply.github.com> Signed-off-by: Taku <45324516+Taaku18@users.noreply.github.com> Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- cogs/utility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cogs/utility.py b/cogs/utility.py index 749cf3e160..579c4a7e4e 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -352,7 +352,7 @@ async def about(self, ctx): embed.add_field( name="Want Modmail in Your Server?", value="Follow the installation guide on [GitHub](https://github.com/modmail-dev/modmail/) " - "and join our [Discord server](https://discord.gg/F34cRU8)!", + "and join our [Discord server](https://discord.gg/cnUpwrnpYb)!", inline=False, ) From ec95eb7f6b6abfb1a89c48eb8e0915313a699116 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:16:04 -0800 Subject: [PATCH 206/225] Update deps: aiohttp, colorama, emoji --- Pipfile | 6 +- Pipfile.lock | 1435 ++++++++++++++++++++++++++------------------------ bot.py | 6 +- 3 files changed, 752 insertions(+), 695 deletions(-) diff --git a/Pipfile b/Pipfile index e61e3b9288..f2590a1e2b 100644 --- a/Pipfile +++ b/Pipfile @@ -10,10 +10,10 @@ pylint = "~=2.9.3" typing-extensions = "==4.2.0" [packages] -aiohttp = "==3.8.1" -colorama = "~=0.4.5" +aiohttp = "==3.9.0" +colorama = "==0.4.6" "discord.py" = "==2.0.1" -emoji = "==1.7.0" +emoji = "==2.8.0" isodate = "~=0.6.0" motor = "==2.5.1" natural = "~=0.2.0" diff --git a/Pipfile.lock b/Pipfile.lock index e1c531856e..35808d048b 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "9d1171901e036b1f78a2e89855d564e9f559736ca076128fa27eb14ee8f917a4" + "sha256": "f28fd3a11b8f1550ba6731a0bc17740966b1fd98d10c1b004d416ca5b1dd3b84" }, "pipfile-spec": 6, "requires": {}, @@ -16,196 +16,190 @@ "default": { "aiohttp": { "hashes": [ - "sha256:01d7bdb774a9acc838e6b8f1d114f45303841b89b95984cbb7d80ea41172a9e3", - "sha256:03a6d5349c9ee8f79ab3ff3694d6ce1cfc3ced1c9d36200cb8f08ba06bd3b782", - "sha256:04d48b8ce6ab3cf2097b1855e1505181bdd05586ca275f2505514a6e274e8e75", - "sha256:0770e2806a30e744b4e21c9d73b7bee18a1cfa3c47991ee2e5a65b887c49d5cf", - "sha256:07b05cd3305e8a73112103c834e91cd27ce5b4bd07850c4b4dbd1877d3f45be7", - "sha256:086f92daf51a032d062ec5f58af5ca6a44d082c35299c96376a41cbb33034675", - "sha256:099ebd2c37ac74cce10a3527d2b49af80243e2a4fa39e7bce41617fbc35fa3c1", - "sha256:0c7ebbbde809ff4e970824b2b6cb7e4222be6b95a296e46c03cf050878fc1785", - "sha256:102e487eeb82afac440581e5d7f8f44560b36cf0bdd11abc51a46c1cd88914d4", - "sha256:11691cf4dc5b94236ccc609b70fec991234e7ef8d4c02dd0c9668d1e486f5abf", - "sha256:11a67c0d562e07067c4e86bffc1553f2cf5b664d6111c894671b2b8712f3aba5", - "sha256:12de6add4038df8f72fac606dff775791a60f113a725c960f2bab01d8b8e6b15", - "sha256:13487abd2f761d4be7c8ff9080de2671e53fff69711d46de703c310c4c9317ca", - "sha256:15b09b06dae900777833fe7fc4b4aa426556ce95847a3e8d7548e2d19e34edb8", - "sha256:1c182cb873bc91b411e184dab7a2b664d4fea2743df0e4d57402f7f3fa644bac", - "sha256:1ed0b6477896559f17b9eaeb6d38e07f7f9ffe40b9f0f9627ae8b9926ae260a8", - "sha256:28d490af82bc6b7ce53ff31337a18a10498303fe66f701ab65ef27e143c3b0ef", - "sha256:2e5d962cf7e1d426aa0e528a7e198658cdc8aa4fe87f781d039ad75dcd52c516", - "sha256:2ed076098b171573161eb146afcb9129b5ff63308960aeca4b676d9d3c35e700", - "sha256:2f2f69dca064926e79997f45b2f34e202b320fd3782f17a91941f7eb85502ee2", - "sha256:31560d268ff62143e92423ef183680b9829b1b482c011713ae941997921eebc8", - "sha256:31d1e1c0dbf19ebccbfd62eff461518dcb1e307b195e93bba60c965a4dcf1ba0", - "sha256:37951ad2f4a6df6506750a23f7cbabad24c73c65f23f72e95897bb2cecbae676", - "sha256:3af642b43ce56c24d063325dd2cf20ee012d2b9ba4c3c008755a301aaea720ad", - "sha256:44db35a9e15d6fe5c40d74952e803b1d96e964f683b5a78c3cc64eb177878155", - "sha256:473d93d4450880fe278696549f2e7aed8cd23708c3c1997981464475f32137db", - "sha256:477c3ea0ba410b2b56b7efb072c36fa91b1e6fc331761798fa3f28bb224830dd", - "sha256:4a4a4e30bf1edcad13fb0804300557aedd07a92cabc74382fdd0ba6ca2661091", - "sha256:4aed991a28ea3ce320dc8ce655875e1e00a11bdd29fe9444dd4f88c30d558602", - "sha256:51467000f3647d519272392f484126aa716f747859794ac9924a7aafa86cd411", - "sha256:55c3d1072704d27401c92339144d199d9de7b52627f724a949fc7d5fc56d8b93", - "sha256:589c72667a5febd36f1315aa6e5f56dd4aa4862df295cb51c769d16142ddd7cd", - "sha256:5bfde62d1d2641a1f5173b8c8c2d96ceb4854f54a44c23102e2ccc7e02f003ec", - "sha256:5c23b1ad869653bc818e972b7a3a79852d0e494e9ab7e1a701a3decc49c20d51", - "sha256:61bfc23df345d8c9716d03717c2ed5e27374e0fe6f659ea64edcd27b4b044cf7", - "sha256:6ae828d3a003f03ae31915c31fa684b9890ea44c9c989056fea96e3d12a9fa17", - "sha256:6c7cefb4b0640703eb1069835c02486669312bf2f12b48a748e0a7756d0de33d", - "sha256:6d69f36d445c45cda7b3b26afef2fc34ef5ac0cdc75584a87ef307ee3c8c6d00", - "sha256:6f0d5f33feb5f69ddd57a4a4bd3d56c719a141080b445cbf18f238973c5c9923", - "sha256:6f8b01295e26c68b3a1b90efb7a89029110d3a4139270b24fda961893216c440", - "sha256:713ac174a629d39b7c6a3aa757b337599798da4c1157114a314e4e391cd28e32", - "sha256:718626a174e7e467f0558954f94af117b7d4695d48eb980146016afa4b580b2e", - "sha256:7187a76598bdb895af0adbd2fb7474d7f6025d170bc0a1130242da817ce9e7d1", - "sha256:71927042ed6365a09a98a6377501af5c9f0a4d38083652bcd2281a06a5976724", - "sha256:7d08744e9bae2ca9c382581f7dce1273fe3c9bae94ff572c3626e8da5b193c6a", - "sha256:7dadf3c307b31e0e61689cbf9e06be7a867c563d5a63ce9dca578f956609abf8", - "sha256:81e3d8c34c623ca4e36c46524a3530e99c0bc95ed068fd6e9b55cb721d408fb2", - "sha256:844a9b460871ee0a0b0b68a64890dae9c415e513db0f4a7e3cab41a0f2fedf33", - "sha256:8b7ef7cbd4fec9a1e811a5de813311ed4f7ac7d93e0fda233c9b3e1428f7dd7b", - "sha256:97ef77eb6b044134c0b3a96e16abcb05ecce892965a2124c566af0fd60f717e2", - "sha256:99b5eeae8e019e7aad8af8bb314fb908dd2e028b3cdaad87ec05095394cce632", - "sha256:a25fa703a527158aaf10dafd956f7d42ac6d30ec80e9a70846253dd13e2f067b", - "sha256:a2f635ce61a89c5732537a7896b6319a8fcfa23ba09bec36e1b1ac0ab31270d2", - "sha256:a79004bb58748f31ae1cbe9fa891054baaa46fb106c2dc7af9f8e3304dc30316", - "sha256:a996d01ca39b8dfe77440f3cd600825d05841088fd6bc0144cc6c2ec14cc5f74", - "sha256:b0e20cddbd676ab8a64c774fefa0ad787cc506afd844de95da56060348021e96", - "sha256:b6613280ccedf24354406caf785db748bebbddcf31408b20c0b48cb86af76866", - "sha256:b9d00268fcb9f66fbcc7cd9fe423741d90c75ee029a1d15c09b22d23253c0a44", - "sha256:bb01ba6b0d3f6c68b89fce7305080145d4877ad3acaed424bae4d4ee75faa950", - "sha256:c2aef4703f1f2ddc6df17519885dbfa3514929149d3ff900b73f45998f2532fa", - "sha256:c34dc4958b232ef6188c4318cb7b2c2d80521c9a56c52449f8f93ab7bc2a8a1c", - "sha256:c3630c3ef435c0a7c549ba170a0633a56e92629aeed0e707fec832dee313fb7a", - "sha256:c3d6a4d0619e09dcd61021debf7059955c2004fa29f48788a3dfaf9c9901a7cd", - "sha256:d15367ce87c8e9e09b0f989bfd72dc641bcd04ba091c68cd305312d00962addd", - "sha256:d2f9b69293c33aaa53d923032fe227feac867f81682f002ce33ffae978f0a9a9", - "sha256:e999f2d0e12eea01caeecb17b653f3713d758f6dcc770417cf29ef08d3931421", - "sha256:ea302f34477fda3f85560a06d9ebdc7fa41e82420e892fc50b577e35fc6a50b2", - "sha256:eaba923151d9deea315be1f3e2b31cc39a6d1d2f682f942905951f4e40200922", - "sha256:ef9612483cb35171d51d9173647eed5d0069eaa2ee812793a75373447d487aa4", - "sha256:f5315a2eb0239185af1bddb1abf472d877fede3cc8d143c6cddad37678293237", - "sha256:fa0ffcace9b3aa34d205d8130f7873fcfefcb6a4dd3dd705b0dab69af6712642", - "sha256:fc5471e1a54de15ef71c1bc6ebe80d4dc681ea600e68bfd1cbce40427f0b7578" + "sha256:05857848da443c8c12110d99285d499b4e84d59918a21132e45c3f0804876994", + "sha256:05a183f1978802588711aed0dea31e697d760ce9055292db9dc1604daa9a8ded", + "sha256:09f23292d29135025e19e8ff4f0a68df078fe4ee013bca0105b2e803989de92d", + "sha256:11ca808f9a6b63485059f5f6e164ef7ec826483c1212a44f268b3653c91237d8", + "sha256:1736d87dad8ef46a8ec9cddd349fa9f7bd3a064c47dd6469c0d6763d3d49a4fc", + "sha256:1df43596b826022b14998f0460926ce261544fedefe0d2f653e1b20f49e96454", + "sha256:23170247ef89ffa842a02bbfdc425028574d9e010611659abeb24d890bc53bb8", + "sha256:2779f5e7c70f7b421915fd47db332c81de365678180a9f3ab404088f87ba5ff9", + "sha256:28185e36a78d247c55e9fbea2332d16aefa14c5276a582ce7a896231c6b1c208", + "sha256:2cbc14a13fb6b42d344e4f27746a4b03a2cb0c1c3c5b932b0d6ad8881aa390e3", + "sha256:2d71abc15ff7047412ef26bf812dfc8d0d1020d664617f4913df2df469f26b76", + "sha256:2d820162c8c2bdbe97d328cd4f417c955ca370027dce593345e437b2e9ffdc4d", + "sha256:317719d7f824eba55857fe0729363af58e27c066c731bc62cd97bc9c3d9c7ea4", + "sha256:35a68cd63ca6aaef5707888f17a70c36efe62b099a4e853d33dc2e9872125be8", + "sha256:3607375053df58ed6f23903aa10cf3112b1240e8c799d243bbad0f7be0666986", + "sha256:366bc870d7ac61726f32a489fbe3d1d8876e87506870be66b01aeb84389e967e", + "sha256:3abf0551874fecf95f93b58f25ef4fc9a250669a2257753f38f8f592db85ddea", + "sha256:3d7f6235c7475658acfc1769d968e07ab585c79f6ca438ddfecaa9a08006aee2", + "sha256:3dd8119752dd30dd7bca7d4bc2a92a59be6a003e4e5c2cf7e248b89751b8f4b7", + "sha256:42fe4fd9f0dfcc7be4248c162d8056f1d51a04c60e53366b0098d1267c4c9da8", + "sha256:45820ddbb276113ead8d4907a7802adb77548087ff5465d5c554f9aa3928ae7d", + "sha256:4790e44f46a4aa07b64504089def5744d3b6780468c4ec3a1a36eb7f2cae9814", + "sha256:4afa8f71dba3a5a2e1e1282a51cba7341ae76585345c43d8f0e624882b622218", + "sha256:4b777c9286b6c6a94f50ddb3a6e730deec327e9e2256cb08b5530db0f7d40fd8", + "sha256:4ee1b4152bc3190cc40ddd6a14715e3004944263ea208229ab4c297712aa3075", + "sha256:51a4cd44788ea0b5e6bb8fa704597af3a30be75503a7ed1098bc5b8ffdf6c982", + "sha256:536b01513d67d10baf6f71c72decdf492fb7433c5f2f133e9a9087379d4b6f31", + "sha256:571760ad7736b34d05597a1fd38cbc7d47f7b65deb722cb8e86fd827404d1f6b", + "sha256:5a2eb5311a37fe105aa35f62f75a078537e1a9e4e1d78c86ec9893a3c97d7a30", + "sha256:5ab16c254e2312efeb799bc3c06897f65a133b38b69682bf75d1f1ee1a9c43a9", + "sha256:65b0a70a25456d329a5e1426702dde67be0fb7a4ead718005ba2ca582d023a94", + "sha256:673343fbc0c1ac44d0d2640addc56e97a052504beacd7ade0dc5e76d3a4c16e8", + "sha256:6777a390e41e78e7c45dab43a4a0196c55c3b8c30eebe017b152939372a83253", + "sha256:6896b8416be9ada4d22cd359d7cb98955576ce863eadad5596b7cdfbf3e17c6c", + "sha256:694df243f394629bcae2d8ed94c589a181e8ba8604159e6e45e7b22e58291113", + "sha256:70e851f596c00f40a2f00a46126c95c2e04e146015af05a9da3e4867cfc55911", + "sha256:7276fe0017664414fdc3618fca411630405f1aaf0cc3be69def650eb50441787", + "sha256:76a86a9989ebf82ee61e06e2bab408aec4ea367dc6da35145c3352b60a112d11", + "sha256:7a94bde005a8f926d0fa38b88092a03dea4b4875a61fbcd9ac6f4351df1b57cd", + "sha256:7ae5f99a32c53731c93ac3075abd3e1e5cfbe72fc3eaac4c27c9dd64ba3b19fe", + "sha256:7e8a3b79b6d186a9c99761fd4a5e8dd575a48d96021f220ac5b5fa856e5dd029", + "sha256:816f4db40555026e4cdda604a1088577c1fb957d02f3f1292e0221353403f192", + "sha256:8303531e2c17b1a494ffaeba48f2da655fe932c4e9a2626c8718403c83e5dd2b", + "sha256:8488519aa05e636c5997719fe543c8daf19f538f4fa044f3ce94bee608817cff", + "sha256:87c8b0a6487e8109427ccf638580865b54e2e3db4a6e0e11c02639231b41fc0f", + "sha256:8c9e5f4d7208cda1a2bb600e29069eecf857e6980d0ccc922ccf9d1372c16f4b", + "sha256:94697c7293199c2a2551e3e3e18438b4cba293e79c6bc2319f5fd652fccb7456", + "sha256:9623cfd9e85b76b83ef88519d98326d4731f8d71869867e47a0b979ffec61c73", + "sha256:98d21092bf2637c5fa724a428a69e8f5955f2182bff61f8036827cf6ce1157bf", + "sha256:99ae01fb13a618b9942376df77a1f50c20a281390dad3c56a6ec2942e266220d", + "sha256:9c196b30f1b1aa3363a69dd69079ae9bec96c2965c4707eaa6914ba099fb7d4f", + "sha256:a00ce44c21612d185c5275c5cba4bab8d7c1590f248638b667ed8a782fa8cd6f", + "sha256:a1b66dbb8a7d5f50e9e2ea3804b01e766308331d0cac76eb30c563ac89c95985", + "sha256:a1d7edf74a36de0e5ca50787e83a77cf352f5504eb0ffa3f07000a911ba353fb", + "sha256:a1e3b3c107ccb0e537f309f719994a55621acd2c8fdf6d5ce5152aed788fb940", + "sha256:a486ddf57ab98b6d19ad36458b9f09e6022de0381674fe00228ca7b741aacb2f", + "sha256:ac9669990e2016d644ba8ae4758688534aabde8dbbc81f9af129c3f5f01ca9cd", + "sha256:b1a2ea8252cacc7fd51df5a56d7a2bb1986ed39be9397b51a08015727dfb69bd", + "sha256:c5b7bf8fe4d39886adc34311a233a2e01bc10eb4e842220235ed1de57541a896", + "sha256:c67a51ea415192c2e53e4e048c78bab82d21955b4281d297f517707dc836bf3d", + "sha256:ca4fddf84ac7d8a7d0866664936f93318ff01ee33e32381a115b19fb5a4d1202", + "sha256:d5b9345ab92ebe6003ae11d8092ce822a0242146e6fa270889b9ba965457ca40", + "sha256:d97c3e286d0ac9af6223bc132dc4bad6540b37c8d6c0a15fe1e70fb34f9ec411", + "sha256:db04d1de548f7a62d1dd7e7cdf7c22893ee168e22701895067a28a8ed51b3735", + "sha256:dcf71c55ec853826cd70eadb2b6ac62ec577416442ca1e0a97ad875a1b3a0305", + "sha256:de3cc86f4ea8b4c34a6e43a7306c40c1275e52bfa9748d869c6b7d54aa6dad80", + "sha256:deac0a32aec29608eb25d730f4bc5a261a65b6c48ded1ed861d2a1852577c932", + "sha256:e18d92c3e9e22553a73e33784fcb0ed484c9874e9a3e96c16a8d6a1e74a0217b", + "sha256:eb6dfd52063186ac97b4caa25764cdbcdb4b10d97f5c5f66b0fa95052e744eb7", + "sha256:f09960b5bb1017d16c0f9e9f7fc42160a5a49fa1e87a175fd4a2b1a1833ea0af", + "sha256:f1e4f254e9c35d8965d377e065c4a8a55d396fe87c8e7e8429bcfdeeb229bfb3", + "sha256:f32c86dc967ab8c719fd229ce71917caad13cc1e8356ee997bf02c5b368799bf", + "sha256:f50b4663c3e0262c3a361faf440761fbef60ccdde5fe8545689a4b3a3c149fb4", + "sha256:f8e05f5163528962ce1d1806fce763ab893b1c5b7ace0a3538cd81a90622f844", + "sha256:f929f4c9b9a00f3e6cc0587abb95ab9c05681f8b14e0fe1daecfa83ea90f8318", + "sha256:f9e09a1c83521d770d170b3801eea19b89f41ccaa61d53026ed111cb6f088887" ], "index": "pypi", - "version": "==3.8.1" + "version": "==3.9.0" }, "aiosignal": { "hashes": [ - "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a", - "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2" + "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", + "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17" ], - "markers": "python_version >= '3.6'", - "version": "==1.2.0" + "markers": "python_version >= '3.7'", + "version": "==1.3.1" }, "async-timeout": { "hashes": [ - "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15", - "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c" + "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", + "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028" ], - "markers": "python_version >= '3.6'", - "version": "==4.0.2" + "markers": "python_version < '3.11'", + "version": "==4.0.3" }, "attrs": { "hashes": [ - "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6", - "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c" + "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", + "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015" ], - "markers": "python_version >= '3.5'", - "version": "==22.1.0" + "markers": "python_version >= '3.7'", + "version": "==23.1.0" }, "cairocffi": { "hashes": [ - "sha256:108a3a7cb09e203bdd8501d9baad91d786d204561bd71e9364e8b34897c47b91" + "sha256:78e6bbe47357640c453d0be929fa49cd05cce2e1286f3d2a1ca9cbda7efdb8b7", + "sha256:aa78ee52b9069d7475eeac457389b6275aa92111895d78fbaa2202a52dac112e" ], "markers": "python_version >= '3.7'", - "version": "==1.3.0" + "version": "==1.6.1" }, "cairosvg": { "hashes": [ - "sha256:98c276b7e4f0caf01e5c7176765c104ffa1aa1461d63b2053b04ab663cf7052b", - "sha256:b0b9929cf5dba005178d746a8036fcf0025550f498ca54db61873322384783bc" + "sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0", + "sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b" ], - "version": "==2.5.2" + "version": "==2.7.1" }, "certifi": { "hashes": [ - "sha256:36973885b9542e6bd01dea287b2b4b3b21236307c56324fcc3f1160f2d655ed5", - "sha256:e232343de1ab72c2aa521b625c80f699e356830fd0e2c620b465b304b17b0516" + "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1", + "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474" ], "markers": "python_version >= '3.6'", - "version": "==2022.9.14" + "version": "==2023.11.17" }, "cffi": { "hashes": [ - "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", - "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef", - "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104", - "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426", - "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405", - "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375", - "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a", - "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e", - "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc", - "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf", - "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185", - "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497", - "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3", - "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35", - "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c", - "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83", - "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21", - "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca", - "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984", - "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac", - "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd", - "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee", - "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a", - "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2", - "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192", - "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7", - "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585", - "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f", - "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e", - "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27", - "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b", - "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e", - "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e", - "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d", - "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c", - "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415", - "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82", - "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02", - "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314", - "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325", - "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c", - "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3", - "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914", - "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045", - "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d", - "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9", - "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5", - "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2", - "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c", - "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3", - "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2", - "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8", - "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d", - "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d", - "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9", - "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162", - "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76", - "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4", - "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e", - "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9", - "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6", - "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b", - "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", - "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0" + "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc", + "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a", + "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417", + "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab", + "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520", + "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36", + "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743", + "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8", + "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed", + "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684", + "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56", + "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324", + "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d", + "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", + "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e", + "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088", + "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000", + "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7", + "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e", + "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673", + "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c", + "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe", + "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2", + "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098", + "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8", + "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a", + "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0", + "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b", + "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896", + "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e", + "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9", + "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2", + "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", + "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6", + "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404", + "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f", + "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", + "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4", + "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc", + "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936", + "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba", + "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872", + "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb", + "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614", + "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1", + "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d", + "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969", + "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b", + "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4", + "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627", + "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", + "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" ], - "version": "==1.15.1" + "markers": "python_version >= '3.8'", + "version": "==1.16.0" }, "charset-normalizer": { "hashes": [ @@ -217,11 +211,11 @@ }, "colorama": { "hashes": [ - "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da", - "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4" + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" ], "index": "pypi", - "version": "==0.4.5" + "version": "==0.4.6" }, "cssselect2": { "hashes": [ @@ -249,83 +243,86 @@ }, "dnspython": { "hashes": [ - "sha256:0f7569a4a6ff151958b64304071d370daa3243d15941a7beedf0c9fe5105603e", - "sha256:a851e51367fb93e9e1361732c1d60dab63eff98712e503ea7d92e6eccb109b4f" + "sha256:57c6fbaaeaaf39c891292012060beb141791735dbb4004798328fc2c467402d8", + "sha256:8dcfae8c7460a2f84b4072e26f1c9f4101ca20c071649cb7c34e8b6a93d58984" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.2.1" + "version": "==2.4.2" }, "emoji": { "hashes": [ - "sha256:65c54533ea3c78f30d0729288998715f418d7467de89ec258a31c0ce8660a1d1" + "sha256:8d8b5dec3c507444b58890e598fc895fcec022b3f5acb49497c6ccc5208b8b00", + "sha256:a8468fd836b7ecb6d1eac054c9a591701ce0ccd6c6f7779ad71b66f76664df90" ], "index": "pypi", - "version": "==1.7.0" + "version": "==2.8.0" }, "frozenlist": { "hashes": [ - "sha256:022178b277cb9277d7d3b3f2762d294f15e85cd2534047e68a118c2bb0058f3e", - "sha256:086ca1ac0a40e722d6833d4ce74f5bf1aba2c77cbfdc0cd83722ffea6da52a04", - "sha256:0bc75692fb3770cf2b5856a6c2c9de967ca744863c5e89595df64e252e4b3944", - "sha256:0dde791b9b97f189874d654c55c24bf7b6782343e14909c84beebd28b7217845", - "sha256:12607804084d2244a7bd4685c9d0dca5df17a6a926d4f1967aa7978b1028f89f", - "sha256:19127f8dcbc157ccb14c30e6f00392f372ddb64a6ffa7106b26ff2196477ee9f", - "sha256:1b51eb355e7f813bcda00276b0114c4172872dc5fb30e3fea059b9367c18fbcb", - "sha256:1e1cf7bc8cbbe6ce3881863671bac258b7d6bfc3706c600008925fb799a256e2", - "sha256:219a9676e2eae91cb5cc695a78b4cb43d8123e4160441d2b6ce8d2c70c60e2f3", - "sha256:2743bb63095ef306041c8f8ea22bd6e4d91adabf41887b1ad7886c4c1eb43d5f", - "sha256:2af6f7a4e93f5d08ee3f9152bce41a6015b5cf87546cb63872cc19b45476e98a", - "sha256:31b44f1feb3630146cffe56344704b730c33e042ffc78d21f2125a6a91168131", - "sha256:31bf9539284f39ff9398deabf5561c2b0da5bb475590b4e13dd8b268d7a3c5c1", - "sha256:35c3d79b81908579beb1fb4e7fcd802b7b4921f1b66055af2578ff7734711cfa", - "sha256:3a735e4211a04ccfa3f4833547acdf5d2f863bfeb01cfd3edaffbc251f15cec8", - "sha256:42719a8bd3792744c9b523674b752091a7962d0d2d117f0b417a3eba97d1164b", - "sha256:49459f193324fbd6413e8e03bd65789e5198a9fa3095e03f3620dee2f2dabff2", - "sha256:4c0c99e31491a1d92cde8648f2e7ccad0e9abb181f6ac3ddb9fc48b63301808e", - "sha256:52137f0aea43e1993264a5180c467a08a3e372ca9d378244c2d86133f948b26b", - "sha256:526d5f20e954d103b1d47232e3839f3453c02077b74203e43407b962ab131e7b", - "sha256:53b2b45052e7149ee8b96067793db8ecc1ae1111f2f96fe1f88ea5ad5fd92d10", - "sha256:572ce381e9fe027ad5e055f143763637dcbac2542cfe27f1d688846baeef5170", - "sha256:58fb94a01414cddcdc6839807db77ae8057d02ddafc94a42faee6004e46c9ba8", - "sha256:5e77a8bd41e54b05e4fb2708dc6ce28ee70325f8c6f50f3df86a44ecb1d7a19b", - "sha256:5f271c93f001748fc26ddea409241312a75e13466b06c94798d1a341cf0e6989", - "sha256:5f63c308f82a7954bf8263a6e6de0adc67c48a8b484fab18ff87f349af356efd", - "sha256:61d7857950a3139bce035ad0b0945f839532987dfb4c06cfe160254f4d19df03", - "sha256:61e8cb51fba9f1f33887e22488bad1e28dd8325b72425f04517a4d285a04c519", - "sha256:625d8472c67f2d96f9a4302a947f92a7adbc1e20bedb6aff8dbc8ff039ca6189", - "sha256:6e19add867cebfb249b4e7beac382d33215d6d54476bb6be46b01f8cafb4878b", - "sha256:717470bfafbb9d9be624da7780c4296aa7935294bd43a075139c3d55659038ca", - "sha256:74140933d45271c1a1283f708c35187f94e1256079b3c43f0c2267f9db5845ff", - "sha256:74e6b2b456f21fc93ce1aff2b9728049f1464428ee2c9752a4b4f61e98c4db96", - "sha256:9494122bf39da6422b0972c4579e248867b6b1b50c9b05df7e04a3f30b9a413d", - "sha256:94e680aeedc7fd3b892b6fa8395b7b7cc4b344046c065ed4e7a1e390084e8cb5", - "sha256:97d9e00f3ac7c18e685320601f91468ec06c58acc185d18bb8e511f196c8d4b2", - "sha256:9c6ef8014b842f01f5d2b55315f1af5cbfde284eb184075c189fd657c2fd8204", - "sha256:a027f8f723d07c3f21963caa7d585dcc9b089335565dabe9c814b5f70c52705a", - "sha256:a718b427ff781c4f4e975525edb092ee2cdef6a9e7bc49e15063b088961806f8", - "sha256:ab386503f53bbbc64d1ad4b6865bf001414930841a870fc97f1546d4d133f141", - "sha256:ab6fa8c7871877810e1b4e9392c187a60611fbf0226a9e0b11b7b92f5ac72792", - "sha256:b47d64cdd973aede3dd71a9364742c542587db214e63b7529fbb487ed67cddd9", - "sha256:b499c6abe62a7a8d023e2c4b2834fce78a6115856ae95522f2f974139814538c", - "sha256:bbb1a71b1784e68870800b1bc9f3313918edc63dbb8f29fbd2e767ce5821696c", - "sha256:c3b31180b82c519b8926e629bf9f19952c743e089c41380ddca5db556817b221", - "sha256:c56c299602c70bc1bb5d1e75f7d8c007ca40c9d7aebaf6e4ba52925d88ef826d", - "sha256:c92deb5d9acce226a501b77307b3b60b264ca21862bd7d3e0c1f3594022f01bc", - "sha256:cc2f3e368ee5242a2cbe28323a866656006382872c40869b49b265add546703f", - "sha256:d82bed73544e91fb081ab93e3725e45dd8515c675c0e9926b4e1f420a93a6ab9", - "sha256:da1cdfa96425cbe51f8afa43e392366ed0b36ce398f08b60de6b97e3ed4affef", - "sha256:da5ba7b59d954f1f214d352308d1d86994d713b13edd4b24a556bcc43d2ddbc3", - "sha256:e0c8c803f2f8db7217898d11657cb6042b9b0553a997c4a0601f48a691480fab", - "sha256:ee4c5120ddf7d4dd1eaf079af3af7102b56d919fa13ad55600a4e0ebe532779b", - "sha256:eee0c5ecb58296580fc495ac99b003f64f82a74f9576a244d04978a7e97166db", - "sha256:f5abc8b4d0c5b556ed8cd41490b606fe99293175a82b98e652c3f2711b452988", - "sha256:f810e764617b0748b49a731ffaa525d9bb36ff38332411704c2400125af859a6", - "sha256:f89139662cc4e65a4813f4babb9ca9544e42bddb823d2ec434e18dad582543bc", - "sha256:fa47319a10e0a076709644a0efbcaab9e91902c8bd8ef74c6adb19d320f69b83", - "sha256:fabb953ab913dadc1ff9dcc3a7a7d3dc6a92efab3a0373989b8063347f8705be" + "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6", + "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01", + "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251", + "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9", + "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b", + "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87", + "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf", + "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f", + "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0", + "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2", + "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b", + "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc", + "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c", + "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467", + "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9", + "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1", + "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a", + "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79", + "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167", + "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300", + "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf", + "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea", + "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2", + "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab", + "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3", + "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb", + "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087", + "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc", + "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8", + "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62", + "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f", + "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326", + "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c", + "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431", + "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963", + "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7", + "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef", + "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3", + "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956", + "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781", + "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472", + "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc", + "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839", + "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672", + "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3", + "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503", + "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d", + "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8", + "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b", + "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc", + "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f", + "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559", + "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b", + "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95", + "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb", + "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963", + "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919", + "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f", + "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3", + "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1", + "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e" ], - "markers": "python_version >= '3.7'", - "version": "==1.3.1" + "markers": "python_version >= '3.8'", + "version": "==1.4.0" }, "idna": { "hashes": [ @@ -363,68 +360,83 @@ }, "multidict": { "hashes": [ - "sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60", - "sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c", - "sha256:0556a1d4ea2d949efe5fd76a09b4a82e3a4a30700553a6725535098d8d9fb672", - "sha256:05f6949d6169878a03e607a21e3b862eaf8e356590e8bdae4227eedadacf6e51", - "sha256:07a017cfa00c9890011628eab2503bee5872f27144936a52eaab449be5eaf032", - "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2", - "sha256:19adcfc2a7197cdc3987044e3f415168fc5dc1f720c932eb1ef4f71a2067e08b", - "sha256:19d9bad105dfb34eb539c97b132057a4e709919ec4dd883ece5838bcbf262b80", - "sha256:225383a6603c086e6cef0f2f05564acb4f4d5f019a4e3e983f572b8530f70c88", - "sha256:23b616fdc3c74c9fe01d76ce0d1ce872d2d396d8fa8e4899398ad64fb5aa214a", - "sha256:2957489cba47c2539a8eb7ab32ff49101439ccf78eab724c828c1a54ff3ff98d", - "sha256:2d36e929d7f6a16d4eb11b250719c39560dd70545356365b494249e2186bc389", - "sha256:2e4a0785b84fb59e43c18a015ffc575ba93f7d1dbd272b4cdad9f5134b8a006c", - "sha256:3368bf2398b0e0fcbf46d85795adc4c259299fec50c1416d0f77c0a843a3eed9", - "sha256:373ba9d1d061c76462d74e7de1c0c8e267e9791ee8cfefcf6b0b2495762c370c", - "sha256:4070613ea2227da2bfb2c35a6041e4371b0af6b0be57f424fe2318b42a748516", - "sha256:45183c96ddf61bf96d2684d9fbaf6f3564d86b34cb125761f9a0ef9e36c1d55b", - "sha256:4571f1beddff25f3e925eea34268422622963cd8dc395bb8778eb28418248e43", - "sha256:47e6a7e923e9cada7c139531feac59448f1f47727a79076c0b1ee80274cd8eee", - "sha256:47fbeedbf94bed6547d3aa632075d804867a352d86688c04e606971595460227", - "sha256:497988d6b6ec6ed6f87030ec03280b696ca47dbf0648045e4e1d28b80346560d", - "sha256:4bae31803d708f6f15fd98be6a6ac0b6958fcf68fda3c77a048a4f9073704aae", - "sha256:50bd442726e288e884f7be9071016c15a8742eb689a593a0cac49ea093eef0a7", - "sha256:514fe2b8d750d6cdb4712346a2c5084a80220821a3e91f3f71eec11cf8d28fd4", - "sha256:5774d9218d77befa7b70d836004a768fb9aa4fdb53c97498f4d8d3f67bb9cfa9", - "sha256:5fdda29a3c7e76a064f2477c9aab1ba96fd94e02e386f1e665bca1807fc5386f", - "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013", - "sha256:626fe10ac87851f4cffecee161fc6f8f9853f0f6f1035b59337a51d29ff3b4f9", - "sha256:6701bf8a5d03a43375909ac91b6980aea74b0f5402fbe9428fc3f6edf5d9677e", - "sha256:684133b1e1fe91eda8fa7447f137c9490a064c6b7f392aa857bba83a28cfb693", - "sha256:6f3cdef8a247d1eafa649085812f8a310e728bdf3900ff6c434eafb2d443b23a", - "sha256:75bdf08716edde767b09e76829db8c1e5ca9d8bb0a8d4bd94ae1eafe3dac5e15", - "sha256:7c40b7bbece294ae3a87c1bc2abff0ff9beef41d14188cda94ada7bcea99b0fb", - "sha256:8004dca28e15b86d1b1372515f32eb6f814bdf6f00952699bdeb541691091f96", - "sha256:8064b7c6f0af936a741ea1efd18690bacfbae4078c0c385d7c3f611d11f0cf87", - "sha256:89171b2c769e03a953d5969b2f272efa931426355b6c0cb508022976a17fd376", - "sha256:8cbf0132f3de7cc6c6ce00147cc78e6439ea736cee6bca4f068bcf892b0fd658", - "sha256:9cc57c68cb9139c7cd6fc39f211b02198e69fb90ce4bc4a094cf5fe0d20fd8b0", - "sha256:a007b1638e148c3cfb6bf0bdc4f82776cef0ac487191d093cdc316905e504071", - "sha256:a2c34a93e1d2aa35fbf1485e5010337c72c6791407d03aa5f4eed920343dd360", - "sha256:a45e1135cb07086833ce969555df39149680e5471c04dfd6a915abd2fc3f6dbc", - "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3", - "sha256:aef9cc3d9c7d63d924adac329c33835e0243b5052a6dfcbf7732a921c6e918ba", - "sha256:b9d153e7f1f9ba0b23ad1568b3b9e17301e23b042c23870f9ee0522dc5cc79e8", - "sha256:bfba7c6d5d7c9099ba21f84662b037a0ffd4a5e6b26ac07d19e423e6fdf965a9", - "sha256:c207fff63adcdf5a485969131dc70e4b194327666b7e8a87a97fbc4fd80a53b2", - "sha256:d0509e469d48940147e1235d994cd849a8f8195e0bca65f8f5439c56e17872a3", - "sha256:d16cce709ebfadc91278a1c005e3c17dd5f71f5098bfae1035149785ea6e9c68", - "sha256:d48b8ee1d4068561ce8033d2c344cf5232cb29ee1a0206a7b828c79cbc5982b8", - "sha256:de989b195c3d636ba000ee4281cd03bb1234635b124bf4cd89eeee9ca8fcb09d", - "sha256:e07c8e79d6e6fd37b42f3250dba122053fddb319e84b55dd3a8d6446e1a7ee49", - "sha256:e2c2e459f7050aeb7c1b1276763364884595d47000c1cddb51764c0d8976e608", - "sha256:e5b20e9599ba74391ca0cfbd7b328fcc20976823ba19bc573983a25b32e92b57", - "sha256:e875b6086e325bab7e680e4316d667fc0e5e174bb5611eb16b3ea121c8951b86", - "sha256:f4f052ee022928d34fe1f4d2bc743f32609fb79ed9c49a1710a5ad6b2198db20", - "sha256:fcb91630817aa8b9bc4a74023e4198480587269c272c58b3279875ed7235c293", - "sha256:fd9fc9c4849a07f3635ccffa895d57abce554b467d611a5009ba4f39b78a8849", - "sha256:feba80698173761cddd814fa22e88b0661e98cb810f9f986c54aa34d281e4937", - "sha256:feea820722e69451743a3d56ad74948b68bf456984d63c1a92e8347b7b88452d" + "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9", + "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8", + "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03", + "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710", + "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161", + "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664", + "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569", + "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067", + "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313", + "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706", + "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2", + "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636", + "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49", + "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93", + "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603", + "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0", + "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60", + "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4", + "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e", + "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1", + "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60", + "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951", + "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc", + "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe", + "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95", + "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d", + "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8", + "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed", + "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2", + "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775", + "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87", + "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c", + "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2", + "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98", + "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3", + "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe", + "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78", + "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660", + "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176", + "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e", + "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988", + "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c", + "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c", + "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0", + "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449", + "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f", + "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde", + "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5", + "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d", + "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac", + "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a", + "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9", + "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca", + "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11", + "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35", + "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063", + "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b", + "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982", + "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258", + "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1", + "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52", + "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480", + "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7", + "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461", + "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d", + "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc", + "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779", + "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a", + "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547", + "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0", + "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171", + "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf", + "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d", + "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba" ], "markers": "python_version >= '3.7'", - "version": "==6.0.2" + "version": "==6.0.4" }, "natural": { "hashes": [ @@ -443,69 +455,63 @@ }, "pillow": { "hashes": [ - "sha256:0030fdbd926fb85844b8b92e2f9449ba89607231d3dd597a21ae72dc7fe26927", - "sha256:030e3460861488e249731c3e7ab59b07c7853838ff3b8e16aac9561bb345da14", - "sha256:0ed2c4ef2451de908c90436d6e8092e13a43992f1860275b4d8082667fbb2ffc", - "sha256:136659638f61a251e8ed3b331fc6ccd124590eeff539de57c5f80ef3a9594e58", - "sha256:13b725463f32df1bfeacbf3dd197fb358ae8ebcd8c5548faa75126ea425ccb60", - "sha256:1536ad017a9f789430fb6b8be8bf99d2f214c76502becc196c6f2d9a75b01b76", - "sha256:15928f824870535c85dbf949c09d6ae7d3d6ac2d6efec80f3227f73eefba741c", - "sha256:17d4cafe22f050b46d983b71c707162d63d796a1235cdf8b9d7a112e97b15bac", - "sha256:1802f34298f5ba11d55e5bb09c31997dc0c6aed919658dfdf0198a2fe75d5490", - "sha256:1cc1d2451e8a3b4bfdb9caf745b58e6c7a77d2e469159b0d527a4554d73694d1", - "sha256:1fd6f5e3c0e4697fa7eb45b6e93996299f3feee73a3175fa451f49a74d092b9f", - "sha256:254164c57bab4b459f14c64e93df11eff5ded575192c294a0c49270f22c5d93d", - "sha256:2ad0d4df0f5ef2247e27fc790d5c9b5a0af8ade9ba340db4a73bb1a4a3e5fb4f", - "sha256:2c58b24e3a63efd22554c676d81b0e57f80e0a7d3a5874a7e14ce90ec40d3069", - "sha256:2d33a11f601213dcd5718109c09a52c2a1c893e7461f0be2d6febc2879ec2402", - "sha256:336b9036127eab855beec9662ac3ea13a4544a523ae273cbf108b228ecac8437", - "sha256:337a74fd2f291c607d220c793a8135273c4c2ab001b03e601c36766005f36885", - "sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e", - "sha256:3d1f14f5f691f55e1b47f824ca4fdcb4b19b4323fe43cc7bb105988cad7496be", - "sha256:408673ed75594933714482501fe97e055a42996087eeca7e5d06e33218d05aa8", - "sha256:4134d3f1ba5f15027ff5c04296f13328fecd46921424084516bdb1b2548e66ff", - "sha256:4ad2f835e0ad81d1689f1b7e3fbac7b01bb8777d5a985c8962bedee0cc6d43da", - "sha256:50dff9cc21826d2977ef2d2a205504034e3a4563ca6f5db739b0d1026658e004", - "sha256:510cef4a3f401c246cfd8227b300828715dd055463cdca6176c2e4036df8bd4f", - "sha256:5aed7dde98403cd91d86a1115c78d8145c83078e864c1de1064f52e6feb61b20", - "sha256:69bd1a15d7ba3694631e00df8de65a8cb031911ca11f44929c97fe05eb9b6c1d", - "sha256:6bf088c1ce160f50ea40764f825ec9b72ed9da25346216b91361eef8ad1b8f8c", - "sha256:6e8c66f70fb539301e064f6478d7453e820d8a2c631da948a23384865cd95544", - "sha256:727dd1389bc5cb9827cbd1f9d40d2c2a1a0c9b32dd2261db522d22a604a6eec9", - "sha256:74a04183e6e64930b667d321524e3c5361094bb4af9083db5c301db64cd341f3", - "sha256:75e636fd3e0fb872693f23ccb8a5ff2cd578801251f3a4f6854c6a5d437d3c04", - "sha256:7761afe0126d046974a01e030ae7529ed0ca6a196de3ec6937c11df0df1bc91c", - "sha256:7888310f6214f19ab2b6df90f3f06afa3df7ef7355fc025e78a3044737fab1f5", - "sha256:7b0554af24df2bf96618dac71ddada02420f946be943b181108cac55a7a2dcd4", - "sha256:7c7b502bc34f6e32ba022b4a209638f9e097d7a9098104ae420eb8186217ebbb", - "sha256:808add66ea764ed97d44dda1ac4f2cfec4c1867d9efb16a33d158be79f32b8a4", - "sha256:831e648102c82f152e14c1a0938689dbb22480c548c8d4b8b248b3e50967b88c", - "sha256:93689632949aff41199090eff5474f3990b6823404e45d66a5d44304e9cdc467", - "sha256:96b5e6874431df16aee0c1ba237574cb6dff1dcb173798faa6a9d8b399a05d0e", - "sha256:9a54614049a18a2d6fe156e68e188da02a046a4a93cf24f373bffd977e943421", - "sha256:a138441e95562b3c078746a22f8fca8ff1c22c014f856278bdbdd89ca36cff1b", - "sha256:a647c0d4478b995c5e54615a2e5360ccedd2f85e70ab57fbe817ca613d5e63b8", - "sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb", - "sha256:ad2277b185ebce47a63f4dc6302e30f05762b688f8dc3de55dbae4651872cdf3", - "sha256:adabc0bce035467fb537ef3e5e74f2847c8af217ee0be0455d4fec8adc0462fc", - "sha256:b6d5e92df2b77665e07ddb2e4dbd6d644b78e4c0d2e9272a852627cdba0d75cf", - "sha256:bc431b065722a5ad1dfb4df354fb9333b7a582a5ee39a90e6ffff688d72f27a1", - "sha256:bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a", - "sha256:c79698d4cd9318d9481d89a77e2d3fcaeff5486be641e60a4b49f3d2ecca4e28", - "sha256:cb6259196a589123d755380b65127ddc60f4c64b21fc3bb46ce3a6ea663659b0", - "sha256:d5b87da55a08acb586bad5c3aa3b86505f559b84f39035b233d5bf844b0834b1", - "sha256:dcd7b9c7139dc8258d164b55696ecd16c04607f1cc33ba7af86613881ffe4ac8", - "sha256:dfe4c1fedfde4e2fbc009d5ad420647f7730d719786388b7de0999bf32c0d9fd", - "sha256:ea98f633d45f7e815db648fd7ff0f19e328302ac36427343e4432c84432e7ff4", - "sha256:ec52c351b35ca269cb1f8069d610fc45c5bd38c3e91f9ab4cbbf0aebc136d9c8", - "sha256:eef7592281f7c174d3d6cbfbb7ee5984a671fcd77e3fc78e973d492e9bf0eb3f", - "sha256:f07f1f00e22b231dd3d9b9208692042e29792d6bd4f6639415d2f23158a80013", - "sha256:f3fac744f9b540148fa7715a435d2283b71f68bfb6d4aae24482a890aed18b59", - "sha256:fa768eff5f9f958270b081bb33581b4b569faabf8774726b283edb06617101dc", - "sha256:fac2d65901fb0fdf20363fbd345c01958a742f2dc62a8dd4495af66e3ff502a4" + "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d", + "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de", + "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616", + "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839", + "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099", + "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a", + "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219", + "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106", + "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b", + "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412", + "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b", + "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7", + "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2", + "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7", + "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14", + "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f", + "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27", + "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57", + "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262", + "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28", + "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610", + "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172", + "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273", + "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e", + "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d", + "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818", + "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f", + "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9", + "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01", + "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7", + "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651", + "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312", + "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80", + "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666", + "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061", + "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b", + "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992", + "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593", + "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4", + "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db", + "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba", + "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd", + "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e", + "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212", + "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb", + "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2", + "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34", + "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256", + "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f", + "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2", + "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38", + "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996", + "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a", + "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793" ], - "markers": "python_version >= '3.7'", - "version": "==9.2.0" + "markers": "python_version >= '3.8'", + "version": "==10.1.0" }, "pycparser": { "hashes": [ @@ -515,121 +521,121 @@ "version": "==2.21" }, "pymongo": { - "extras": [ - "srv" - ], + "extras": [], "hashes": [ - "sha256:06b64cdf5121f86b78a84e61b8f899b6988732a8d304b503ea1f94a676221c06", - "sha256:07398d8a03545b98282f459f2603a6bb271f4448d484ed7f411121a519a7ea48", - "sha256:0a02313e71b7c370c43056f6b16c45effbb2d29a44d24403a3d5ba6ed322fa3f", - "sha256:0a89cadc0062a5e53664dde043f6c097172b8c1c5f0094490095282ff9995a5f", - "sha256:0be605bfb8461384a4cb81e80f51eb5ca1b89851f2d0e69a75458c788a7263a4", - "sha256:0d52a70350ec3dfc39b513df12b03b7f4c8f8ec6873bbf958299999db7b05eb1", - "sha256:0e7a5d0b9077e8c3e57727f797ee8adf12e1d5e7534642230d98980d160d1320", - "sha256:145d78c345a38011497e55aff22c0f8edd40ee676a6810f7e69563d68a125e83", - "sha256:14dee106a10b77224bba5efeeb6aee025aabe88eb87a2b850c46d3ee55bdab4a", - "sha256:176fdca18391e1206c32fb1d8265628a84d28333c20ad19468d91e3e98312cd1", - "sha256:1b4c535f524c9d8c86c3afd71d199025daa070859a2bdaf94a298120b0de16db", - "sha256:1b5cb75d2642ff7db823f509641f143f752c0d1ab03166cafea1e42e50469834", - "sha256:1c6c71e198b36f0f0dfe354f06d3655ecfa30d69493a1da125a9a54668aad652", - "sha256:1c771f1a8b3cd2d697baaf57e9cfa4ae42371cacfbea42ea01d9577c06d92f96", - "sha256:208a61db8b8b647fb5b1ff3b52b4ed6dbced01eac3b61009958adb203596ee99", - "sha256:2157d68f85c28688e8b723bbe70c8013e0aba5570e08c48b3562f74d33fc05c4", - "sha256:2301051701b27aff2cbdf83fae22b7ca883c9563dfd088033267291b46196643", - "sha256:2567885ff0c8c7c0887ba6cefe4ae4af96364a66a7069f924ce0cd12eb971d04", - "sha256:2577b8161eeae4dd376d13100b2137d883c10bb457dd08935f60c9f9d4b5c5f6", - "sha256:27e5ea64332385385b75414888ce9d1a9806be8616d7cef4ef409f4f256c6d06", - "sha256:28bfd5244d32faf3e49b5a8d1fab0631e922c26e8add089312e4be19fb05af50", - "sha256:295a5beaecb7bf054c1c6a28749ed72b19f4d4b61edcd8a0815d892424baf780", - "sha256:2c46a0afef69d61938a6fe32c3afd75b91dec3ab3056085dc72abbeedcc94166", - "sha256:3100a2352bdded6232b385ceda0c0a4624598c517d52c2d8cf014b7abbebd84d", - "sha256:320a1fe403dd83a35709fcf01083d14bc1462e9789b711201349a9158db3a87e", - "sha256:320f8734553c50cffe8a8e1ae36dfc7d7be1941c047489db20a814d2a170d7b5", - "sha256:33ab8c031f788609924e329003088831045f683931932a52a361d4a955b7dce2", - "sha256:3492ae1f97209c66af70e863e6420e6301cecb0a51a5efa701058aa73a8ca29e", - "sha256:351a2efe1c9566c348ad0076f4bf541f4905a0ebe2d271f112f60852575f3c16", - "sha256:3f0ac6e0203bd88863649e6ed9c7cfe53afab304bc8225f2597c4c0a74e4d1f0", - "sha256:3fedad05147b40ff8a93fcd016c421e6c159f149a2a481cfa0b94bfa3e473bab", - "sha256:4294f2c1cd069b793e31c2e6d7ac44b121cf7cedccd03ebcc30f3fc3417b314a", - "sha256:463b974b7f49d65a16ca1435bc1c25a681bb7d630509dd23b2e819ed36da0b7f", - "sha256:4e0a3ea7fd01cf0a36509f320226bd8491e0f448f00b8cb89f601c109f6874e1", - "sha256:514e78d20d8382d5b97f32b20c83d1d0452c302c9a135f0a9022236eb9940fda", - "sha256:517b09b1dd842390a965a896d1327c55dfe78199c9f5840595d40facbcd81854", - "sha256:51d1d061df3995c2332ae78f036492cc188cb3da8ef122caeab3631a67bb477e", - "sha256:5296669bff390135528001b4e48d33a7acaffcd361d98659628ece7f282f11aa", - "sha256:5296e5e69243ffd76bd919854c4da6630ae52e46175c804bc4c0e050d937b705", - "sha256:58db209da08a502ce6948841d522dcec80921d714024354153d00b054571993c", - "sha256:5b779e87300635b8075e8d5cfd4fdf7f46078cd7610c381d956bca5556bb8f97", - "sha256:5cf113a46d81cff0559d57aa66ffa473d57d1a9496f97426318b6b5b14fdec1c", - "sha256:5d20072d81cbfdd8e15e6a0c91fc7e3a4948c71e0adebfc67d3b4bcbe8602711", - "sha256:5d67dbc8da2dac1644d71c1839d12d12aa333e266a9964d5b1a49feed036bc94", - "sha256:5f530f35e1a57d4360eddcbed6945aecdaee2a491cd3f17025e7b5f2eea88ee7", - "sha256:5fdffb0cfeb4dc8646a5381d32ec981ae8472f29c695bf09e8f7a8edb2db12ca", - "sha256:602284e652bb56ca8760f8e88a5280636c5b63d7946fca1c2fe0f83c37dffc64", - "sha256:648fcfd8e019b122b7be0e26830a3a2224d57c3e934f19c1e53a77b8380e6675", - "sha256:64b9122be1c404ce4eb367ad609b590394587a676d84bfed8e03c3ce76d70560", - "sha256:6526933760ee1e6090db808f1690a111ec409699c1990efc96f134d26925c37f", - "sha256:6632b1c63d58cddc72f43ab9f17267354ddce563dd5e11eadabd222dcc808808", - "sha256:6f93dbfa5a461107bc3f5026e0d5180499e13379e9404f07a9f79eb5e9e1303d", - "sha256:71c0db2c313ea8a80825fb61b7826b8015874aec29ee6364ade5cb774fe4511b", - "sha256:71c5c200fd37a5322706080b09c3ec8907cf01c377a7187f354fc9e9e13abc73", - "sha256:7738147cd9dbd6d18d5593b3491b4620e13b61de975fd737283e4ad6c255c273", - "sha256:7a6e4dccae8ef5dd76052647d78f02d5d0ffaff1856277d951666c54aeba3ad2", - "sha256:7b4a9fcd95e978cd3c96cdc2096aa54705266551422cf0883c12a4044def31c6", - "sha256:80710d7591d579442c67a3bc7ae9dcba9ff95ea8414ac98001198d894fc4ff46", - "sha256:81a3ebc33b1367f301d1c8eda57eec4868e951504986d5d3fe437479dcdac5b2", - "sha256:8455176fd1b86de97d859fed4ae0ef867bf998581f584c7a1a591246dfec330f", - "sha256:845b178bd127bb074835d2eac635b980c58ec5e700ebadc8355062df708d5a71", - "sha256:858af7c2ab98f21ed06b642578b769ecfcabe4754648b033168a91536f7beef9", - "sha256:87e18f29bac4a6be76a30e74de9c9005475e27100acf0830679420ce1fd9a6fd", - "sha256:89d7baa847383b9814de640c6f1a8553d125ec65e2761ad146ea2e75a7ad197c", - "sha256:8c7ad5cab282f53b9d78d51504330d1c88c83fbe187e472c07e6908a0293142e", - "sha256:8d92c6bb9174d47c2257528f64645a00bbc6324a9ff45a626192797aff01dc14", - "sha256:9252c991e8176b5a2fa574c5ab9a841679e315f6e576eb7cf0bd958f3e39b0ad", - "sha256:93111fd4e08fa889c126aa8baf5c009a941880a539c87672e04583286517450a", - "sha256:95d15cf81cd2fb926f2a6151a9f94c7aacc102b415e72bc0e040e29332b6731c", - "sha256:9d5b66d457d2c5739c184a777455c8fde7ab3600a56d8bbebecf64f7c55169e1", - "sha256:a055d29f1302892a9389a382bed10a3f77708bcf3e49bfb76f7712fa5f391cc6", - "sha256:a1ba93be779a9b8e5e44f5c133dc1db4313661cead8a2fd27661e6cb8d942ee9", - "sha256:a283425e6a474facd73072d8968812d1d9058490a5781e022ccf8895500b83ce", - "sha256:a351986d6c9006308f163c359ced40f80b6cffb42069f3e569b979829951038d", - "sha256:a766157b195a897c64945d4ff87b050bb0e763bb78f3964e996378621c703b00", - "sha256:a8a3540e21213cb8ce232e68a7d0ee49cdd35194856c50b8bd87eeb572fadd42", - "sha256:a8e0a086dbbee406cc6f603931dfe54d1cb2fba585758e06a2de01037784b737", - "sha256:ab23b0545ec71ea346bf50a5d376d674f56205b729980eaa62cdb7871805014b", - "sha256:b0db9a4691074c347f5d7ee830ab3529bc5ad860939de21c1f9c403daf1eda9a", - "sha256:b1b5be40ebf52c3c67ee547e2c4435ed5bc6352f38d23e394520b686641a6be4", - "sha256:b3e08aef4ea05afbc0a70cd23c13684e7f5e074f02450964ec5cfa1c759d33d2", - "sha256:b7df0d99e189b7027d417d4bfd9b8c53c9c7ed5a0a1495d26a6f547d820eca88", - "sha256:be1f10145f7ea76e3e836fdc5c8429c605675bdcddb0bca9725ee6e26874c00c", - "sha256:bf254a1a95e95fdf4eaa25faa1ea450a6533ed7a997f9f8e49ab971b61ea514d", - "sha256:bfc2d763d05ec7211313a06e8571236017d3e61d5fef97fcf34ec4b36c0b6556", - "sha256:c164eda0be9048f83c24b9b2656900041e069ddf72de81c17d874d0c32f6079f", - "sha256:c22591cff80188dd8543be0b559d0c807f7288bd353dc0bcfe539b4588b3a5cd", - "sha256:c5f83bb59d0ff60c6fdb1f8a7b0288fbc4640b1f0fd56f5ae2387749c35d34e3", - "sha256:c7e8221278e5f9e2b6d3893cfc3a3e46c017161a57bb0e6f244826e4cee97916", - "sha256:c8d6bf6fcd42cde2f02efb8126812a010c297eacefcd090a609639d2aeda6185", - "sha256:c8f7dd025cb0bf19e2f60a64dfc24b513c8330e0cfe4a34ccf941eafd6194d9e", - "sha256:c9d212e2af72d5c8d082775a43eb726520e95bf1c84826440f74225843975136", - "sha256:cebb3d8bcac4a6b48be65ebbc5c9881ed4a738e27bb96c86d9d7580a1fb09e05", - "sha256:d3082e5c4d7b388792124f5e805b469109e58f1ab1eb1fbd8b998e8ab766ffb7", - "sha256:d81047341ab56061aa4b6823c54d4632579c3b16e675089e8f520e9b918a133b", - "sha256:d81299f63dc33cc172c26faf59cc54dd795fc6dd5821a7676cca112a5ee8bbd6", - "sha256:dfa217bf8cf3ff6b30c8e6a89014e0c0e7b50941af787b970060ae5ba04a4ce5", - "sha256:dfec57f15f53d677b8e4535695ff3f37df7f8fe431f2efa8c3c8c4025b53d1eb", - "sha256:e099b79ccf7c40f18b149a64d3d10639980035f9ceb223169dd806ff1bb0d9cc", - "sha256:e1fc4d3985868860b6585376e511bb32403c5ffb58b0ed913496c27fd791deea", - "sha256:e2b4c95c47fb81b19ea77dc1c50d23af3eba87c9628fcc2e03d44124a3d336ea", - "sha256:e4e5d163e6644c2bc84dd9f67bfa89288c23af26983d08fefcc2cbc22f6e57e6", - "sha256:e66b3c9f8b89d4fd58a59c04fdbf10602a17c914fbaaa5e6ea593f1d54b06362", - "sha256:ed7d11330e443aeecab23866055e08a5a536c95d2c25333aeb441af2dbac38d2", - "sha256:f340a2a908644ea6cccd399be0fb308c66e05d2800107345f9f0f0d59e1731c4", - "sha256:f38b35ecd2628bf0267761ed659e48af7e620a7fcccfccf5774e7308fb18325c", - "sha256:f6d5443104f89a840250087863c91484a72f254574848e951d1bdd7d8b2ce7c9", - "sha256:fc2048d13ff427605fea328cbe5369dce549b8c7657b0e22051a5b8831170af6" + "sha256:028175dd8d2979a889153a2308e8e500b3df7d9e3fd1c33ca7fdeadf61cc87a2", + "sha256:02f0e1a75d3bc0e16c7e15daf9c56185642be055e425f3b34888fc6eb1b22401", + "sha256:0665412dce26b2318092a33bd2d2327d487c4490cfcde158d6946d39b1e28d78", + "sha256:09b9d0f5a445c7e0ddcc021b09835aa6556f0166afc498f57dfdd72cdf6f02ad", + "sha256:09de3bfc995ae8cb955abb0c9ae963c134dba1b5622be3bcc527b89b0fd4091c", + "sha256:0e5536994cf2d8488c6fd9dea71df3c4dbb3e0d2ba5e695da06d9142a29a0969", + "sha256:0f2c5a5984599a88d087a15859860579b825098b473d8c843f1979a83d159f2e", + "sha256:1037097708498bdc85f23c8798a5c46c7bce432d77d23608ff14e0d831f1a971", + "sha256:10f0fddc1d63ba3d4a4bffcc7720184c1b7efd570726ad5e2f55818da320239f", + "sha256:12721d926d43d33dd3318e58dce9b0250e8a9c6e1093fa8e09f4805193ff4b43", + "sha256:1410faa51ce835cc1234c99ec42e98ab4f3c6f50d92d86a2d4f6e11c97ee7a4e", + "sha256:16e74b9c2aca2734c7f49f00fe68d6830a30d26df60e2ace7fe40ccb92087b94", + "sha256:172db03182a22e9002157b262c1ea3b0045c73d4ff465adc152ce5b4b0e7b8d4", + "sha256:174fd1000e896d0dfbc7f6d7e6a1992a4868796c7dec31679e38218c78d6a942", + "sha256:1c2c5e2b00e2fadcd590c0b2e293d71215e98ed1cb635cfca2be4998d197e534", + "sha256:1c9d23f62a3fa7523d849c4942acc0d9ff7081ebc00c808ee7cfdc070df0687f", + "sha256:21e61a536ffed84d10376c21c13a6ed1ebefb61989a844952547c229d6aeedf3", + "sha256:222591b828de10ac90064047b5d4916953f38c38b155009c4b8b5e0d33117c2b", + "sha256:2406df90b2335371706c59b7d79e9633b81ed2a7ecd48c1faf8584552bdf2d90", + "sha256:24e954be35ad4537840f20bbc8d75320ae647d3cb4fab12cb8fcd2d55f408e76", + "sha256:26f9cc42a162faa241c82e117ac85734ae9f14343dc2df1c90c6b2181f791b22", + "sha256:28565e3dbd69fe5fe35a210067064dbb6ed5abe997079f653c19c873c3896fe6", + "sha256:2943d739715f265a2983ac43747595b6af3312d0a370614040959fd293763adf", + "sha256:2bfc39276c0e6d07c95bd1088b5003f049e986e089509f7dbd68bb7a4b1e65ac", + "sha256:2dae3b353a10c3767e0aa1c1492f2af388f1012b08117695ab3fd1f219e5814e", + "sha256:2e0854170813238f0c3131050c67cb1fb1ade75c93bf6cd156c1bd9a16095528", + "sha256:30245a8747dc90019a3c9ad9df987e0280a3ea632ad36227cde7d1d8dcba0830", + "sha256:30ed2788a6ec68743e2040ab1d16573d7d9f6e7333e45070ce9268cbc93d148c", + "sha256:32eac95bbb030b2376ffd897376c6f870222a3457f01a9ce466b9057876132f8", + "sha256:34cd48df7e1fc69222f296d8f69e3957eb7c6b5aa0709d3467184880ed7538c0", + "sha256:34dbf5fecf653c152edb75a35a8b15dfdc4549473484ee768aeb12c97983cead", + "sha256:398fb86d374dc351a4abc2e24cd15e5e14b2127f6d90ce0df3fdf2adcc55ac1b", + "sha256:3ad3a3df830f7df7e0856c2bdb54d19f5bf188bd7420985e18643b8e4d2a075f", + "sha256:3b261d593f2563299062733ae003a925420a86ff4ddda68a69097d67204e43f3", + "sha256:3c5cb6c93c94df76a879bad4b89db0104b01806d17c2b803c1316ba50962b6d6", + "sha256:3cfc9bc1e8b5667bc1f3dbe46d2f85b3f24ff7533893bdc1203058012db2c046", + "sha256:4092b660ec720d44d3ca81074280dc25c7a3718df1b6c0fe9fe36ac6ed2833e4", + "sha256:42ba8606492d76e6f9e4c7a458ed4bc712603be393259a52450345f0945da2cf", + "sha256:4a32f3dfcca4a4816373bdb6256c18c78974ebb3430e7da988516cd95b2bd6e4", + "sha256:4a82a1c10f5608e6494913faa169e213d703194bfca0aa710901f303be212414", + "sha256:4bbc0d27dfef7689285e54f2e0a224f0c7cd9d5c46d2638fabad5500b951c92f", + "sha256:4d9ed67c987bf9ac2ac684590ba3d2599cdfb0f331ee3db607f9684469b3b59d", + "sha256:4f6dd55dab77adf60b445c11f426ee5cdfa1b86f6d54cb937bfcbf09572333ab", + "sha256:50a81b2d9f188c7909e0a1084fa969bb92a788076809c437ac1ae80393f46df9", + "sha256:50b99f4d3eee6f03778fe841d6f470e6c18e744dc665156da6da3bc6e65b398d", + "sha256:5136ebe8da6a1604998a8eb96be55935aa5f7129c41cc7bddc400d48e8df43be", + "sha256:570ae3365b23d4fd8c669cb57613b1a90b2757e993588d3370ef90945dbeec4b", + "sha256:5831a377d15a626fbec10890ffebc4c6abcd37e4126737932cd780a171eabdc1", + "sha256:59c98e86c5e861032b71e6e5b65f23e6afaacea6e82483b66f1191a5021a7b4f", + "sha256:5bdeb71a610a7b801416268e500e716d0fe693fb10d809e17f0fb3dac5be5a34", + "sha256:5c1db7d366004d6c699eb08c716a63ae0a3e946d061cbebea65d7ce361950265", + "sha256:61660710b054ae52c8fc10368e91d74719eb05554b631d7f8ca93d21d2bff2e6", + "sha256:644470442beaf969df99c4e00367a817eee05f0bba5d888f1ba6fe97b5e1c102", + "sha256:64ed1a5ce5e5926727eb0f87c698c4d9a7a9f7b0953683a65e9ce2b7cc5f8e91", + "sha256:65a063970e15a4f338f14b820561cf6cdaf2839691ac0adb2474ddff9d0b8b0b", + "sha256:65b6fddf6a7b91da044f202771a38e71bbb9bf42720a406b26b25fe2256e7102", + "sha256:6af0a4b17faf26779d5caee8542a4f2cba040cea27d3bffc476cbc6ccbd4c8ee", + "sha256:70b67390e27e58876853efbb87e43c85252de2515e2887f7dd901b4fa3d21973", + "sha256:7219b1a726ced3bacecabef9bd114529bbb69477901373e800d7d0140baadc95", + "sha256:7593cb1214185a0c5b43b96effc51ce82ddc933298ee36db7dc2bd45d61b4adc", + "sha256:776f90bf2252f90a4ae838e7917638894c6356bef7265f424592e2fd1f577d05", + "sha256:79f777eaf3f5b2c6d81f9ef00d87837001d7063302503bbcbfdbf3e9bc27c96f", + "sha256:7c7cab8155f430ca460a6fc7ae8a705b34f3e279a57adb5f900eb81943ec777c", + "sha256:7cb987b199fa223ad78eebaa9fbc183d5a5944bfe568a9d6f617316ca1c1f32f", + "sha256:7ec2bb598847569ae34292f580842d37619eea3e546005042f485e15710180d5", + "sha256:80d8576b04d0824f63bf803190359c0d3bcb6e7fa63fefbd4bc0ceaa7faae38c", + "sha256:851f2bb52b5cb2f4711171ca925e0e05344a8452972a748a8a8ffdda1e1d72a7", + "sha256:8927f22ef6a16229da7f18944deac8605bdc2c0858be5184259f2f7ce7fd4459", + "sha256:8ad0515abb132f52ce9d8abd1a29681a1e65dba7b7fe13ea01e1a8db5715bf80", + "sha256:8cc37b437cba909bef06499dadd91a39c15c14225e8d8c7870020049f8a549fe", + "sha256:93d4e9a02c17813b34e4bd9f6fbf07310c140c8f74341537c24d07c1cdeb24d1", + "sha256:944249aa83dee314420c37d0f40c30a8f6dc4a3877566017b87062e53af449f4", + "sha256:9b2ed9c3b30f11cd4a3fbfc22167af7987b01b444215c2463265153fe7cf66d6", + "sha256:9c3d07ea19cd2856d9943dce37e75d69ecbb5baf93c3e4c82f73b6075c481292", + "sha256:9f592b202d77923498b32ddc5b376e5fa9ba280d3e16ed56cb8c932fe6d6a478", + "sha256:a149377d1ff766fd618500798d0d94637f66d0ae222bb6d28f41f3e15c626297", + "sha256:a17b81f22398e3e0f72bdf938e98c810286994b2bcc0a125cd5ad8fd4ea54ad7", + "sha256:a424bdedfd84454d2905a861e0d4bb947cc5bd024fdeb3600c1a97d2be0f4255", + "sha256:a6cbb73d9fc2282677e2b7a137d13da987bd0b13abd88ed27bba5534c226db06", + "sha256:a796ef39dadf9d73af05d24937644d386495e43a7d13617aa3651d836da542c8", + "sha256:aa3bca8e76f5c00ed2bb4325e0e383a547d71595926d5275d7c88175aaf7435e", + "sha256:b01ce58eec5edeededf1992d2dce63fb8565e437be12d6f139d75b15614c4d08", + "sha256:b0746d0d4535f56bbaa63a8f6da362f330804d578e66e126b226eebe76c2bf00", + "sha256:b1223b826acbef07a7f5eb9bf37247b0b580119916dca9eae19d92b1290f5855", + "sha256:b5b733694e7df22d5c049581acfc487695a6ff813322318bed8dd66f79978636", + "sha256:b6793baf4639c72a500698a49e9250b293e17ae1faf11ac1699d8141194786fe", + "sha256:b96e0e9d2d48948240b510bac81614458fc10adcd3a93240c2fd96448b4efd35", + "sha256:bc04c92d05c142889c26810a4842273deb42e66411273cab4ad09268fe69ba69", + "sha256:bdd34c57b4da51a7961beb33645646d197e41f8517801dc76b37c1441e7a4e10", + "sha256:c0379447587ee4b8f983ba183202496e86c0358f47c45612619d634d1fcd82bd", + "sha256:c3b70ed82f20d18d22eafc9bda0ea656605071762f7d31f3c5afc35c59d3393b", + "sha256:c7c45a8a1a752002b0a7c81ab3a4c5e3b6f67f9826b16fbe3943f5329f565f24", + "sha256:c8f755ff1f4ab4ca790d1d6d3229006100b301475948021b6b2757822e0d6c97", + "sha256:d1a19d6c5098f1f4e11430cd74621699453cbc534dd7ade9167e582f50814b19", + "sha256:d1ee773fb72ba024e7e3bb6ea8907fe52bccafcb5184aaced6bad995bd30ea20", + "sha256:d42eb29ba314adfd9c11234b4b646f61b0448bf9b00f14db4b317e6e4b947e77", + "sha256:d593d50815771f517d3ac4367ff716e3f3c78edae51d98e1e25791459f8848ff", + "sha256:d7910135f5de1c5c3578e61d6f4b087715b15e365f11d4fa51a9cee92988b2bd", + "sha256:d7c91747ec8dde51440dd594603158cc98abb3f7df84b2ed8a836f138285e4fb", + "sha256:db2e11507fe9cc2a722be21ccc62c1b1295398fe9724c1f14900cdc7166fc0d7", + "sha256:db5b4f8ad8607a3d612da1d4c89a84e4cf5c88f98b46365820d9babe5884ba45", + "sha256:e1956f3338c10308e2f99c2c9ff46ae412035cbcd7aaa76c39ccdb806854a247", + "sha256:e22d6cf5802cd09b674c307cc9e03870b8c37c503ebec3d25b86f2ce8c535dc7", + "sha256:e5161167b3840e9c84c80f2534ea6a099f51749d5673b662a3dd248be17c3208", + "sha256:e5e87c0eb774561c546f979342a8ff36ebee153c60a0b6c6b03ba989ceb9538c", + "sha256:e6f8191a282ef77e526f8f8f63753a437e4aa4bc78f5edd8b6b6ed0eaebd5363", + "sha256:e8f6979664ff477cd61b06bf8aba206df7b2334209815ab3b1019931dab643d6", + "sha256:ea8824ebc9a1a5c8269e8f1e3989b5a6bec876726e2f3c33ebd036cb488277f0", + "sha256:f4175fcdddf764d371ee52ec4505a40facee2533e84abf2953cda86d050cfa1f", + "sha256:fe8194f107f0fa3cabd14e9e809f174eca335993c1db72d1e74e0f496e7afe1f" ], "index": "pypi", - "version": "==3.12.3" + "version": "==3.13.0" }, "python-dateutil": { "hashes": [ @@ -665,55 +671,57 @@ }, "tinycss2": { "hashes": [ - "sha256:b2e44dd8883c360c35dd0d1b5aad0b610e5156c2cb3b33434634e539ead9d8bf", - "sha256:fe794ceaadfe3cf3e686b22155d0da5780dd0e273471a51846d0a02bc204fec8" + "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847", + "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627" ], - "markers": "python_version >= '3.6'", - "version": "==1.1.1" + "markers": "python_version >= '3.7'", + "version": "==1.2.1" }, "urllib3": { "hashes": [ - "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e", - "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997" + "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07", + "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'", - "version": "==1.26.12" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.26.18" }, "uvloop": { "hashes": [ - "sha256:0949caf774b9fcefc7c5756bacbbbd3fc4c05a6b7eebc7c7ad6f825b23998d6d", - "sha256:0ddf6baf9cf11a1a22c71487f39f15b2cf78eb5bde7e5b45fbb99e8a9d91b9e1", - "sha256:1436c8673c1563422213ac6907789ecb2b070f5939b9cbff9ef7113f2b531595", - "sha256:23609ca361a7fc587031429fa25ad2ed7242941adec948f9d10c045bfecab06b", - "sha256:2a6149e1defac0faf505406259561bc14b034cdf1d4711a3ddcdfbaa8d825a05", - "sha256:2deae0b0fb00a6af41fe60a675cec079615b01d68beb4cc7b722424406b126a8", - "sha256:307958f9fc5c8bb01fad752d1345168c0abc5d62c1b72a4a8c6c06f042b45b20", - "sha256:30babd84706115626ea78ea5dbc7dd8d0d01a2e9f9b306d24ca4ed5796c66ded", - "sha256:3378eb62c63bf336ae2070599e49089005771cc651c8769aaad72d1bd9385a7c", - "sha256:3d97672dc709fa4447ab83276f344a165075fd9f366a97b712bdd3fee05efae8", - "sha256:3db8de10ed684995a7f34a001f15b374c230f7655ae840964d51496e2f8a8474", - "sha256:3ebeeec6a6641d0adb2ea71dcfb76017602ee2bfd8213e3fcc18d8f699c5104f", - "sha256:45cea33b208971e87a31c17622e4b440cac231766ec11e5d22c76fab3bf9df62", - "sha256:6708f30db9117f115eadc4f125c2a10c1a50d711461699a0cbfaa45b9a78e376", - "sha256:68532f4349fd3900b839f588972b3392ee56042e440dd5873dfbbcd2cc67617c", - "sha256:6aafa5a78b9e62493539456f8b646f85abc7093dd997f4976bb105537cf2635e", - "sha256:7d37dccc7ae63e61f7b96ee2e19c40f153ba6ce730d8ba4d3b4e9738c1dccc1b", - "sha256:864e1197139d651a76c81757db5eb199db8866e13acb0dfe96e6fc5d1cf45fc4", - "sha256:8887d675a64cfc59f4ecd34382e5b4f0ef4ae1da37ed665adba0c2badf0d6578", - "sha256:8efcadc5a0003d3a6e887ccc1fb44dec25594f117a94e3127954c05cf144d811", - "sha256:9b09e0f0ac29eee0451d71798878eae5a4e6a91aa275e114037b27f7db72702d", - "sha256:a4aee22ece20958888eedbad20e4dbb03c37533e010fb824161b4f05e641f738", - "sha256:a5abddb3558d3f0a78949c750644a67be31e47936042d4f6c888dd6f3c95f4aa", - "sha256:c092a2c1e736086d59ac8e41f9c98f26bbf9b9222a76f21af9dfe949b99b2eb9", - "sha256:c686a47d57ca910a2572fddfe9912819880b8765e2f01dc0dd12a9bf8573e539", - "sha256:cbbe908fda687e39afd6ea2a2f14c2c3e43f2ca88e3a11964b297822358d0e6c", - "sha256:ce9f61938d7155f79d3cb2ffa663147d4a76d16e08f65e2c66b77bd41b356718", - "sha256:dbbaf9da2ee98ee2531e0c780455f2841e4675ff580ecf93fe5c48fe733b5667", - "sha256:f1e507c9ee39c61bfddd79714e4f85900656db1aec4d40c6de55648e85c2799c", - "sha256:ff3d00b70ce95adce264462c930fbaecb29718ba6563db354608f37e49e09024" + "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd", + "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec", + "sha256:13dfdf492af0aa0a0edf66807d2b465607d11c4fa48f4a1fd41cbea5b18e8e8b", + "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc", + "sha256:271718e26b3e17906b28b67314c45d19106112067205119dddbd834c2b7ce797", + "sha256:2df95fca285a9f5bfe730e51945ffe2fa71ccbfdde3b0da5772b4ee4f2e770d5", + "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2", + "sha256:34175c9fd2a4bc3adc1380e1261f60306344e3407c20a4d684fd5f3be010fa3d", + "sha256:45bf4c24c19fb8a50902ae37c5de50da81de4922af65baf760f7c0c42e1088be", + "sha256:472d61143059c84947aa8bb74eabbace30d577a03a1805b77933d6bd13ddebbd", + "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12", + "sha256:492e2c32c2af3f971473bc22f086513cedfc66a130756145a931a90c3958cb17", + "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef", + "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24", + "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428", + "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1", + "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849", + "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593", + "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd", + "sha256:6e3d4e85ac060e2342ff85e90d0c04157acb210b9ce508e784a944f852a40e67", + "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6", + "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3", + "sha256:78ab247f0b5671cc887c31d33f9b3abfb88d2614b84e4303f1a63b46c046c8bd", + "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8", + "sha256:8ca4956c9ab567d87d59d49fa3704cf29e37109ad348f2d5223c9bf761a332e7", + "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533", + "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957", + "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650", + "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e", + "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7", + "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256" ], + "index": "pypi", "markers": "sys_platform != 'win32'", - "version": "==0.17.0" + "version": "==0.19.0" }, "webencodings": { "hashes": [ @@ -724,68 +732,83 @@ }, "yarl": { "hashes": [ - "sha256:076eede537ab978b605f41db79a56cad2e7efeea2aa6e0fa8f05a26c24a034fb", - "sha256:07b21e274de4c637f3e3b7104694e53260b5fc10d51fb3ec5fed1da8e0f754e3", - "sha256:0ab5a138211c1c366404d912824bdcf5545ccba5b3ff52c42c4af4cbdc2c5035", - "sha256:0c03f456522d1ec815893d85fccb5def01ffaa74c1b16ff30f8aaa03eb21e453", - "sha256:12768232751689c1a89b0376a96a32bc7633c08da45ad985d0c49ede691f5c0d", - "sha256:19cd801d6f983918a3f3a39f3a45b553c015c5aac92ccd1fac619bd74beece4a", - "sha256:1ca7e596c55bd675432b11320b4eacc62310c2145d6801a1f8e9ad160685a231", - "sha256:1e4808f996ca39a6463f45182e2af2fae55e2560be586d447ce8016f389f626f", - "sha256:205904cffd69ae972a1707a1bd3ea7cded594b1d773a0ce66714edf17833cdae", - "sha256:20df6ff4089bc86e4a66e3b1380460f864df3dd9dccaf88d6b3385d24405893b", - "sha256:21ac44b763e0eec15746a3d440f5e09ad2ecc8b5f6dcd3ea8cb4773d6d4703e3", - "sha256:29e256649f42771829974e742061c3501cc50cf16e63f91ed8d1bf98242e5507", - "sha256:2d800b9c2eaf0684c08be5f50e52bfa2aa920e7163c2ea43f4f431e829b4f0fd", - "sha256:2d93a049d29df172f48bcb09acf9226318e712ce67374f893b460b42cc1380ae", - "sha256:31a9a04ecccd6b03e2b0e12e82131f1488dea5555a13a4d32f064e22a6003cfe", - "sha256:3d1a50e461615747dd93c099f297c1994d472b0f4d2db8a64e55b1edf704ec1c", - "sha256:449c957ffc6bc2309e1fbe67ab7d2c1efca89d3f4912baeb8ead207bb3cc1cd4", - "sha256:4a88510731cd8d4befaba5fbd734a7dd914de5ab8132a5b3dde0bbd6c9476c64", - "sha256:4c322cbaa4ed78a8aac89b2174a6df398faf50e5fc12c4c191c40c59d5e28357", - "sha256:5395da939ffa959974577eff2cbfc24b004a2fb6c346918f39966a5786874e54", - "sha256:5587bba41399854703212b87071c6d8638fa6e61656385875f8c6dff92b2e461", - "sha256:56c11efb0a89700987d05597b08a1efcd78d74c52febe530126785e1b1a285f4", - "sha256:5999c4662631cb798496535afbd837a102859568adc67d75d2045e31ec3ac497", - "sha256:59ddd85a1214862ce7c7c66457f05543b6a275b70a65de366030d56159a979f0", - "sha256:6347f1a58e658b97b0a0d1ff7658a03cb79bdbda0331603bed24dd7054a6dea1", - "sha256:6628d750041550c5d9da50bb40b5cf28a2e63b9388bac10fedd4f19236ef4957", - "sha256:6afb336e23a793cd3b6476c30f030a0d4c7539cd81649683b5e0c1b0ab0bf350", - "sha256:6c8148e0b52bf9535c40c48faebb00cb294ee577ca069d21bd5c48d302a83780", - "sha256:76577f13333b4fe345c3704811ac7509b31499132ff0181f25ee26619de2c843", - "sha256:7c0da7e44d0c9108d8b98469338705e07f4bb7dab96dbd8fa4e91b337db42548", - "sha256:7de89c8456525650ffa2bb56a3eee6af891e98f498babd43ae307bd42dca98f6", - "sha256:7ec362167e2c9fd178f82f252b6d97669d7245695dc057ee182118042026da40", - "sha256:7fce6cbc6c170ede0221cc8c91b285f7f3c8b9fe28283b51885ff621bbe0f8ee", - "sha256:85cba594433915d5c9a0d14b24cfba0339f57a2fff203a5d4fd070e593307d0b", - "sha256:8b0af1cf36b93cee99a31a545fe91d08223e64390c5ecc5e94c39511832a4bb6", - "sha256:9130ddf1ae9978abe63808b6b60a897e41fccb834408cde79522feb37fb72fb0", - "sha256:99449cd5366fe4608e7226c6cae80873296dfa0cde45d9b498fefa1de315a09e", - "sha256:9de955d98e02fab288c7718662afb33aab64212ecb368c5dc866d9a57bf48880", - "sha256:a0fb2cb4204ddb456a8e32381f9a90000429489a25f64e817e6ff94879d432fc", - "sha256:a165442348c211b5dea67c0206fc61366212d7082ba8118c8c5c1c853ea4d82e", - "sha256:ab2a60d57ca88e1d4ca34a10e9fb4ab2ac5ad315543351de3a612bbb0560bead", - "sha256:abc06b97407868ef38f3d172762f4069323de52f2b70d133d096a48d72215d28", - "sha256:af887845b8c2e060eb5605ff72b6f2dd2aab7a761379373fd89d314f4752abbf", - "sha256:b19255dde4b4f4c32e012038f2c169bb72e7f081552bea4641cab4d88bc409dd", - "sha256:b3ded839a5c5608eec8b6f9ae9a62cb22cd037ea97c627f38ae0841a48f09eae", - "sha256:c1445a0c562ed561d06d8cbc5c8916c6008a31c60bc3655cdd2de1d3bf5174a0", - "sha256:d0272228fabe78ce00a3365ffffd6f643f57a91043e119c289aaba202f4095b0", - "sha256:d0b51530877d3ad7a8d47b2fff0c8df3b8f3b8deddf057379ba50b13df2a5eae", - "sha256:d0f77539733e0ec2475ddcd4e26777d08996f8cd55d2aef82ec4d3896687abda", - "sha256:d2b8f245dad9e331540c350285910b20dd913dc86d4ee410c11d48523c4fd546", - "sha256:dd032e8422a52e5a4860e062eb84ac94ea08861d334a4bcaf142a63ce8ad4802", - "sha256:de49d77e968de6626ba7ef4472323f9d2e5a56c1d85b7c0e2a190b2173d3b9be", - "sha256:de839c3a1826a909fdbfe05f6fe2167c4ab033f1133757b5936efe2f84904c07", - "sha256:e80ed5a9939ceb6fda42811542f31c8602be336b1fb977bccb012e83da7e4936", - "sha256:ea30a42dc94d42f2ba4d0f7c0ffb4f4f9baa1b23045910c0c32df9c9902cb272", - "sha256:ea513a25976d21733bff523e0ca836ef1679630ef4ad22d46987d04b372d57fc", - "sha256:ed19b74e81b10b592084a5ad1e70f845f0aacb57577018d31de064e71ffa267a", - "sha256:f5af52738e225fcc526ae64071b7e5342abe03f42e0e8918227b38c9aa711e28", - "sha256:fae37373155f5ef9b403ab48af5136ae9851151f7aacd9926251ab26b953118b" + "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571", + "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3", + "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3", + "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c", + "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7", + "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04", + "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191", + "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea", + "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4", + "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4", + "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095", + "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e", + "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74", + "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef", + "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33", + "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde", + "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45", + "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf", + "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b", + "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac", + "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0", + "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528", + "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716", + "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb", + "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18", + "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72", + "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6", + "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582", + "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5", + "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368", + "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc", + "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9", + "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be", + "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a", + "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80", + "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8", + "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6", + "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417", + "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574", + "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59", + "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608", + "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82", + "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1", + "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3", + "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d", + "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8", + "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc", + "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac", + "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8", + "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955", + "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0", + "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367", + "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb", + "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a", + "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623", + "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2", + "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6", + "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7", + "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4", + "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051", + "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938", + "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8", + "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9", + "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3", + "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5", + "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9", + "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333", + "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185", + "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3", + "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560", + "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b", + "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7", + "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78", + "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7" ], "markers": "python_version >= '3.7'", - "version": "==1.8.1" + "version": "==1.9.2" } }, "develop": { @@ -799,11 +822,11 @@ }, "bandit": { "hashes": [ - "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2", - "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a" + "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549", + "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e" ], "index": "pypi", - "version": "==1.7.4" + "version": "==1.7.5" }, "black": { "hashes": [ @@ -836,86 +859,85 @@ }, "click": { "hashes": [ - "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", - "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" + "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" ], "markers": "python_version >= '3.7'", - "version": "==8.1.3" - }, - "colorama": { - "hashes": [ - "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da", - "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4" - ], - "index": "pypi", - "version": "==0.4.5" + "version": "==8.1.7" }, "gitdb": { "hashes": [ - "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd", - "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa" + "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", + "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b" ], - "markers": "python_version >= '3.6'", - "version": "==4.0.9" + "markers": "python_version >= '3.7'", + "version": "==4.0.11" }, "gitpython": { "hashes": [ - "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704", - "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d" + "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4", + "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a" ], "markers": "python_version >= '3.7'", - "version": "==3.1.27" + "version": "==3.1.40" }, "isort": { "hashes": [ - "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7", - "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951" + "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504", + "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6" ], - "markers": "python_version < '4.0' and python_full_version >= '3.6.1'", - "version": "==5.10.1" + "markers": "python_version >= '3.8'", + "version": "==5.12.0" }, "lazy-object-proxy": { "hashes": [ - "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7", - "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a", - "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c", - "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc", - "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f", - "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09", - "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442", - "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e", - "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029", - "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61", - "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb", - "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0", - "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35", - "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42", - "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1", - "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad", - "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443", - "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd", - "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9", - "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148", - "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38", - "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55", - "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36", - "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a", - "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b", - "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44", - "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6", - "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69", - "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4", - "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84", - "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de", - "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28", - "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c", - "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1", - "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8", - "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b", - "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb" + "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382", + "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82", + "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9", + "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494", + "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46", + "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30", + "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63", + "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4", + "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae", + "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be", + "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701", + "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd", + "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006", + "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a", + "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586", + "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8", + "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821", + "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07", + "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b", + "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171", + "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b", + "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2", + "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7", + "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4", + "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8", + "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e", + "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f", + "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda", + "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4", + "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e", + "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671", + "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11", + "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455", + "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734", + "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb", + "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59" ], - "markers": "python_version >= '3.6'", - "version": "==1.7.1" + "markers": "python_version >= '3.7'", + "version": "==1.9.0" + }, + "markdown-it-py": { + "hashes": [ + "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", + "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb" + ], + "markers": "python_version >= '3.8'", + "version": "==3.0.0" }, "mccabe": { "hashes": [ @@ -924,36 +946,53 @@ ], "version": "==0.6.1" }, + "mdurl": { + "hashes": [ + "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", + "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" + ], + "markers": "python_version >= '3.7'", + "version": "==0.1.2" + }, "mypy-extensions": { "hashes": [ - "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", - "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" + "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", + "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" ], - "version": "==0.4.3" + "markers": "python_version >= '3.5'", + "version": "==1.0.0" }, "pathspec": { "hashes": [ - "sha256:46846318467efc4556ccfd27816e004270a9eeeeb4d062ce5e6fc7a87c573f93", - "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d" + "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20", + "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3" ], "markers": "python_version >= '3.7'", - "version": "==0.10.1" + "version": "==0.11.2" }, "pbr": { "hashes": [ - "sha256:cfcc4ff8e698256fc17ea3ff796478b050852585aa5bae79ecd05b2ab7b39b9a", - "sha256:da3e18aac0a3c003e9eea1a81bd23e5a3a75d745670dcf736317b7d966887fdf" + "sha256:4a7317d5e3b17a3dccb6a8cfe67dab65b20551404c52c8ed41279fa4f0cb4cda", + "sha256:d1377122a5a00e2f940ee482999518efe16d745d423a670c27773dfbc3c9a7d9" ], "markers": "python_version >= '2.6'", - "version": "==5.10.0" + "version": "==6.0.0" }, "platformdirs": { "hashes": [ - "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788", - "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19" + "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b", + "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731" + ], + "markers": "python_version >= '3.7'", + "version": "==4.0.0" + }, + "pygments": { + "hashes": [ + "sha256:1b37f1b1e1bff2af52ecaf28cc601e2ef7077000b227a0675da25aef85784bc4", + "sha256:e45a0e74bf9c530f564ca81b8952343be986a29f6afe7f5ad95c5f06b7bdf5e8" ], "markers": "python_version >= '3.7'", - "version": "==2.5.2" + "version": "==2.17.1" }, "pylint": { "hashes": [ @@ -965,73 +1004,91 @@ }, "pyyaml": { "hashes": [ - "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", - "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", - "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", - "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", - "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", - "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", - "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", - "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", - "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", - "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", - "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", - "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", - "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", - "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", - "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", - "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", - "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", - "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", - "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", - "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", - "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", - "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", - "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", - "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", - "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", - "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", - "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", - "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", - "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", - "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", - "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", - "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", - "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", - "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", - "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", - "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", - "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", - "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", - "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", - "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" + "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", + "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", + "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", + "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", + "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", + "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", + "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", + "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", + "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", + "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", + "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", + "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", + "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", + "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", + "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", + "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", + "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", + "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", + "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", + "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", + "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", + "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", + "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", + "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", + "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", + "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", + "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", + "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", + "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", + "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", + "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", + "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", + "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", + "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", + "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", + "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", + "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", + "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", + "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", + "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", + "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", + "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", + "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", + "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", + "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", + "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", + "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", + "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", + "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", + "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" ], "markers": "python_version >= '3.6'", - "version": "==6.0" + "version": "==6.0.1" }, - "setuptools": { + "rich": { "hashes": [ - "sha256:2e24e0bec025f035a2e72cdd1961119f557d78ad331bb00ff82efb2ab8da8e82", - "sha256:7732871f4f7fa58fb6bdcaeadb0161b2bd046c85905dbaa066bdcbcc81953b57" + "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa", + "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235" ], "markers": "python_version >= '3.7'", - "version": "==65.3.0" + "version": "==13.7.0" + }, + "setuptools": { + "hashes": [ + "sha256:4c65d4f7891e5b046e9146913b87098144de2ca2128fbc10135b8556a6ddd946", + "sha256:eb03b43f23910c5fd0909cb677ad017cd9531f493d27f8b3f5316ff1fb07390e" + ], + "markers": "python_version >= '3.8'", + "version": "==69.0.0" }, "smmap": { "hashes": [ - "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94", - "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936" + "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62", + "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da" ], - "markers": "python_version >= '3.6'", - "version": "==5.0.0" + "markers": "python_version >= '3.7'", + "version": "==5.0.1" }, "stevedore": { "hashes": [ - "sha256:87e4d27fe96d0d7e4fc24f0cbe3463baae4ec51e81d95fbe60d2474636e0c7d8", - "sha256:f82cc99a1ff552310d19c379827c2c64dd9f85a38bcd5559db2470161867b786" + "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d", + "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c" ], "markers": "python_version >= '3.8'", - "version": "==4.0.0" + "version": "==5.1.0" }, "toml": { "hashes": [ diff --git a/bot.py b/bot.py index f36ecc8351..4245ce408b 100644 --- a/bot.py +++ b/bot.py @@ -21,7 +21,7 @@ from aiohttp import ClientSession, ClientResponseError from discord.ext import commands, tasks from discord.ext.commands.view import StringView -from emoji import UNICODE_EMOJI +from emoji import is_emoji from pkg_resources import parse_version @@ -623,11 +623,11 @@ async def convert_emoji(self, name: str) -> str: ctx = SimpleNamespace(bot=self, guild=self.modmail_guild) converter = commands.EmojiConverter() - if name not in UNICODE_EMOJI["en"]: + if not is_emoji(name): try: name = await converter.convert(ctx, name.strip(":")) except commands.BadArgument as e: - logger.warning("%s is not a valid emoji. %s.", name, e) + logger.warning("%s is not a valid emoji: %s", name, e) raise return name From 6fea4b61f1bfc20e2e9fcd9b235a5b39b14bb814 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:38:57 -0800 Subject: [PATCH 207/225] Updated the rest of the dependencies --- .github/workflows/lints.yml | 2 +- Pipfile | 26 +- Pipfile.lock | 490 +++++++++++++++++++----------------- pyproject.toml | 2 +- 4 files changed, 269 insertions(+), 251 deletions(-) diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index eaad52221f..b283dff078 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.9', '3.10'] + python-version: ['3.10', '3.11'] name: Python ${{ matrix.python-version }} on ubuntu-latest diff --git a/Pipfile b/Pipfile index f2590a1e2b..95c75285b5 100644 --- a/Pipfile +++ b/Pipfile @@ -4,26 +4,26 @@ url = "https://pypi.org/simple" verify_ssl = true [dev-packages] -bandit = "~=1.7.0" -black = "==22.3.0" -pylint = "~=2.9.3" -typing-extensions = "==4.2.0" +bandit = ">=1.7.5" +black = "==23.11.0" +pylint = "==3.0.2" +typing-extensions = "==4.8.0" [packages] aiohttp = "==3.9.0" colorama = "==0.4.6" "discord.py" = "==2.0.1" emoji = "==2.8.0" -isodate = "~=0.6.0" -motor = "==2.5.1" -natural = "~=0.2.0" -parsedatetime = "~=2.6" +isodate = "==0.6.1" +motor = "==3.3.2" +natural = "==0.2.0" # Why is this needed? +parsedatetime = "==2.6" pymongo = {extras = ["srv"], version = "*"} # Required by motor -python-dateutil = "~=2.8.1" -python-dotenv = "==0.20.0" -uvloop = {version = ">=0.15.2", markers = "sys_platform != 'win32'"} -lottie = {version = "==0.6.11", extras = ["pdf"]} -requests = "==2.28.1" +python-dateutil = "==2.8.2" +python-dotenv = "==1.0.0" +uvloop = {version = ">=0.19.0", markers = "sys_platform != 'win32'"} +lottie = {version = "==0.7.0", extras = ["pdf"]} +requests = "==2.31.0" [scripts] bot = "python bot.py" diff --git a/Pipfile.lock b/Pipfile.lock index 35808d048b..640ea61ff6 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "f28fd3a11b8f1550ba6731a0bc17740966b1fd98d10c1b004d416ca5b1dd3b84" + "sha256": "e883a9f5e7c62e52df23b5a710713897b06264d3a35fd4af2251ef78e7ddc82e" }, "pipfile-spec": 6, "requires": {}, @@ -133,6 +133,7 @@ "sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0", "sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b" ], + "markers": "python_version >= '3.5'", "version": "==2.7.1" }, "certifi": { @@ -198,16 +199,104 @@ "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" ], - "markers": "python_version >= '3.8'", + "markers": "python_full_version >= '3.8.0'", "version": "==1.16.0" }, "charset-normalizer": { "hashes": [ - "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", - "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" + "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", + "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087", + "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786", + "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", + "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", + "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185", + "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", + "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", + "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519", + "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898", + "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269", + "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", + "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", + "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6", + "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8", + "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a", + "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", + "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", + "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714", + "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2", + "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", + "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", + "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d", + "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", + "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", + "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", + "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", + "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d", + "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a", + "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", + "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", + "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", + "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0", + "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", + "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", + "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac", + "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25", + "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", + "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", + "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", + "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2", + "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", + "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", + "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", + "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99", + "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c", + "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", + "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811", + "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", + "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", + "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", + "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", + "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04", + "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c", + "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", + "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458", + "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", + "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99", + "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985", + "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", + "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238", + "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f", + "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d", + "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796", + "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a", + "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", + "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8", + "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", + "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5", + "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5", + "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711", + "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4", + "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", + "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c", + "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", + "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4", + "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", + "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", + "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", + "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c", + "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", + "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8", + "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", + "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b", + "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", + "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", + "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", + "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33", + "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", + "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" ], - "markers": "python_version >= '3.6'", - "version": "==2.1.1" + "markers": "python_version >= '3.7'", + "version": "==3.3.2" }, "colorama": { "hashes": [ @@ -246,7 +335,7 @@ "sha256:57c6fbaaeaaf39c891292012060beb141791735dbb4004798328fc2c467402d8", "sha256:8dcfae8c7460a2f84b4072e26f1c9f4101ca20c071649cb7c34e8b6a93d58984" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version < '4.0' and python_full_version >= '3.8.0'", "version": "==2.4.2" }, "emoji": { @@ -321,7 +410,7 @@ "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1", "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e" ], - "markers": "python_version >= '3.8'", + "markers": "python_full_version >= '3.8.0'", "version": "==1.4.0" }, "idna": { @@ -345,18 +434,18 @@ "pdf" ], "hashes": [ - "sha256:d53e96265887aa9187c7c707fd612b3d52f38da64c81ea82297783efb47f7e3f" + "sha256:a3242f8ba37051fbdd7503ecd168203a08e4af26f17be2ecca08a64af1e7d3c1" ], "index": "pypi", - "version": "==0.6.11" + "version": "==0.7.0" }, "motor": { "hashes": [ - "sha256:663473f4498f955d35db7b6f25651cb165514c247136f368b84419cb7635f6b8", - "sha256:961fdceacaae2c7236c939166f66415be81be8bbb762da528386738de3a0f509" + "sha256:6fe7e6f0c4f430b9e030b9d22549b732f7c2226af3ab71ecc309e4a1b7d19953", + "sha256:d2fc38de15f1c8058f389c1a44a4d4105c0405c48c061cd492a654496f7bc26a" ], "index": "pypi", - "version": "==2.5.1" + "version": "==3.3.2" }, "multidict": { "hashes": [ @@ -510,7 +599,7 @@ "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a", "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793" ], - "markers": "python_version >= '3.8'", + "markers": "python_full_version >= '3.8.0'", "version": "==10.1.0" }, "pycparser": { @@ -521,121 +610,94 @@ "version": "==2.21" }, "pymongo": { - "extras": [], + "extras": [ + "srv" + ], "hashes": [ - "sha256:028175dd8d2979a889153a2308e8e500b3df7d9e3fd1c33ca7fdeadf61cc87a2", - "sha256:02f0e1a75d3bc0e16c7e15daf9c56185642be055e425f3b34888fc6eb1b22401", - "sha256:0665412dce26b2318092a33bd2d2327d487c4490cfcde158d6946d39b1e28d78", - "sha256:09b9d0f5a445c7e0ddcc021b09835aa6556f0166afc498f57dfdd72cdf6f02ad", - "sha256:09de3bfc995ae8cb955abb0c9ae963c134dba1b5622be3bcc527b89b0fd4091c", - "sha256:0e5536994cf2d8488c6fd9dea71df3c4dbb3e0d2ba5e695da06d9142a29a0969", - "sha256:0f2c5a5984599a88d087a15859860579b825098b473d8c843f1979a83d159f2e", - "sha256:1037097708498bdc85f23c8798a5c46c7bce432d77d23608ff14e0d831f1a971", - "sha256:10f0fddc1d63ba3d4a4bffcc7720184c1b7efd570726ad5e2f55818da320239f", - "sha256:12721d926d43d33dd3318e58dce9b0250e8a9c6e1093fa8e09f4805193ff4b43", - "sha256:1410faa51ce835cc1234c99ec42e98ab4f3c6f50d92d86a2d4f6e11c97ee7a4e", - "sha256:16e74b9c2aca2734c7f49f00fe68d6830a30d26df60e2ace7fe40ccb92087b94", - "sha256:172db03182a22e9002157b262c1ea3b0045c73d4ff465adc152ce5b4b0e7b8d4", - "sha256:174fd1000e896d0dfbc7f6d7e6a1992a4868796c7dec31679e38218c78d6a942", - "sha256:1c2c5e2b00e2fadcd590c0b2e293d71215e98ed1cb635cfca2be4998d197e534", - "sha256:1c9d23f62a3fa7523d849c4942acc0d9ff7081ebc00c808ee7cfdc070df0687f", - "sha256:21e61a536ffed84d10376c21c13a6ed1ebefb61989a844952547c229d6aeedf3", - "sha256:222591b828de10ac90064047b5d4916953f38c38b155009c4b8b5e0d33117c2b", - "sha256:2406df90b2335371706c59b7d79e9633b81ed2a7ecd48c1faf8584552bdf2d90", - "sha256:24e954be35ad4537840f20bbc8d75320ae647d3cb4fab12cb8fcd2d55f408e76", - "sha256:26f9cc42a162faa241c82e117ac85734ae9f14343dc2df1c90c6b2181f791b22", - "sha256:28565e3dbd69fe5fe35a210067064dbb6ed5abe997079f653c19c873c3896fe6", - "sha256:2943d739715f265a2983ac43747595b6af3312d0a370614040959fd293763adf", - "sha256:2bfc39276c0e6d07c95bd1088b5003f049e986e089509f7dbd68bb7a4b1e65ac", - "sha256:2dae3b353a10c3767e0aa1c1492f2af388f1012b08117695ab3fd1f219e5814e", - "sha256:2e0854170813238f0c3131050c67cb1fb1ade75c93bf6cd156c1bd9a16095528", - "sha256:30245a8747dc90019a3c9ad9df987e0280a3ea632ad36227cde7d1d8dcba0830", - "sha256:30ed2788a6ec68743e2040ab1d16573d7d9f6e7333e45070ce9268cbc93d148c", - "sha256:32eac95bbb030b2376ffd897376c6f870222a3457f01a9ce466b9057876132f8", - "sha256:34cd48df7e1fc69222f296d8f69e3957eb7c6b5aa0709d3467184880ed7538c0", - "sha256:34dbf5fecf653c152edb75a35a8b15dfdc4549473484ee768aeb12c97983cead", - "sha256:398fb86d374dc351a4abc2e24cd15e5e14b2127f6d90ce0df3fdf2adcc55ac1b", - "sha256:3ad3a3df830f7df7e0856c2bdb54d19f5bf188bd7420985e18643b8e4d2a075f", - "sha256:3b261d593f2563299062733ae003a925420a86ff4ddda68a69097d67204e43f3", - "sha256:3c5cb6c93c94df76a879bad4b89db0104b01806d17c2b803c1316ba50962b6d6", - "sha256:3cfc9bc1e8b5667bc1f3dbe46d2f85b3f24ff7533893bdc1203058012db2c046", - "sha256:4092b660ec720d44d3ca81074280dc25c7a3718df1b6c0fe9fe36ac6ed2833e4", - "sha256:42ba8606492d76e6f9e4c7a458ed4bc712603be393259a52450345f0945da2cf", - "sha256:4a32f3dfcca4a4816373bdb6256c18c78974ebb3430e7da988516cd95b2bd6e4", - "sha256:4a82a1c10f5608e6494913faa169e213d703194bfca0aa710901f303be212414", - "sha256:4bbc0d27dfef7689285e54f2e0a224f0c7cd9d5c46d2638fabad5500b951c92f", - "sha256:4d9ed67c987bf9ac2ac684590ba3d2599cdfb0f331ee3db607f9684469b3b59d", - "sha256:4f6dd55dab77adf60b445c11f426ee5cdfa1b86f6d54cb937bfcbf09572333ab", - "sha256:50a81b2d9f188c7909e0a1084fa969bb92a788076809c437ac1ae80393f46df9", - "sha256:50b99f4d3eee6f03778fe841d6f470e6c18e744dc665156da6da3bc6e65b398d", - "sha256:5136ebe8da6a1604998a8eb96be55935aa5f7129c41cc7bddc400d48e8df43be", - "sha256:570ae3365b23d4fd8c669cb57613b1a90b2757e993588d3370ef90945dbeec4b", - "sha256:5831a377d15a626fbec10890ffebc4c6abcd37e4126737932cd780a171eabdc1", - "sha256:59c98e86c5e861032b71e6e5b65f23e6afaacea6e82483b66f1191a5021a7b4f", - "sha256:5bdeb71a610a7b801416268e500e716d0fe693fb10d809e17f0fb3dac5be5a34", - "sha256:5c1db7d366004d6c699eb08c716a63ae0a3e946d061cbebea65d7ce361950265", - "sha256:61660710b054ae52c8fc10368e91d74719eb05554b631d7f8ca93d21d2bff2e6", - "sha256:644470442beaf969df99c4e00367a817eee05f0bba5d888f1ba6fe97b5e1c102", - "sha256:64ed1a5ce5e5926727eb0f87c698c4d9a7a9f7b0953683a65e9ce2b7cc5f8e91", - "sha256:65a063970e15a4f338f14b820561cf6cdaf2839691ac0adb2474ddff9d0b8b0b", - "sha256:65b6fddf6a7b91da044f202771a38e71bbb9bf42720a406b26b25fe2256e7102", - "sha256:6af0a4b17faf26779d5caee8542a4f2cba040cea27d3bffc476cbc6ccbd4c8ee", - "sha256:70b67390e27e58876853efbb87e43c85252de2515e2887f7dd901b4fa3d21973", - "sha256:7219b1a726ced3bacecabef9bd114529bbb69477901373e800d7d0140baadc95", - "sha256:7593cb1214185a0c5b43b96effc51ce82ddc933298ee36db7dc2bd45d61b4adc", - "sha256:776f90bf2252f90a4ae838e7917638894c6356bef7265f424592e2fd1f577d05", - "sha256:79f777eaf3f5b2c6d81f9ef00d87837001d7063302503bbcbfdbf3e9bc27c96f", - "sha256:7c7cab8155f430ca460a6fc7ae8a705b34f3e279a57adb5f900eb81943ec777c", - "sha256:7cb987b199fa223ad78eebaa9fbc183d5a5944bfe568a9d6f617316ca1c1f32f", - "sha256:7ec2bb598847569ae34292f580842d37619eea3e546005042f485e15710180d5", - "sha256:80d8576b04d0824f63bf803190359c0d3bcb6e7fa63fefbd4bc0ceaa7faae38c", - "sha256:851f2bb52b5cb2f4711171ca925e0e05344a8452972a748a8a8ffdda1e1d72a7", - "sha256:8927f22ef6a16229da7f18944deac8605bdc2c0858be5184259f2f7ce7fd4459", - "sha256:8ad0515abb132f52ce9d8abd1a29681a1e65dba7b7fe13ea01e1a8db5715bf80", - "sha256:8cc37b437cba909bef06499dadd91a39c15c14225e8d8c7870020049f8a549fe", - "sha256:93d4e9a02c17813b34e4bd9f6fbf07310c140c8f74341537c24d07c1cdeb24d1", - "sha256:944249aa83dee314420c37d0f40c30a8f6dc4a3877566017b87062e53af449f4", - "sha256:9b2ed9c3b30f11cd4a3fbfc22167af7987b01b444215c2463265153fe7cf66d6", - "sha256:9c3d07ea19cd2856d9943dce37e75d69ecbb5baf93c3e4c82f73b6075c481292", - "sha256:9f592b202d77923498b32ddc5b376e5fa9ba280d3e16ed56cb8c932fe6d6a478", - "sha256:a149377d1ff766fd618500798d0d94637f66d0ae222bb6d28f41f3e15c626297", - "sha256:a17b81f22398e3e0f72bdf938e98c810286994b2bcc0a125cd5ad8fd4ea54ad7", - "sha256:a424bdedfd84454d2905a861e0d4bb947cc5bd024fdeb3600c1a97d2be0f4255", - "sha256:a6cbb73d9fc2282677e2b7a137d13da987bd0b13abd88ed27bba5534c226db06", - "sha256:a796ef39dadf9d73af05d24937644d386495e43a7d13617aa3651d836da542c8", - "sha256:aa3bca8e76f5c00ed2bb4325e0e383a547d71595926d5275d7c88175aaf7435e", - "sha256:b01ce58eec5edeededf1992d2dce63fb8565e437be12d6f139d75b15614c4d08", - "sha256:b0746d0d4535f56bbaa63a8f6da362f330804d578e66e126b226eebe76c2bf00", - "sha256:b1223b826acbef07a7f5eb9bf37247b0b580119916dca9eae19d92b1290f5855", - "sha256:b5b733694e7df22d5c049581acfc487695a6ff813322318bed8dd66f79978636", - "sha256:b6793baf4639c72a500698a49e9250b293e17ae1faf11ac1699d8141194786fe", - "sha256:b96e0e9d2d48948240b510bac81614458fc10adcd3a93240c2fd96448b4efd35", - "sha256:bc04c92d05c142889c26810a4842273deb42e66411273cab4ad09268fe69ba69", - "sha256:bdd34c57b4da51a7961beb33645646d197e41f8517801dc76b37c1441e7a4e10", - "sha256:c0379447587ee4b8f983ba183202496e86c0358f47c45612619d634d1fcd82bd", - "sha256:c3b70ed82f20d18d22eafc9bda0ea656605071762f7d31f3c5afc35c59d3393b", - "sha256:c7c45a8a1a752002b0a7c81ab3a4c5e3b6f67f9826b16fbe3943f5329f565f24", - "sha256:c8f755ff1f4ab4ca790d1d6d3229006100b301475948021b6b2757822e0d6c97", - "sha256:d1a19d6c5098f1f4e11430cd74621699453cbc534dd7ade9167e582f50814b19", - "sha256:d1ee773fb72ba024e7e3bb6ea8907fe52bccafcb5184aaced6bad995bd30ea20", - "sha256:d42eb29ba314adfd9c11234b4b646f61b0448bf9b00f14db4b317e6e4b947e77", - "sha256:d593d50815771f517d3ac4367ff716e3f3c78edae51d98e1e25791459f8848ff", - "sha256:d7910135f5de1c5c3578e61d6f4b087715b15e365f11d4fa51a9cee92988b2bd", - "sha256:d7c91747ec8dde51440dd594603158cc98abb3f7df84b2ed8a836f138285e4fb", - "sha256:db2e11507fe9cc2a722be21ccc62c1b1295398fe9724c1f14900cdc7166fc0d7", - "sha256:db5b4f8ad8607a3d612da1d4c89a84e4cf5c88f98b46365820d9babe5884ba45", - "sha256:e1956f3338c10308e2f99c2c9ff46ae412035cbcd7aaa76c39ccdb806854a247", - "sha256:e22d6cf5802cd09b674c307cc9e03870b8c37c503ebec3d25b86f2ce8c535dc7", - "sha256:e5161167b3840e9c84c80f2534ea6a099f51749d5673b662a3dd248be17c3208", - "sha256:e5e87c0eb774561c546f979342a8ff36ebee153c60a0b6c6b03ba989ceb9538c", - "sha256:e6f8191a282ef77e526f8f8f63753a437e4aa4bc78f5edd8b6b6ed0eaebd5363", - "sha256:e8f6979664ff477cd61b06bf8aba206df7b2334209815ab3b1019931dab643d6", - "sha256:ea8824ebc9a1a5c8269e8f1e3989b5a6bec876726e2f3c33ebd036cb488277f0", - "sha256:f4175fcdddf764d371ee52ec4505a40facee2533e84abf2953cda86d050cfa1f", - "sha256:fe8194f107f0fa3cabd14e9e809f174eca335993c1db72d1e74e0f496e7afe1f" + "sha256:014e7049dd019a6663747ca7dae328943e14f7261f7c1381045dfc26a04fa330", + "sha256:055f5c266e2767a88bb585d01137d9c7f778b0195d3dbf4a487ef0638be9b651", + "sha256:05c30fd35cc97f14f354916b45feea535d59060ef867446b5c3c7f9b609dd5dc", + "sha256:0634994b026336195778e5693583c060418d4ab453eff21530422690a97e1ee8", + "sha256:09c7de516b08c57647176b9fc21d929d628e35bcebc7422220c89ae40b62126a", + "sha256:107a234dc55affc5802acb3b6d83cbb8c87355b38a9457fcd8806bdeb8bce161", + "sha256:10a379fb60f1b2406ae57b8899bacfe20567918c8e9d2d545e1b93628fcf2050", + "sha256:128b1485753106c54af481789cdfea12b90a228afca0b11fb3828309a907e10e", + "sha256:1394c4737b325166a65ae7c145af1ebdb9fb153ebedd37cf91d676313e4a67b8", + "sha256:1c63e3a2e8fb815c4b1f738c284a4579897e37c3cfd95fdb199229a1ccfb638a", + "sha256:1e4ed21029d80c4f62605ab16398fe1ce093fff4b5f22d114055e7d9fbc4adb0", + "sha256:1ec71ac633b126c0775ed4604ca8f56c3540f5c21a1220639f299e7a544b55f9", + "sha256:21812453354b151200034750cd30b0140e82ec2a01fd4357390f67714a1bfbde", + "sha256:256c503a75bd71cf7fb9ebf889e7e222d49c6036a48aad5a619f98a0adf0e0d7", + "sha256:2703a9f8f5767986b4f51c259ff452cc837c5a83c8ed5f5361f6e49933743b2f", + "sha256:288c21ab9531b037f7efa4e467b33176bc73a0c27223c141b822ab4a0e66ff2a", + "sha256:2972dd1f1285866aba027eff2f4a2bbf8aa98563c2ced14cb34ee5602b36afdf", + "sha256:2973f113e079fb98515722cd728e1820282721ec9fd52830e4b73cabdbf1eb28", + "sha256:2ca0ba501898b2ec31e6c3acf90c31910944f01d454ad8e489213a156ccf1bda", + "sha256:2d2be5c9c3488fa8a70f83ed925940f488eac2837a996708d98a0e54a861f212", + "sha256:2f8c04277d879146eacda920476e93d520eff8bec6c022ac108cfa6280d84348", + "sha256:325701ae7b56daa5b0692305b7cb505ca50f80a1288abb32ff420a8a209b01ca", + "sha256:3729b8db02063da50eeb3db88a27670d85953afb9a7f14c213ac9e3dca93034b", + "sha256:3919708594b86d0f5cdc713eb6fccd3f9b9532af09ea7a5d843c933825ef56c4", + "sha256:39a1cd5d383b37285641d5a7a86be85274466ae336a61b51117155936529f9b3", + "sha256:3ec6c20385c5a58e16b1ea60c5e4993ea060540671d7d12664f385f2fb32fe79", + "sha256:47aa128be2e66abd9d1a9b0437c62499d812d291f17b55185cb4aa33a5f710a4", + "sha256:49f2af6cf82509b15093ce3569229e0d53c90ad8ae2eef940652d4cf1f81e045", + "sha256:4a0269811661ba93c472c8a60ea82640e838c2eb148d252720a09b5123f2c2fe", + "sha256:518c90bdd6e842c446d01a766b9136fec5ec6cc94f3b8c3f8b4a332786ee6b64", + "sha256:5717a308a703dda2886a5796a07489c698b442f5e409cf7dc2ac93de8d61d764", + "sha256:5802acc012bbb4bce4dff92973dff76482f30ef35dd4cb8ab5b0e06aa8f08c80", + "sha256:5e63146dbdb1eac207464f6e0cfcdb640c9c5ff0f57b754fa96fe252314a1dc6", + "sha256:6695d7136a435c1305b261a9ddb9b3ecec9863e05aab3935b96038145fd3a977", + "sha256:680fa0fc719e1a3dcb81130858368f51d83667d431924d0bcf249644bce8f303", + "sha256:6b18276f14b4b6d92e707ab6db19b938e112bd2f1dc3f9f1a628df58e4fd3f0d", + "sha256:6bafea6061d63059d8bc2ffc545e2f049221c8a4457d236c5cd6a66678673eab", + "sha256:6d6a1b1361f118e7fefa17ae3114e77f10ee1b228b20d50c47c9f351346180c8", + "sha256:747c84f4e690fbe6999c90ac97246c95d31460d890510e4a3fa61b7d2b87aa34", + "sha256:79f41576b3022c2fe9780ae3e44202b2438128a25284a8ddfa038f0785d87019", + "sha256:7b0e6361754ac596cd16bfc6ed49f69ffcd9b60b7bc4bcd3ea65c6a83475e4ff", + "sha256:7e3b0127b260d4abae7b62203c4c7ef0874c901b55155692353db19de4b18bc4", + "sha256:7fc2bb8a74dcfcdd32f89528e38dcbf70a3a6594963d60dc9595e3b35b66e414", + "sha256:806e094e9e85d8badc978af8c95b69c556077f11844655cb8cd2d1758769e521", + "sha256:81dd1308bd5630d2bb5980f00aa163b986b133f1e9ed66c66ce2a5bc3572e891", + "sha256:82e620842e12e8cb4050d2643a81c8149361cd82c0a920fa5a15dc4ca8a4000f", + "sha256:85f2cdc400ee87f5952ebf2a117488f2525a3fb2e23863a8efe3e4ee9e54e4d1", + "sha256:8ab6bcc8e424e07c1d4ba6df96f7fb963bcb48f590b9456de9ebd03b88084fe8", + "sha256:8adf014f2779992eba3b513e060d06f075f0ab2fb3ad956f413a102312f65cdf", + "sha256:9b0f98481ad5dc4cb430a60bbb8869f05505283b9ae1c62bdb65eb5e020ee8e3", + "sha256:9bea9138b0fc6e2218147e9c6ce1ff76ff8e29dc00bb1b64842bd1ca107aee9f", + "sha256:a09bfb51953930e7e838972ddf646c5d5f984992a66d79da6ba7f6a8d8a890cd", + "sha256:a0be99b599da95b7a90a918dd927b20c434bea5e1c9b3efc6a3c6cd67c23f813", + "sha256:a49aca4d961823b2846b739380c847e8964ff7ae0f0a683992b9d926054f0d6d", + "sha256:a4dc1319d0c162919ee7f4ee6face076becae2abbd351cc14f1fe70af5fb20d9", + "sha256:a8273e1abbcff1d7d29cbbb1ea7e57d38be72f1af3c597c854168508b91516c2", + "sha256:a8f7f9feecae53fa18d6a3ea7c75f9e9a1d4d20e5c3f9ce3fba83f07bcc4eee2", + "sha256:ad4f66fbb893b55f96f03020e67dcab49ffde0177c6565ccf9dec4fdf974eb61", + "sha256:af425f323fce1b07755edd783581e7283557296946212f5b1a934441718e7528", + "sha256:b14dd73f595199f4275bed4fb509277470d9b9059310537e3b3daba12b30c157", + "sha256:b4ad70d7cac4ca0c7b31444a0148bd3af01a2662fa12b1ad6f57cd4a04e21766", + "sha256:b80a4ee19b3442c57c38afa978adca546521a8822d663310b63ae2a7d7b13f3a", + "sha256:ba51129fcc510824b6ca6e2ce1c27e3e4d048b6e35d3ae6f7e517bed1b8b25ce", + "sha256:c011bd5ad03cc096f99ffcfdd18a1817354132c1331bed7a837a25226659845f", + "sha256:cc94f9fea17a5af8cf1a343597711a26b0117c0b812550d99934acb89d526ed2", + "sha256:ccd785fafa1c931deff6a7116e9a0d402d59fabe51644b0d0c268295ff847b25", + "sha256:d16a534da0e39785687b7295e2fcf9a339f4a20689024983d11afaa4657f8507", + "sha256:d3077a31633beef77d057c6523f5de7271ddef7bde5e019285b00c0cc9cac1e3", + "sha256:d603edea1ff7408638b2504905c032193b7dcee7af269802dbb35bc8c3310ed5", + "sha256:db082f728160369d9a6ed2e722438291558fc15ce06d0a7d696a8dad735c236b", + "sha256:ddef295aaf80cefb0c1606f1995899efcb17edc6b327eb6589e234e614b87756", + "sha256:e16ade71c93f6814d095d25cd6d28a90d63511ea396bd96e9ffcb886b278baaa", + "sha256:e3db7d833a7c38c317dc95b54e27f1d27012e031b45a7c24e360b53197d5f6e7", + "sha256:e5e193f89f4f8c1fe273f9a6e6df915092c9f2af6db2d1afb8bd53855025c11f", + "sha256:eb438a8bf6b695bf50d57e6a059ff09652a07968b2041178b3744ea785fcef9b", + "sha256:ebf02c32afa6b67e5861a27183dd98ed88419a94a2ab843cc145fb0bafcc5b28", + "sha256:ecd9e1fa97aa11bf67472220285775fa15e896da108f425e55d23d7540a712ce", + "sha256:ef67fedd863ffffd4adfd46d9d992b0f929c7f61a8307366d664d93517f2c78e", + "sha256:f28ae33dc5a0b9cee06e95fd420e42155d83271ab75964baf747ce959cac5f52", + "sha256:fb1c56d891f9e34303c451998ef62ba52659648bb0d75b03c5e4ac223a3342c2", + "sha256:fe03bf25fae4b95d8afe40004a321df644400fdcba4c8e5e1a19c1085b740888" ], "index": "pypi", - "version": "==3.13.0" + "version": "==4.6.0" }, "python-dateutil": { "hashes": [ @@ -647,19 +709,19 @@ }, "python-dotenv": { "hashes": [ - "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f", - "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938" + "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba", + "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a" ], "index": "pypi", - "version": "==0.20.0" + "version": "==1.0.0" }, "requests": { "hashes": [ - "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", - "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" + "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", + "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" ], "index": "pypi", - "version": "==2.28.1" + "version": "==2.31.0" }, "six": { "hashes": [ @@ -679,11 +741,11 @@ }, "urllib3": { "hashes": [ - "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07", - "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0" + "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3", + "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.26.18" + "markers": "python_full_version >= '3.8.0'", + "version": "==2.1.0" }, "uvloop": { "hashes": [ @@ -814,11 +876,11 @@ "develop": { "astroid": { "hashes": [ - "sha256:3975a0bd5373bdce166e60c851cfcbaf21ee96de80ec518c1f4cb3e94c3fb334", - "sha256:ab7f36e8a78b8e54a62028ba6beef7561db4cdb6f2a5009ecc44a6f42b5697ef" + "sha256:7d5895c9825e18079c5aeac0572bc2e4c83205c95d416e0b4fee8bc361d2d9ca", + "sha256:86b0bb7d7da0be1a7c4aedb7974e391b32d4ed89e33de6ed6902b4b15c97577e" ], - "markers": "python_version ~= '3.6'", - "version": "==2.6.6" + "markers": "python_version >= '3.8'", + "version": "==3.0.1" }, "bandit": { "hashes": [ @@ -830,32 +892,27 @@ }, "black": { "hashes": [ - "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b", - "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176", - "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09", - "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a", - "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015", - "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79", - "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb", - "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20", - "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464", - "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968", - "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82", - "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21", - "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0", - "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265", - "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b", - "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a", - "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72", - "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce", - "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0", - "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a", - "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163", - "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad", - "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d" + "sha256:250d7e60f323fcfc8ea6c800d5eba12f7967400eb6c2d21ae85ad31c204fb1f4", + "sha256:2a9acad1451632021ee0d146c8765782a0c3846e0e0ea46659d7c4f89d9b212b", + "sha256:412f56bab20ac85927f3a959230331de5614aecda1ede14b373083f62ec24e6f", + "sha256:421f3e44aa67138ab1b9bfbc22ee3780b22fa5b291e4db8ab7eee95200726b07", + "sha256:45aa1d4675964946e53ab81aeec7a37613c1cb71647b5394779e6efb79d6d187", + "sha256:4c44b7211a3a0570cc097e81135faa5f261264f4dfaa22bd5ee2875a4e773bd6", + "sha256:4c68855825ff432d197229846f971bc4d6666ce90492e5b02013bcaca4d9ab05", + "sha256:5133f5507007ba08d8b7b263c7aa0f931af5ba88a29beacc4b2dc23fcefe9c06", + "sha256:54caaa703227c6e0c87b76326d0862184729a69b73d3b7305b6288e1d830067e", + "sha256:58e5f4d08a205b11800332920e285bd25e1a75c54953e05502052738fe16b3b5", + "sha256:698c1e0d5c43354ec5d6f4d914d0d553a9ada56c85415700b81dc90125aac244", + "sha256:6c1cac07e64433f646a9a838cdc00c9768b3c362805afc3fce341af0e6a9ae9f", + "sha256:760415ccc20f9e8747084169110ef75d545f3b0932ee21368f63ac0fee86b221", + "sha256:7f622b6822f02bfaf2a5cd31fdb7cd86fcf33dab6ced5185c35f5db98260b055", + "sha256:cf57719e581cfd48c4efe28543fea3d139c6b6f1238b3f0102a9c73992cbb479", + "sha256:d136ef5b418c81660ad847efe0e55c58c8208b77a57a28a503a5f345ccf01394", + "sha256:dbea0bb8575c6b6303cc65017b46351dc5953eea5c0a59d7b7e3a2d2f433a911", + "sha256:fc7f6a44d52747e65a02558e1d807c82df1d66ffa80a601862040a43ec2e3142" ], "index": "pypi", - "version": "==22.3.0" + "version": "==23.11.0" }, "click": { "hashes": [ @@ -865,6 +922,14 @@ "markers": "python_version >= '3.7'", "version": "==8.1.7" }, + "dill": { + "hashes": [ + "sha256:76b122c08ef4ce2eedcd4d1abd8e641114bfc6c2867f49f3c41facf65bf19f5e", + "sha256:cc1c8b182eb3013e24bd475ff2e9295af86c1a38eb1aff128dac8962a9ce3c03" + ], + "markers": "python_version < '3.11'", + "version": "==0.3.7" + }, "gitdb": { "hashes": [ "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", @@ -889,48 +954,6 @@ "markers": "python_version >= '3.8'", "version": "==5.12.0" }, - "lazy-object-proxy": { - "hashes": [ - "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382", - "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82", - "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9", - "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494", - "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46", - "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30", - "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63", - "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4", - "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae", - "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be", - "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701", - "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd", - "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006", - "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a", - "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586", - "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8", - "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821", - "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07", - "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b", - "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171", - "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b", - "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2", - "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7", - "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4", - "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8", - "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e", - "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f", - "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda", - "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4", - "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e", - "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671", - "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11", - "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455", - "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734", - "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb", - "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59" - ], - "markers": "python_version >= '3.7'", - "version": "==1.9.0" - }, "markdown-it-py": { "hashes": [ "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", @@ -941,10 +964,11 @@ }, "mccabe": { "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", + "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" ], - "version": "==0.6.1" + "markers": "python_version >= '3.6'", + "version": "==0.7.0" }, "mdurl": { "hashes": [ @@ -962,6 +986,14 @@ "markers": "python_version >= '3.5'", "version": "==1.0.0" }, + "packaging": { + "hashes": [ + "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", + "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" + ], + "markers": "python_version >= '3.7'", + "version": "==23.2" + }, "pathspec": { "hashes": [ "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20", @@ -996,11 +1028,11 @@ }, "pylint": { "hashes": [ - "sha256:2e1a0eb2e8ab41d6b5dbada87f066492bb1557b12b76c47c2ee8aa8a11186594", - "sha256:8b838c8983ee1904b2de66cce9d0b96649a91901350e956d78f289c3bc87b48e" + "sha256:0d4c286ef6d2f66c8bfb527a7f8a629009e42c99707dec821a03e1b51a4c1496", + "sha256:60ed5f3a9ff8b61839ff0348b3624ceeb9e6c2a92c514d81c9cc273da3b6bcda" ], "index": "pypi", - "version": "==2.9.6" + "version": "==3.0.2" }, "pyyaml": { "hashes": [ @@ -1066,14 +1098,6 @@ "markers": "python_version >= '3.7'", "version": "==13.7.0" }, - "setuptools": { - "hashes": [ - "sha256:4c65d4f7891e5b046e9146913b87098144de2ca2128fbc10135b8556a6ddd946", - "sha256:eb03b43f23910c5fd0909cb677ad017cd9531f493d27f8b3f5316ff1fb07390e" - ], - "markers": "python_version >= '3.8'", - "version": "==69.0.0" - }, "smmap": { "hashes": [ "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62", @@ -1090,14 +1114,6 @@ "markers": "python_version >= '3.8'", "version": "==5.1.0" }, - "toml": { - "hashes": [ - "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", - "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" - ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.10.2" - }, "tomli": { "hashes": [ "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", @@ -1106,19 +1122,21 @@ "markers": "python_version < '3.11'", "version": "==2.0.1" }, - "typing-extensions": { + "tomlkit": { "hashes": [ - "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708", - "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376" + "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4", + "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba" ], - "index": "pypi", - "version": "==4.2.0" + "markers": "python_version >= '3.7'", + "version": "==0.12.3" }, - "wrapt": { + "typing-extensions": { "hashes": [ - "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" + "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0", + "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef" ], - "version": "==1.12.1" + "index": "pypi", + "version": "==4.8.0" } } } diff --git a/pyproject.toml b/pyproject.toml index 751cc5a75a..389c24e3d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.black] line-length = "110" -target-version = ['py39'] +target-version = ['py310'] include = '\.pyi?$' extend-exclude = ''' ( From 27a16fe3ca3826ed402f64950e2d81148dac9f18 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 20 Nov 2023 13:45:09 -0800 Subject: [PATCH 208/225] Bump dpy version to 2.3.2 --- Pipfile | 2 +- Pipfile.lock | 40 ++++++++++++++++++++-------------------- bot.py | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Pipfile b/Pipfile index 95c75285b5..a0c9daa37e 100644 --- a/Pipfile +++ b/Pipfile @@ -12,7 +12,7 @@ typing-extensions = "==4.8.0" [packages] aiohttp = "==3.9.0" colorama = "==0.4.6" -"discord.py" = "==2.0.1" +"discord.py" = "==2.3.2" emoji = "==2.8.0" isodate = "==0.6.1" motor = "==3.3.2" diff --git a/Pipfile.lock b/Pipfile.lock index 640ea61ff6..d420515b19 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "e883a9f5e7c62e52df23b5a710713897b06264d3a35fd4af2251ef78e7ddc82e" + "sha256": "c1d663437fd62a76081e36be69c204bef95a30908d9eac1f3df8863ccbd4d383" }, "pipfile-spec": 6, "requires": {}, @@ -199,7 +199,7 @@ "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" ], - "markers": "python_full_version >= '3.8.0'", + "markers": "python_version >= '3.8'", "version": "==1.16.0" }, "charset-normalizer": { @@ -324,18 +324,18 @@ }, "discord.py": { "hashes": [ - "sha256:309146476e986cb8faf038cd5d604d4b3834ef15c2d34df697ce5064bf5cd779", - "sha256:aeb186348bf011708b085b2715cf92bbb72c692eb4f59c4c0b488130cc4c4b7e" + "sha256:4560f70f2eddba7e83370ecebd237ac09fbb4980dc66507482b0c0e5b8f76b9c", + "sha256:9da4679fc3cb10c64b388284700dc998663e0e57328283bbfcfc2525ec5960a6" ], "index": "pypi", - "version": "==2.0.1" + "version": "==2.3.2" }, "dnspython": { "hashes": [ "sha256:57c6fbaaeaaf39c891292012060beb141791735dbb4004798328fc2c467402d8", "sha256:8dcfae8c7460a2f84b4072e26f1c9f4101ca20c071649cb7c34e8b6a93d58984" ], - "markers": "python_version < '4.0' and python_full_version >= '3.8.0'", + "markers": "python_version >= '3.8' and python_version < '4.0'", "version": "==2.4.2" }, "emoji": { @@ -410,7 +410,7 @@ "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1", "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e" ], - "markers": "python_full_version >= '3.8.0'", + "markers": "python_version >= '3.8'", "version": "==1.4.0" }, "idna": { @@ -599,7 +599,7 @@ "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a", "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793" ], - "markers": "python_full_version >= '3.8.0'", + "markers": "python_version >= '3.8'", "version": "==10.1.0" }, "pycparser": { @@ -744,7 +744,7 @@ "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3", "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54" ], - "markers": "python_full_version >= '3.8.0'", + "markers": "python_version >= '3.8'", "version": "==2.1.0" }, "uvloop": { @@ -919,7 +919,7 @@ "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==8.1.7" }, "dill": { @@ -935,7 +935,7 @@ "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==4.0.11" }, "gitpython": { @@ -943,7 +943,7 @@ "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4", "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==3.1.40" }, "isort": { @@ -975,7 +975,7 @@ "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==0.1.2" }, "mypy-extensions": { @@ -991,7 +991,7 @@ "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==23.2" }, "pathspec": { @@ -999,7 +999,7 @@ "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20", "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==0.11.2" }, "pbr": { @@ -1015,7 +1015,7 @@ "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b", "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==4.0.0" }, "pygments": { @@ -1023,7 +1023,7 @@ "sha256:1b37f1b1e1bff2af52ecaf28cc601e2ef7077000b227a0675da25aef85784bc4", "sha256:e45a0e74bf9c530f564ca81b8952343be986a29f6afe7f5ad95c5f06b7bdf5e8" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==2.17.1" }, "pylint": { @@ -1095,7 +1095,7 @@ "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa", "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==13.7.0" }, "smmap": { @@ -1103,7 +1103,7 @@ "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62", "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==5.0.1" }, "stevedore": { @@ -1127,7 +1127,7 @@ "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4", "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==0.12.3" }, "typing-extensions": { diff --git a/bot.py b/bot.py index 4245ce408b..49787f5005 100644 --- a/bot.py +++ b/bot.py @@ -1793,7 +1793,7 @@ def main(): sys.exit(0) # check discord version - discord_version = "2.0.1" + discord_version = "2.3.2" if discord.__version__ != discord_version: logger.error( "Dependencies are not updated, run pipenv install. discord.py version expected %s, received %s", From 9464c5db97c5ce134a86333879d31ac06fe255c6 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:02:21 -0800 Subject: [PATCH 209/225] Fixed compat with MissingRequiredArgument requiring additional param --- bot.py | 7 ++++--- cogs/modmail.py | 7 +++---- cogs/utility.py | 9 ++++----- core/thread.py | 5 +++-- core/utils.py | 10 ++++++++++ 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/bot.py b/bot.py index 49787f5005..3a4cc8a3d8 100644 --- a/bot.py +++ b/bot.py @@ -1746,9 +1746,10 @@ def format_channel_name(self, author, exclude_channel=None, force_null=False): if force_null: name = "null" - name = new_name = ( - "".join(l for l in name if l not in string.punctuation and l.isprintable()) or "null" - ) + f"-{author.discriminator}" + name = "".join(l for l in name if l not in string.punctuation and l.isprintable()) or "null" + if author.discriminator != "0": + name += f"-{author.discriminator}" + new_name = name counter = 1 existed = set(c.name for c in guild.text_channels if c != exclude_channel) diff --git a/cogs/modmail.py b/cogs/modmail.py index 445015e4de..ac9ab65a58 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -3,7 +3,6 @@ from datetime import datetime, timezone from itertools import zip_longest from typing import Optional, Union, List, Tuple, Literal -from types import SimpleNamespace import discord from discord.ext import commands @@ -1164,7 +1163,7 @@ async def logs(self, ctx, *, user: User = None): if not user: thread = ctx.thread if not thread: - raise commands.MissingRequiredArgument(SimpleNamespace(name="member")) + raise commands.MissingRequiredArgument(DummyParam("user")) user = thread.recipient or await self.bot.get_or_fetch_user(thread.id) default_avatar = "https://cdn.discordapp.com/embed/avatars/0.png" @@ -1839,7 +1838,7 @@ async def block( if thread: user_or_role = thread.recipient elif after is None: - raise commands.MissingRequiredArgument(SimpleNamespace(name="user or role")) + raise commands.MissingRequiredArgument(DummyParam("user or role")) else: raise commands.BadArgument(f'User or role "{after.arg}" not found.') @@ -1919,7 +1918,7 @@ async def unblock(self, ctx, *, user_or_role: Union[User, Role] = None): if thread: user_or_role = thread.recipient else: - raise commands.MissingRequiredArgument(SimpleNamespace(name="user")) + raise commands.MissingRequiredArgument(DummyParam("user or role")) mention = getattr(user_or_role, "mention", f"`{user_or_role.id}`") name = getattr(user_or_role, "name", f"`{user_or_role.id}`") diff --git a/cogs/utility.py b/cogs/utility.py index 579c4a7e4e..126b6f785f 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -11,7 +11,6 @@ from json import JSONDecodeError, loads from subprocess import PIPE from textwrap import indent -from types import SimpleNamespace from typing import Union import discord @@ -30,7 +29,7 @@ UnseenFormatter, getLogger, ) -from core.utils import trigger_typing, truncate +from core.utils import trigger_typing, truncate, DummyParam from core.paginator import EmbedPaginatorSession, MessagePaginatorSession @@ -522,12 +521,12 @@ async def activity(self, ctx, activity_type: str.lower, *, message: str = ""): return await ctx.send(embed=embed) if not message: - raise commands.MissingRequiredArgument(SimpleNamespace(name="message")) + raise commands.MissingRequiredArgument(DummyParam("message")) try: activity_type = ActivityType[activity_type] except KeyError: - raise commands.MissingRequiredArgument(SimpleNamespace(name="activity")) + raise commands.MissingRequiredArgument(DummyParam("activity")) activity, _ = await self.set_presence(activity_type=activity_type, activity_message=message) @@ -572,7 +571,7 @@ async def status(self, ctx, *, status_type: str.lower): try: status = Status[status_type] except KeyError: - raise commands.MissingRequiredArgument(SimpleNamespace(name="status")) + raise commands.MissingRequiredArgument(DummyParam("status")) _, status = await self.set_presence(status=status) diff --git a/core/thread.py b/core/thread.py index 09c5df46ee..0222eb0102 100644 --- a/core/thread.py +++ b/core/thread.py @@ -32,6 +32,7 @@ AcceptButton, DenyButton, ConfirmThreadCreationView, + DummyParam, ) logger = getLogger(__name__) @@ -800,7 +801,7 @@ async def note( self, message: discord.Message, persistent=False, thread_creation=False ) -> discord.Message: if not message.content and not message.attachments: - raise MissingRequiredArgument(SimpleNamespace(name="msg")) + raise MissingRequiredArgument(DummyParam("msg")) msg = await self.send( message, @@ -821,7 +822,7 @@ async def reply( ) -> typing.Tuple[typing.List[discord.Message], discord.Message]: """Returns List[user_dm_msg] and thread_channel_msg""" if not message.content and not message.attachments: - raise MissingRequiredArgument(SimpleNamespace(name="msg")) + raise MissingRequiredArgument(DummyParam("msg")) if not any(g.get_member(self.id) for g in self.bot.guilds): return await message.channel.send( embed=discord.Embed( diff --git a/core/utils.py b/core/utils.py index 0e9f090d12..d5940d1c2b 100644 --- a/core/utils.py +++ b/core/utils.py @@ -42,6 +42,7 @@ "AcceptButton", "DenyButton", "ConfirmThreadCreationView", + "DummyParam", ] @@ -588,3 +589,12 @@ class ConfirmThreadCreationView(discord.ui.View): def __init__(self): super().__init__(timeout=20) self.value = None + + +class DummyParam: + """ + A dummy parameter that can be used for MissingRequiredArgument. + """ + def __init__(self, name): + self.name = name + self.displayed_name = name From ef349e87e62851881a82fc652110f4ec4d7307ef Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:05:47 -0800 Subject: [PATCH 210/225] black format + update changelog --- CHANGELOG.md | 3 +++ core/utils.py | 1 + 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f79f46c491..03f3e09241 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ however, insignificant breaking changes do not guarantee a major version bump, s # [UNRELEASED] +Drops support for Python 3.9. Python 3.10 and Python 3.11 are now the only supported versions. + ### Fixed - `?alias make/create` as aliases to `?alias add`. This improves continuity between the bot and its command structure. ([PR #3195](https://github.com/kyb3r/modmail/pull/3195)) - Loading the blocked list with the `?blocked` command takes a long time when the list is large. ([PR #3242](https://github.com/kyb3r/modmail/pull/3242)) @@ -29,6 +31,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s ### Changed - Repo moved to https://github.com/modmail-dev/modmail. +- Channel name no longer shows `-0` if the user has migrated to the new username system. - Guild icons in embed footers and author urls now have a fixed size of 128. ([PR #3261](https://github.com/modmail-dev/modmail/pull/3261)) - Discord.py internal logging is now enabled by default. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) - The confirm-thread-creation dialog now uses buttons instead of reactions. ([PR #3273](https://github.com/modmail-dev/Modmail/pull/3273)) diff --git a/core/utils.py b/core/utils.py index d5940d1c2b..b50ed3d0fc 100644 --- a/core/utils.py +++ b/core/utils.py @@ -595,6 +595,7 @@ class DummyParam: """ A dummy parameter that can be used for MissingRequiredArgument. """ + def __init__(self, name): self.name = name self.displayed_name = name From 7231a5d48aa8273f063b50a1b2bd1bf8f4c547d1 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:06:25 -0800 Subject: [PATCH 211/225] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03f3e09241..d0ca324a29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ Drops support for Python 3.9. Python 3.10 and Python 3.11 are now the only suppo ### Internal - Renamed `Bot.log_file_name` to `Bot.log_file_path`. Log files are now created at `temp/logs/modmail.log`. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) - `ConfigManager.get` no longer accepts two positional arguments: the `convert` argument is now keyword-only. +- Various dependencies have been updated to their latest versions. # v4.0.2 From 55f9ba89049506cf21abace145d869422234caea Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:13:35 -0800 Subject: [PATCH 212/225] Remove some more discriminator references --- cogs/modmail.py | 12 +++++++----- core/utils.py | 6 +++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/cogs/modmail.py b/cogs/modmail.py index ac9ab65a58..ee27806177 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -729,8 +729,9 @@ def format_log_embeds(self, logs, avatar_url): f"{self.bot.config['log_url'].strip('/')}{'/' + prefix if prefix else ''}/{entry['key']}" ) - username = entry["recipient"]["name"] + "#" - username += entry["recipient"]["discriminator"] + username = entry["recipient"]["name"] + if entry["recipient"]["discriminator"] != "0": + username += "#" + entry["recipient"]["discriminator"] embed = discord.Embed(color=self.bot.main_color, timestamp=created_at) embed.set_author(name=f"{title} - {username}", icon_url=avatar_url, url=log_url) @@ -1855,7 +1856,7 @@ async def block( ) return await ctx.send(embed=embed) - reason = f"by {escape_markdown(ctx.author.name)}#{ctx.author.discriminator}" + reason = f"by {escape_markdown(str(ctx.author))}" if after is not None: if "%" in reason: @@ -2054,11 +2055,12 @@ async def repair(self, ctx): # match username from channel name # username-1234, username-1234_1, username-1234_2 - m = re.match(r"^(.+)-(\d{4})(?:_\d+)?$", ctx.channel.name) + m = re.match(r"^(.+?)(?:-(\d{4}))?(?:_\d+)?$", ctx.channel.name) if m is not None: users = set( filter( - lambda member: member.name == m.group(1) and member.discriminator == m.group(2), + lambda member: member.name == m.group(1) + and (member.discriminator == "0" or member.discriminator == m.group(2)), ctx.guild.members, ) ) diff --git a/core/utils.py b/core/utils.py index b50ed3d0fc..e25bbf2009 100644 --- a/core/utils.py +++ b/core/utils.py @@ -127,7 +127,11 @@ def format_preview(messages: typing.List[typing.Dict[str, typing.Any]]): continue author = message["author"] content = str(message["content"]).replace("\n", " ") - name = author["name"] + "#" + str(author["discriminator"]) + + name = author["name"] + discriminator = str(author["discriminator"]) + if discriminator != "0": + name += "#" + discriminator prefix = "[M]" if author["mod"] else "[R]" out += truncate(f"`{prefix} {name}:` {content}", max=75) + "\n" From 5482e94374da73161b3ba33df25de089f2950cc3 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:19:31 -0800 Subject: [PATCH 213/225] Remove pkg_resources and replaced with packaging, updated requirements.txt --- Pipfile | 1 + Pipfile.lock | 198 ++++++++++++++++++++++++++--------------------- bot.py | 6 +- cogs/plugins.py | 6 +- cogs/utility.py | 11 +-- requirements.txt | 59 +++++++------- 6 files changed, 152 insertions(+), 129 deletions(-) diff --git a/Pipfile b/Pipfile index a0c9daa37e..98e60935be 100644 --- a/Pipfile +++ b/Pipfile @@ -17,6 +17,7 @@ emoji = "==2.8.0" isodate = "==0.6.1" motor = "==3.3.2" natural = "==0.2.0" # Why is this needed? +packaging = "==23.2" parsedatetime = "==2.6" pymongo = {extras = ["srv"], version = "*"} # Required by motor python-dateutil = "==2.8.2" diff --git a/Pipfile.lock b/Pipfile.lock index d420515b19..2892217178 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "c1d663437fd62a76081e36be69c204bef95a30908d9eac1f3df8863ccbd4d383" + "sha256": "2744146f249e9fd303c9cba7df1fff03a597cf8a141075c2d4d51ff80efbee7b" }, "pipfile-spec": 6, "requires": {}, @@ -534,6 +534,14 @@ "index": "pypi", "version": "==0.2.0" }, + "packaging": { + "hashes": [ + "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", + "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" + ], + "index": "pypi", + "version": "==23.2" + }, "parsedatetime": { "hashes": [ "sha256:4cb368fbb18a0b7231f4d76119165451c8d2e35951455dfee97c62a87b04d455", @@ -794,83 +802,99 @@ }, "yarl": { "hashes": [ - "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571", - "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3", - "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3", - "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c", - "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7", - "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04", - "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191", - "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea", - "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4", - "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4", - "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095", - "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e", - "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74", - "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef", - "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33", - "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde", - "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45", - "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf", - "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b", - "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac", - "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0", - "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528", - "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716", - "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb", - "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18", - "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72", - "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6", - "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582", - "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5", - "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368", - "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc", - "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9", - "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be", - "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a", - "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80", - "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8", - "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6", - "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417", - "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574", - "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59", - "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608", - "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82", - "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1", - "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3", - "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d", - "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8", - "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc", - "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac", - "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8", - "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955", - "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0", - "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367", - "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb", - "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a", - "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623", - "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2", - "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6", - "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7", - "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4", - "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051", - "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938", - "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8", - "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9", - "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3", - "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5", - "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9", - "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333", - "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185", - "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3", - "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560", - "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b", - "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7", - "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78", - "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7" + "sha256:09c19e5f4404574fcfb736efecf75844ffe8610606f3fccc35a1515b8b6712c4", + "sha256:0ab5baaea8450f4a3e241ef17e3d129b2143e38a685036b075976b9c415ea3eb", + "sha256:0d155a092bf0ebf4a9f6f3b7a650dc5d9a5bbb585ef83a52ed36ba46f55cc39d", + "sha256:126638ab961633f0940a06e1c9d59919003ef212a15869708dcb7305f91a6732", + "sha256:1a0a4f3aaa18580038cfa52a7183c8ffbbe7d727fe581300817efc1e96d1b0e9", + "sha256:1d93461e2cf76c4796355494f15ffcb50a3c198cc2d601ad8d6a96219a10c363", + "sha256:26a1a8443091c7fbc17b84a0d9f38de34b8423b459fb853e6c8cdfab0eacf613", + "sha256:271d63396460b6607b588555ea27a1a02b717ca2e3f2cf53bdde4013d7790929", + "sha256:28a108cb92ce6cf867690a962372996ca332d8cda0210c5ad487fe996e76b8bb", + "sha256:29beac86f33d6c7ab1d79bd0213aa7aed2d2f555386856bb3056d5fdd9dab279", + "sha256:2c757f64afe53a422e45e3e399e1e3cf82b7a2f244796ce80d8ca53e16a49b9f", + "sha256:2dad8166d41ebd1f76ce107cf6a31e39801aee3844a54a90af23278b072f1ccf", + "sha256:2dc72e891672343b99db6d497024bf8b985537ad6c393359dc5227ef653b2f17", + "sha256:2f3c8822bc8fb4a347a192dd6a28a25d7f0ea3262e826d7d4ef9cc99cd06d07e", + "sha256:32435d134414e01d937cd9d6cc56e8413a8d4741dea36af5840c7750f04d16ab", + "sha256:3cfa4dbe17b2e6fca1414e9c3bcc216f6930cb18ea7646e7d0d52792ac196808", + "sha256:3d5434b34100b504aabae75f0622ebb85defffe7b64ad8f52b8b30ec6ef6e4b9", + "sha256:4003f380dac50328c85e85416aca6985536812c082387255c35292cb4b41707e", + "sha256:44e91a669c43f03964f672c5a234ae0d7a4d49c9b85d1baa93dec28afa28ffbd", + "sha256:4a14907b597ec55740f63e52d7fee0e9ee09d5b9d57a4f399a7423268e457b57", + "sha256:4ce77d289f8d40905c054b63f29851ecbfd026ef4ba5c371a158cfe6f623663e", + "sha256:4d6d74a97e898c1c2df80339aa423234ad9ea2052f66366cef1e80448798c13d", + "sha256:51382c72dd5377861b573bd55dcf680df54cea84147c8648b15ac507fbef984d", + "sha256:525cd69eff44833b01f8ef39aa33a9cc53a99ff7f9d76a6ef6a9fb758f54d0ff", + "sha256:53ec65f7eee8655bebb1f6f1607760d123c3c115a324b443df4f916383482a67", + "sha256:5f74b015c99a5eac5ae589de27a1201418a5d9d460e89ccb3366015c6153e60a", + "sha256:6280353940f7e5e2efaaabd686193e61351e966cc02f401761c4d87f48c89ea4", + "sha256:632c7aeb99df718765adf58eacb9acb9cbc555e075da849c1378ef4d18bf536a", + "sha256:6465d36381af057d0fab4e0f24ef0e80ba61f03fe43e6eeccbe0056e74aadc70", + "sha256:66a6dbf6ca7d2db03cc61cafe1ee6be838ce0fbc97781881a22a58a7c5efef42", + "sha256:6d350388ba1129bc867c6af1cd17da2b197dff0d2801036d2d7d83c2d771a682", + "sha256:7217234b10c64b52cc39a8d82550342ae2e45be34f5bff02b890b8c452eb48d7", + "sha256:721ee3fc292f0d069a04016ef2c3a25595d48c5b8ddc6029be46f6158d129c92", + "sha256:72a57b41a0920b9a220125081c1e191b88a4cdec13bf9d0649e382a822705c65", + "sha256:73cc83f918b69110813a7d95024266072d987b903a623ecae673d1e71579d566", + "sha256:778df71c8d0c8c9f1b378624b26431ca80041660d7be7c3f724b2c7a6e65d0d6", + "sha256:79e1df60f7c2b148722fb6cafebffe1acd95fd8b5fd77795f56247edaf326752", + "sha256:7c86d0d0919952d05df880a1889a4f0aeb6868e98961c090e335671dea5c0361", + "sha256:7eaf13af79950142ab2bbb8362f8d8d935be9aaf8df1df89c86c3231e4ff238a", + "sha256:828235a2a169160ee73a2fcfb8a000709edf09d7511fccf203465c3d5acc59e4", + "sha256:8535e111a064f3bdd94c0ed443105934d6f005adad68dd13ce50a488a0ad1bf3", + "sha256:88d2c3cc4b2f46d1ba73d81c51ec0e486f59cc51165ea4f789677f91a303a9a7", + "sha256:8a2538806be846ea25e90c28786136932ec385c7ff3bc1148e45125984783dc6", + "sha256:8dab30b21bd6fb17c3f4684868c7e6a9e8468078db00f599fb1c14e324b10fca", + "sha256:8f18a7832ff85dfcd77871fe677b169b1bc60c021978c90c3bb14f727596e0ae", + "sha256:946db4511b2d815979d733ac6a961f47e20a29c297be0d55b6d4b77ee4b298f6", + "sha256:96758e56dceb8a70f8a5cff1e452daaeff07d1cc9f11e9b0c951330f0a2396a7", + "sha256:9a172c3d5447b7da1680a1a2d6ecdf6f87a319d21d52729f45ec938a7006d5d8", + "sha256:9a5211de242754b5e612557bca701f39f8b1a9408dff73c6db623f22d20f470e", + "sha256:9df9a0d4c5624790a0dea2e02e3b1b3c69aed14bcb8650e19606d9df3719e87d", + "sha256:aa4643635f26052401750bd54db911b6342eb1a9ac3e74f0f8b58a25d61dfe41", + "sha256:aed37db837ecb5962469fad448aaae0f0ee94ffce2062cf2eb9aed13328b5196", + "sha256:af52725c7c39b0ee655befbbab5b9a1b209e01bb39128dce0db226a10014aacc", + "sha256:b0b8c06afcf2bac5a50b37f64efbde978b7f9dc88842ce9729c020dc71fae4ce", + "sha256:b61e64b06c3640feab73fa4ff9cb64bd8182de52e5dc13038e01cfe674ebc321", + "sha256:b7831566595fe88ba17ea80e4b61c0eb599f84c85acaa14bf04dd90319a45b90", + "sha256:b8bc5b87a65a4e64bc83385c05145ea901b613d0d3a434d434b55511b6ab0067", + "sha256:b8d51817cf4b8d545963ec65ff06c1b92e5765aa98831678d0e2240b6e9fd281", + "sha256:b9f9cafaf031c34d95c1528c16b2fa07b710e6056b3c4e2e34e9317072da5d1a", + "sha256:bb72d2a94481e7dc7a0c522673db288f31849800d6ce2435317376a345728225", + "sha256:c25ec06e4241e162f5d1f57c370f4078797ade95c9208bd0c60f484834f09c96", + "sha256:c405d482c320a88ab53dcbd98d6d6f32ada074f2d965d6e9bf2d823158fa97de", + "sha256:c4472fe53ebf541113e533971bd8c32728debc4c6d8cc177f2bff31d011ec17e", + "sha256:c4b1efb11a8acd13246ffb0bee888dd0e8eb057f8bf30112e3e21e421eb82d4a", + "sha256:c5f3faeb8100a43adf3e7925d556801d14b5816a0ac9e75e22948e787feec642", + "sha256:c6f034386e5550b5dc8ded90b5e2ff7db21f0f5c7de37b6efc5dac046eb19c10", + "sha256:c99ddaddb2fbe04953b84d1651149a0d85214780e4d0ee824e610ab549d98d92", + "sha256:ca6b66f69e30f6e180d52f14d91ac854b8119553b524e0e28d5291a724f0f423", + "sha256:cccdc02e46d2bd7cb5f38f8cc3d9db0d24951abd082b2f242c9e9f59c0ab2af3", + "sha256:cd49a908cb6d387fc26acee8b7d9fcc9bbf8e1aca890c0b2fdfd706057546080", + "sha256:cf7a4e8de7f1092829caef66fd90eaf3710bc5efd322a816d5677b7664893c93", + "sha256:cfd77e8e5cafba3fb584e0f4b935a59216f352b73d4987be3af51f43a862c403", + "sha256:d34c4f80956227f2686ddea5b3585e109c2733e2d4ef12eb1b8b4e84f09a2ab6", + "sha256:d61a0ca95503867d4d627517bcfdc28a8468c3f1b0b06c626f30dd759d3999fd", + "sha256:d81657b23e0edb84b37167e98aefb04ae16cbc5352770057893bd222cdc6e45f", + "sha256:d92d897cb4b4bf915fbeb5e604c7911021a8456f0964f3b8ebbe7f9188b9eabb", + "sha256:dd318e6b75ca80bff0b22b302f83a8ee41c62b8ac662ddb49f67ec97e799885d", + "sha256:dd952b9c64f3b21aedd09b8fe958e4931864dba69926d8a90c90d36ac4e28c9a", + "sha256:e0e7e83f31e23c5d00ff618045ddc5e916f9e613d33c5a5823bc0b0a0feb522f", + "sha256:e0f17d1df951336a02afc8270c03c0c6e60d1f9996fcbd43a4ce6be81de0bd9d", + "sha256:e2a16ef5fa2382af83bef4a18c1b3bcb4284c4732906aa69422cf09df9c59f1f", + "sha256:e36021db54b8a0475805acc1d6c4bca5d9f52c3825ad29ae2d398a9d530ddb88", + "sha256:e73db54c967eb75037c178a54445c5a4e7461b5203b27c45ef656a81787c0c1b", + "sha256:e741bd48e6a417bdfbae02e088f60018286d6c141639359fb8df017a3b69415a", + "sha256:f7271d6bd8838c49ba8ae647fc06469137e1c161a7ef97d778b72904d9b68696", + "sha256:fc391e3941045fd0987c77484b2799adffd08e4b6735c4ee5f054366a2e1551d", + "sha256:fc94441bcf9cb8c59f51f23193316afefbf3ff858460cb47b5758bf66a14d130", + "sha256:fe34befb8c765b8ce562f0200afda3578f8abb159c76de3ab354c80b72244c41", + "sha256:fe8080b4f25dfc44a86bedd14bc4f9d469dfc6456e6f3c5d9077e81a5fedfba7", + "sha256:ff34cb09a332832d1cf38acd0f604c068665192c6107a439a92abfd8acf90fe2" ], "markers": "python_version >= '3.7'", - "version": "==1.9.2" + "version": "==1.9.3" } }, "develop": { @@ -919,7 +943,7 @@ "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==8.1.7" }, "dill": { @@ -935,7 +959,7 @@ "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4", "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==4.0.11" }, "gitpython": { @@ -943,7 +967,7 @@ "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4", "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==3.1.40" }, "isort": { @@ -975,7 +999,7 @@ "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.1.2" }, "mypy-extensions": { @@ -991,7 +1015,7 @@ "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" ], - "markers": "python_full_version >= '3.7.0'", + "index": "pypi", "version": "==23.2" }, "pathspec": { @@ -999,7 +1023,7 @@ "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20", "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.11.2" }, "pbr": { @@ -1015,7 +1039,7 @@ "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b", "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==4.0.0" }, "pygments": { @@ -1023,7 +1047,7 @@ "sha256:1b37f1b1e1bff2af52ecaf28cc601e2ef7077000b227a0675da25aef85784bc4", "sha256:e45a0e74bf9c530f564ca81b8952343be986a29f6afe7f5ad95c5f06b7bdf5e8" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==2.17.1" }, "pylint": { @@ -1095,7 +1119,7 @@ "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa", "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==13.7.0" }, "smmap": { @@ -1103,7 +1127,7 @@ "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62", "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==5.0.1" }, "stevedore": { @@ -1127,7 +1151,7 @@ "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4", "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.12.3" }, "typing-extensions": { diff --git a/bot.py b/bot.py index 3a4cc8a3d8..84ddf653a2 100644 --- a/bot.py +++ b/bot.py @@ -22,7 +22,7 @@ from discord.ext import commands, tasks from discord.ext.commands.view import StringView from emoji import is_emoji -from pkg_resources import parse_version +from packaging.version import Version try: @@ -186,7 +186,7 @@ async def load_extensions(self): @property def version(self): - return parse_version(__version__) + return Version(__version__) @property def api(self) -> ApiClient: @@ -1586,7 +1586,7 @@ async def autoupdate(self): changelog = await Changelog.from_url(self) latest = changelog.latest_version - if self.version < parse_version(latest.version): + if self.version < Version(latest.version): error = None data = {} try: diff --git a/cogs/plugins.py b/cogs/plugins.py index d5787956f1..fc6e09f05d 100644 --- a/cogs/plugins.py +++ b/cogs/plugins.py @@ -16,7 +16,7 @@ import discord from discord.ext import commands -from pkg_resources import parse_version +from packaging.version import Version from core import checks from core.models import PermissionLevel, getLogger @@ -300,7 +300,7 @@ async def parse_user_input(self, ctx, plugin_name, check_version=False): if check_version: required_version = details.get("bot_version", False) - if required_version and self.bot.version < parse_version(required_version): + if required_version and self.bot.version < Version(required_version): embed = discord.Embed( description="Your bot's version is too low. " f"This plugin requires version `{required_version}`.", @@ -688,7 +688,7 @@ async def plugins_registry(self, ctx, *, plugin_name: typing.Union[int, str] = N embed.set_footer(text="This plugin is currently loaded.") else: required_version = details.get("bot_version", False) - if required_version and self.bot.version < parse_version(required_version): + if required_version and self.bot.version < Version(required_version): embed.set_footer( text="Your bot is unable to install this plugin, " f"minimum required version is v{required_version}." diff --git a/cogs/utility.py b/cogs/utility.py index 126b6f785f..b892ffc01b 100644 --- a/cogs/utility.py +++ b/cogs/utility.py @@ -14,11 +14,12 @@ from typing import Union import discord -from aiohttp import ClientResponseError from discord.enums import ActivityType, Status from discord.ext import commands, tasks from discord.ext.commands.view import StringView -from pkg_resources import parse_version + +from aiohttp import ClientResponseError +from packaging.version import Version from core import checks, utils from core.changelog import Changelog @@ -341,9 +342,9 @@ async def about(self, ctx): latest = changelog.latest_version if self.bot.version.is_prerelease: - stable = next(filter(lambda v: not parse_version(v.version).is_prerelease, changelog.versions)) + stable = next(filter(lambda v: not Version(v.version).is_prerelease, changelog.versions)) footer = f"You are on the prerelease version โ€ข the latest version is v{stable.version}." - elif self.bot.version < parse_version(latest.version): + elif self.bot.version < Version(latest.version): footer = f"A newer version is available v{latest.version}." else: footer = "You are up to date with the latest version." @@ -1930,7 +1931,7 @@ async def update(self, ctx, *, flag: str = ""): "(https://github.com/modmail-dev/modmail/blob/master/bot.py#L1)" ) - if self.bot.version >= parse_version(latest.version) and flag.lower() != "force": + if self.bot.version >= Version(latest.version) and flag.lower() != "force": embed = discord.Embed(title="Already up to date", description=desc, color=self.bot.main_color) data = await self.bot.api.get_user_info() diff --git a/requirements.txt b/requirements.txt index 313426315e..3c712a43a0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,40 +1,37 @@ -# -# These requirements were autogenerated by pipenv -# To regenerate from the project's Pipfile, run: -# -# pipenv lock --requirements -# - -i https://pypi.org/simple -aiohttp==3.8.1 -aiosignal==1.2.0; python_version >= '3.6' -async-timeout==4.0.2; python_version >= '3.6' -attrs==21.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -cairocffi==1.3.0; python_version >= '3.7' -cairosvg==2.5.2 -cffi==1.15.0 -charset-normalizer==2.0.12; python_version >= '3.5' -colorama==0.4.4 -cssselect2==0.6.0; python_version >= '3.7' +aiohttp==3.9.0 +aiosignal==1.3.1; python_version >= '3.7' +async-timeout==4.0.3; python_version < '3.11' +attrs==23.1.0; python_version >= '3.7' +cairocffi==1.6.1; python_version >= '3.7' +cairosvg==2.7.1; python_version >= '3.5' +certifi==2023.11.17; python_version >= '3.6' +cffi==1.16.0; python_version >= '3.8' +charset-normalizer==3.3.2; python_version >= '3.7' +colorama==0.4.6 +cssselect2==0.7.0; python_version >= '3.7' defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -dnspython==2.2.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -emoji==1.7.0 -frozenlist==1.3.0; python_version >= '3.7' -discord.py==2.0.1 -idna==3.3; python_version >= '3.5' +discord.py==2.3.2 +dnspython==2.4.2; python_version >= '3.8' and python_version < '4.0' +emoji==2.8.0 +frozenlist==1.4.0; python_version >= '3.8' +idna==3.4; python_version >= '3.5' isodate==0.6.1 -lottie[pdf]==0.6.11 -motor==2.5.1 -multidict==6.0.2; python_version >= '3.7' +lottie[pdf]==0.7.0 +motor==3.3.2 +multidict==6.0.4; python_version >= '3.7' natural==0.2.0 +packaging==23.2 parsedatetime==2.6 -pillow==9.1.0; python_version >= '3.7' +pillow==10.1.0; python_version >= '3.8' pycparser==2.21 -pymongo==3.12.3 +pymongo[srv]==4.6.0 python-dateutil==2.8.2 -python-dotenv==0.20.0 +python-dotenv==1.0.0 +requests==2.31.0 six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -tinycss2==1.1.1; python_version >= '3.6' -uvloop==0.16.0; sys_platform != 'win32' +tinycss2==1.2.1; python_version >= '3.7' +urllib3==2.1.0; python_version >= '3.8' +uvloop==0.19.0; sys_platform != 'win32' webencodings==0.5.1 -yarl==1.7.2; python_version >= '3.6' +yarl==1.9.3; python_version >= '3.7' From 71e6e8737673b8c9d9aa45fa313a6b23e2c381cd Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:28:01 -0800 Subject: [PATCH 214/225] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0ca324a29..6512a29f5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Drops support for Python 3.9. Python 3.10 and Python 3.11 are now the only suppo - `STREAM_LOG_FORMAT` and `FILE_LOG_FORMAT` environment variable to set the log format of the stream and file handlers respectively. Possible options are `json` and `plain` (default). ([PR #3305](https://github.com/modmail-dev/Modmail/pull/3305)) - `LOG_EXPIRATION` environment variable to set the expiration time of logs. ([PR #3257](https://github.com/modmail-dev/Modmail/pull/3257)) - New registry plugins: [`autoreact`](https://github.com/martinbndr/kyb3r-modmail-plugins/tree/master/autoreact) and [`rename`](https://github.com/Nicklaus-s/modmail-plugins/tree/main/rename). +- Improved join/leave message for multiple servers. ### Changed - Repo moved to https://github.com/modmail-dev/modmail. From 048a9d2b823591729ff4e1ed4e3fad9368ee9064 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:30:36 -0800 Subject: [PATCH 215/225] Black reformat code --- core/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/utils.py b/core/utils.py index 8cc91d8130..9f9f572f5a 100644 --- a/core/utils.py +++ b/core/utils.py @@ -154,7 +154,7 @@ def is_image_url(url: str, **kwargs) -> str: """ try: result = parse.urlparse(url) - if result.netloc == 'gyazo.com' and result.scheme in ['http', 'https']: + if result.netloc == "gyazo.com" and result.scheme in ["http", "https"]: # gyazo support url = re.sub( r"(https?://)((?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|%[0-9a-fA-F][0-9a-fA-F])+)", From 3af8dfa4722871b1a20b565fbd92d6669e7fc386 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Tue, 21 Nov 2023 07:16:16 -0800 Subject: [PATCH 216/225] Fixed #3315: gif stickers are now rendered correctly, allow bare sticker reply/note --- CHANGELOG.md | 2 ++ core/thread.py | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6512a29f5f..01a03b35b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s Drops support for Python 3.9. Python 3.10 and Python 3.11 are now the only supported versions. ### Fixed +- GIF stickers causes the bot to crash. - `?alias make/create` as aliases to `?alias add`. This improves continuity between the bot and its command structure. ([PR #3195](https://github.com/kyb3r/modmail/pull/3195)) - Loading the blocked list with the `?blocked` command takes a long time when the list is large. ([PR #3242](https://github.com/kyb3r/modmail/pull/3242)) - Reply not being forwarded from DM. (PR [#3239](https://github.com/modmail-dev/modmail/pull/3239)) @@ -33,6 +34,7 @@ Drops support for Python 3.9. Python 3.10 and Python 3.11 are now the only suppo ### Changed - Repo moved to https://github.com/modmail-dev/modmail. - Channel name no longer shows `-0` if the user has migrated to the new username system. +- `?note` and `?reply` now allows you to send a sticker without any message. - Guild icons in embed footers and author urls now have a fixed size of 128. ([PR #3261](https://github.com/modmail-dev/modmail/pull/3261)) - Discord.py internal logging is now enabled by default. ([PR #3216](https://github.com/modmail-dev/Modmail/pull/3216)) - The confirm-thread-creation dialog now uses buttons instead of reactions. ([PR #3273](https://github.com/modmail-dev/Modmail/pull/3273)) diff --git a/core/thread.py b/core/thread.py index 0222eb0102..646c98a604 100644 --- a/core/thread.py +++ b/core/thread.py @@ -800,7 +800,7 @@ async def edit_dm_message(self, message: discord.Message, content: str) -> None: async def note( self, message: discord.Message, persistent=False, thread_creation=False ) -> discord.Message: - if not message.content and not message.attachments: + if not message.content and not message.attachments and not message.stickers: raise MissingRequiredArgument(DummyParam("msg")) msg = await self.send( @@ -821,7 +821,7 @@ async def reply( self, message: discord.Message, anonymous: bool = False, plain: bool = False ) -> typing.Tuple[typing.List[discord.Message], discord.Message]: """Returns List[user_dm_msg] and thread_channel_msg""" - if not message.content and not message.attachments: + if not message.content and not message.attachments and not message.stickers: raise MissingRequiredArgument(DummyParam("msg")) if not any(g.get_member(self.id) for g in self.bot.guilds): return await message.channel.send( @@ -1020,8 +1020,14 @@ def lottie_to_png(data): return stream.read() for i in message.stickers: - if i.format in (discord.StickerFormatType.png, discord.StickerFormatType.apng): - images.append((i.url, i.name, True)) + if i.format in ( + discord.StickerFormatType.png, + discord.StickerFormatType.apng, + discord.StickerFormatType.gif, + ): + images.append( + (f"https://media.discordapp.net/stickers/{i.id}.{i.format.file_extension}", i.name, True) + ) elif i.format == discord.StickerFormatType.lottie: # save the json lottie representation try: From 35194d81b18883f5d03a8a6098a6aac1e592bba9 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Tue, 21 Nov 2023 07:18:31 -0800 Subject: [PATCH 217/225] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01a03b35b5..0ef7e87d6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ however, insignificant breaking changes do not guarantee a major version bump, s Drops support for Python 3.9. Python 3.10 and Python 3.11 are now the only supported versions. ### Fixed -- GIF stickers causes the bot to crash. +- GIF stickers no longer cause the bot to crash. - `?alias make/create` as aliases to `?alias add`. This improves continuity between the bot and its command structure. ([PR #3195](https://github.com/kyb3r/modmail/pull/3195)) - Loading the blocked list with the `?blocked` command takes a long time when the list is large. ([PR #3242](https://github.com/kyb3r/modmail/pull/3242)) - Reply not being forwarded from DM. (PR [#3239](https://github.com/modmail-dev/modmail/pull/3239)) From 62ae63761f492f59300d6694b5ea202bdc71edc3 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Tue, 21 Nov 2023 18:09:03 -0800 Subject: [PATCH 218/225] Use discord[speed] extra --- Pipfile | 2 +- Pipfile.lock | 246 ++++++++++++++++++++++++++++++++++++++++++++--- requirements.txt | 28 +++--- 3 files changed, 251 insertions(+), 25 deletions(-) diff --git a/Pipfile b/Pipfile index 98e60935be..21205b36f5 100644 --- a/Pipfile +++ b/Pipfile @@ -12,7 +12,7 @@ typing-extensions = "==4.8.0" [packages] aiohttp = "==3.9.0" colorama = "==0.4.6" -"discord.py" = "==2.3.2" +"discord.py" = {version = "==2.3.2", extras = ["speed"]} emoji = "==2.8.0" isodate = "==0.6.1" motor = "==3.3.2" diff --git a/Pipfile.lock b/Pipfile.lock index 2892217178..5f07c7b131 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2744146f249e9fd303c9cba7df1fff03a597cf8a141075c2d4d51ff80efbee7b" + "sha256": "7fee393ea9ea4c0b923033f0da0fdc590ba3f75c6072812062cdc458b84bf9ae" }, "pipfile-spec": 6, "requires": {}, @@ -14,6 +14,13 @@ ] }, "default": { + "aiodns": { + "hashes": [ + "sha256:1073eac48185f7a4150cad7f96a5192d6911f12b4fb894de80a088508c9b3a99", + "sha256:a387b63da4ced6aad35b1dda2d09620ad608a1c7c0fb71efa07ebb4cd511928d" + ], + "version": "==3.1.1" + }, "aiohttp": { "hashes": [ "sha256:05857848da443c8c12110d99285d499b4e84d59918a21132e45c3f0804876994", @@ -94,6 +101,7 @@ "sha256:f9e09a1c83521d770d170b3801eea19b89f41ccaa61d53026ed111cb6f088887" ], "index": "pypi", + "markers": "python_version >= '3.8'", "version": "==3.9.0" }, "aiosignal": { @@ -120,6 +128,94 @@ "markers": "python_version >= '3.7'", "version": "==23.1.0" }, + "brotli": { + "hashes": [ + "sha256:03d20af184290887bdea3f0f78c4f737d126c74dc2f3ccadf07e54ceca3bf208", + "sha256:0541e747cce78e24ea12d69176f6a7ddb690e62c425e01d31cc065e69ce55b48", + "sha256:069a121ac97412d1fe506da790b3e69f52254b9df4eb665cd42460c837193354", + "sha256:0b63b949ff929fbc2d6d3ce0e924c9b93c9785d877a21a1b678877ffbbc4423a", + "sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128", + "sha256:11d00ed0a83fa22d29bc6b64ef636c4552ebafcef57154b4ddd132f5638fbd1c", + "sha256:141bd4d93984070e097521ed07e2575b46f817d08f9fa42b16b9b5f27b5ac088", + "sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9", + "sha256:1ab4fbee0b2d9098c74f3057b2bc055a8bd92ccf02f65944a241b4349229185a", + "sha256:1ae56aca0402a0f9a3431cddda62ad71666ca9d4dc3a10a142b9dce2e3c0cda3", + "sha256:224e57f6eac61cc449f498cc5f0e1725ba2071a3d4f48d5d9dffba42db196438", + "sha256:22fc2a8549ffe699bfba2256ab2ed0421a7b8fadff114a3d201794e45a9ff578", + "sha256:23032ae55523cc7bccb4f6a0bf368cd25ad9bcdcc1990b64a647e7bbcce9cb5b", + "sha256:2333e30a5e00fe0fe55903c8832e08ee9c3b1382aacf4db26664a16528d51b4b", + "sha256:2954c1c23f81c2eaf0b0717d9380bd348578a94161a65b3a2afc62c86467dd68", + "sha256:2de9d02f5bda03d27ede52e8cfe7b865b066fa49258cbab568720aa5be80a47d", + "sha256:30924eb4c57903d5a7526b08ef4a584acc22ab1ffa085faceb521521d2de32dd", + "sha256:316cc9b17edf613ac76b1f1f305d2a748f1b976b033b049a6ecdfd5612c70409", + "sha256:38025d9f30cf4634f8309c6874ef871b841eb3c347e90b0851f63d1ded5212da", + "sha256:39da8adedf6942d76dc3e46653e52df937a3c4d6d18fdc94a7c29d263b1f5b50", + "sha256:3d7954194c36e304e1523f55d7042c59dc53ec20dd4e9ea9d151f1b62b4415c0", + "sha256:4093c631e96fdd49e0377a9c167bfd75b6d0bad2ace734c6eb20b348bc3ea180", + "sha256:43ce1b9935bfa1ede40028054d7f48b5469cd02733a365eec8a329ffd342915d", + "sha256:4d4a848d1837973bf0f4b5e54e3bec977d99be36a7895c61abb659301b02c112", + "sha256:4ed11165dd45ce798d99a136808a794a748d5dc38511303239d4e2363c0695dc", + "sha256:510b5b1bfbe20e1a7b3baf5fed9e9451873559a976c1a78eebaa3b86c57b4265", + "sha256:524f35912131cc2cabb00edfd8d573b07f2d9f21fa824bd3fb19725a9cf06327", + "sha256:587ca6d3cef6e4e868102672d3bd9dc9698c309ba56d41c2b9c85bbb903cdb95", + "sha256:5b3cc074004d968722f51e550b41a27be656ec48f8afaeeb45ebf65b561481dd", + "sha256:5eeb539606f18a0b232d4ba45adccde4125592f3f636a6182b4a8a436548b914", + "sha256:5f4d5ea15c9382135076d2fb28dde923352fe02951e66935a9efaac8f10e81b0", + "sha256:5fb2ce4b8045c78ebbc7b8f3c15062e435d47e7393cc57c25115cfd49883747a", + "sha256:6172447e1b368dcbc458925e5ddaf9113477b0ed542df258d84fa28fc45ceea7", + "sha256:6c3020404e0b5eefd7c9485ccf8393cfb75ec38ce75586e046573c9dc29967a0", + "sha256:70051525001750221daa10907c77830bc889cb6d865cc0b813d9db7fefc21451", + "sha256:7905193081db9bfa73b1219140b3d315831cbff0d8941f22da695832f0dd188f", + "sha256:7c4855522edb2e6ae7fdb58e07c3ba9111e7621a8956f481c68d5d979c93032e", + "sha256:7e4c4629ddad63006efa0ef968c8e4751c5868ff0b1c5c40f76524e894c50248", + "sha256:7f4bf76817c14aa98cc6697ac02f3972cb8c3da93e9ef16b9c66573a68014f91", + "sha256:81de08ac11bcb85841e440c13611c00b67d3bf82698314928d0b676362546724", + "sha256:861bf317735688269936f755fa136a99d1ed526883859f86e41a5d43c61d8966", + "sha256:890b5a14ce214389b2cc36ce82f3093f96f4cc730c1cffdbefff77a7c71f2a97", + "sha256:89f4988c7203739d48c6f806f1e87a1d96e0806d44f0fba61dba81392c9e474d", + "sha256:8dadd1314583ec0bf2d1379f7008ad627cd6336625d6679cf2f8e67081b83acf", + "sha256:901032ff242d479a0efa956d853d16875d42157f98951c0230f69e69f9c09bac", + "sha256:906bc3a79de8c4ae5b86d3d75a8b77e44404b0f4261714306e3ad248d8ab0951", + "sha256:919e32f147ae93a09fe064d77d5ebf4e35502a8df75c29fb05788528e330fe74", + "sha256:929811df5462e182b13920da56c6e0284af407d1de637d8e536c5cd00a7daf60", + "sha256:949f3b7c29912693cee0afcf09acd6ebc04c57af949d9bf77d6101ebb61e388c", + "sha256:a090ca607cbb6a34b0391776f0cb48062081f5f60ddcce5d11838e67a01928d1", + "sha256:a1fd8a29719ccce974d523580987b7f8229aeace506952fa9ce1d53a033873c8", + "sha256:a37b8f0391212d29b3a91a799c8e4a2855e0576911cdfb2515487e30e322253d", + "sha256:a3daabb76a78f829cafc365531c972016e4aa8d5b4bf60660ad8ecee19df7ccc", + "sha256:a469274ad18dc0e4d316eefa616d1d0c2ff9da369af19fa6f3daa4f09671fd61", + "sha256:a599669fd7c47233438a56936988a2478685e74854088ef5293802123b5b2460", + "sha256:a743e5a28af5f70f9c080380a5f908d4d21d40e8f0e0c8901604d15cfa9ba751", + "sha256:a77def80806c421b4b0af06f45d65a136e7ac0bdca3c09d9e2ea4e515367c7e9", + "sha256:aac0411d20e345dc0920bdec5548e438e999ff68d77564d5e9463a7ca9d3e7b1", + "sha256:ae15b066e5ad21366600ebec29a7ccbc86812ed267e4b28e860b8ca16a2bc474", + "sha256:be36e3d172dc816333f33520154d708a2657ea63762ec16b62ece02ab5e4daf2", + "sha256:c8146669223164fc87a7e3de9f81e9423c67a79d6b3447994dfb9c95da16e2d6", + "sha256:c8fd5270e906eef71d4a8d19b7c6a43760c6abcfcc10c9101d14eb2357418de9", + "sha256:caf9ee9a5775f3111642d33b86237b05808dafcd6268faa492250e9b78046eb2", + "sha256:cdad5b9014d83ca68c25d2e9444e28e967ef16e80f6b436918c700c117a85467", + "sha256:cdbc1fc1bc0bff1cef838eafe581b55bfbffaed4ed0318b724d0b71d4d377619", + "sha256:ceb64bbc6eac5a140ca649003756940f8d6a7c444a68af170b3187623b43bebf", + "sha256:d0c5516f0aed654134a2fc936325cc2e642f8a0e096d075209672eb321cff408", + "sha256:d143fd47fad1db3d7c27a1b1d66162e855b5d50a89666af46e1679c496e8e579", + "sha256:d192f0f30804e55db0d0e0a35d83a9fead0e9a359a9ed0285dbacea60cc10a84", + "sha256:db85ecf4e609a48f4b29055f1e144231b90edc90af7481aa731ba2d059226b1b", + "sha256:de6551e370ef19f8de1807d0a9aa2cdfdce2e85ce88b122fe9f6b2b076837e59", + "sha256:e1140c64812cb9b06c922e77f1c26a75ec5e3f0fb2bf92cc8c58720dec276752", + "sha256:e6a904cb26bfefc2f0a6f240bdf5233be78cd2488900a2f846f3c3ac8489ab80", + "sha256:e84799f09591700a4154154cab9787452925578841a94321d5ee8fb9a9a328f0", + "sha256:e93dfc1a1165e385cc8239fab7c036fb2cd8093728cbd85097b284d7b99249a2", + "sha256:efa8b278894b14d6da122a72fefcebc28445f2d3f880ac59d46c90f4c13be9a3", + "sha256:f0d8a7a6b5983c2496e364b969f0e526647a06b075d034f3297dc66f3b360c64", + "sha256:f296c40e23065d0d6650c4aefe7470d2a25fffda489bcc3eb66083f3ac9f6643", + "sha256:f66b5337fa213f1da0d9000bc8dc0cb5b896b726eefd9c6046f699b169c41b9e", + "sha256:f733d788519c7e3e71f0855c96618720f5d3d60c3cb829d8bbb722dddce37985", + "sha256:fce1473f3ccc4187f75b4690cfc922628aed4d3dd013d047f95a9b3919a86596", + "sha256:fd5f17ff8f14003595ab414e45fce13d073e0762394f957182e69035c9f3d7c2", + "sha256:fdc3ff3bfccdc6b9cc7c342c03aa2400683f0cb891d46e94b64a197910dc4064" + ], + "version": "==1.1.0" + }, "cairocffi": { "hashes": [ "sha256:78e6bbe47357640c453d0be929fa49cd05cce2e1286f3d2a1ca9cbda7efdb8b7", @@ -295,7 +391,7 @@ "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==3.3.2" }, "colorama": { @@ -304,6 +400,7 @@ "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" ], "index": "pypi", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", "version": "==0.4.6" }, "cssselect2": { @@ -323,11 +420,14 @@ "version": "==0.7.1" }, "discord.py": { + "extras": [ + "speed" + ], "hashes": [ "sha256:4560f70f2eddba7e83370ecebd237ac09fbb4980dc66507482b0c0e5b8f76b9c", "sha256:9da4679fc3cb10c64b388284700dc998663e0e57328283bbfcfc2525ec5960a6" ], - "index": "pypi", + "markers": "python_full_version >= '3.8.0'", "version": "==2.3.2" }, "dnspython": { @@ -344,6 +444,7 @@ "sha256:a8468fd836b7ecb6d1eac054c9a591701ce0ccd6c6f7779ad71b66f76664df90" ], "index": "pypi", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.0" }, "frozenlist": { @@ -436,7 +537,7 @@ "hashes": [ "sha256:a3242f8ba37051fbdd7503ecd168203a08e4af26f17be2ecca08a64af1e7d3c1" ], - "index": "pypi", + "markers": "python_version >= '3'", "version": "==0.7.0" }, "motor": { @@ -445,6 +546,7 @@ "sha256:d2fc38de15f1c8058f389c1a44a4d4105c0405c48c061cd492a654496f7bc26a" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==3.3.2" }, "multidict": { @@ -534,12 +636,68 @@ "index": "pypi", "version": "==0.2.0" }, + "orjson": { + "hashes": [ + "sha256:06ad5543217e0e46fd7ab7ea45d506c76f878b87b1b4e369006bdb01acc05a83", + "sha256:0a73160e823151f33cdc05fe2cea557c5ef12fdf276ce29bb4f1c571c8368a60", + "sha256:1234dc92d011d3554d929b6cf058ac4a24d188d97be5e04355f1b9223e98bbe9", + "sha256:1d0dc4310da8b5f6415949bd5ef937e60aeb0eb6b16f95041b5e43e6200821fb", + "sha256:2a11b4b1a8415f105d989876a19b173f6cdc89ca13855ccc67c18efbd7cbd1f8", + "sha256:2e2ecd1d349e62e3960695214f40939bbfdcaeaaa62ccc638f8e651cf0970e5f", + "sha256:3a2ce5ea4f71681623f04e2b7dadede3c7435dfb5e5e2d1d0ec25b35530e277b", + "sha256:3e892621434392199efb54e69edfff9f699f6cc36dd9553c5bf796058b14b20d", + "sha256:3fb205ab52a2e30354640780ce4587157a9563a68c9beaf52153e1cea9aa0921", + "sha256:4689270c35d4bb3102e103ac43c3f0b76b169760aff8bcf2d401a3e0e58cdb7f", + "sha256:49f8ad582da6e8d2cf663c4ba5bf9f83cc052570a3a767487fec6af839b0e777", + "sha256:4bd176f528a8151a6efc5359b853ba3cc0e82d4cd1fab9c1300c5d957dc8f48c", + "sha256:4cf7837c3b11a2dfb589f8530b3cff2bd0307ace4c301e8997e95c7468c1378e", + "sha256:4fd72fab7bddce46c6826994ce1e7de145ae1e9e106ebb8eb9ce1393ca01444d", + "sha256:5148bab4d71f58948c7c39d12b14a9005b6ab35a0bdf317a8ade9a9e4d9d0bd5", + "sha256:5869e8e130e99687d9e4be835116c4ebd83ca92e52e55810962446d841aba8de", + "sha256:602a8001bdf60e1a7d544be29c82560a7b49319a0b31d62586548835bbe2c862", + "sha256:61804231099214e2f84998316f3238c4c2c4aaec302df12b21a64d72e2a135c7", + "sha256:666c6fdcaac1f13eb982b649e1c311c08d7097cbda24f32612dae43648d8db8d", + "sha256:674eb520f02422546c40401f4efaf8207b5e29e420c17051cddf6c02783ff5ca", + "sha256:7ec960b1b942ee3c69323b8721df2a3ce28ff40e7ca47873ae35bfafeb4555ca", + "sha256:7f433be3b3f4c66016d5a20e5b4444ef833a1f802ced13a2d852c637f69729c1", + "sha256:7f8fb7f5ecf4f6355683ac6881fd64b5bb2b8a60e3ccde6ff799e48791d8f864", + "sha256:81a3a3a72c9811b56adf8bcc829b010163bb2fc308877e50e9910c9357e78521", + "sha256:858379cbb08d84fe7583231077d9a36a1a20eb72f8c9076a45df8b083724ad1d", + "sha256:8b9ba0ccd5a7f4219e67fbbe25e6b4a46ceef783c42af7dbc1da548eb28b6531", + "sha256:92af0d00091e744587221e79f68d617b432425a7e59328ca4c496f774a356071", + "sha256:9ebbdbd6a046c304b1845e96fbcc5559cd296b4dfd3ad2509e33c4d9ce07d6a1", + "sha256:9edd2856611e5050004f4722922b7b1cd6268da34102667bd49d2a2b18bafb81", + "sha256:a353bf1f565ed27ba71a419b2cd3db9d6151da426b61b289b6ba1422a702e643", + "sha256:b5b7d4a44cc0e6ff98da5d56cde794385bdd212a86563ac321ca64d7f80c80d1", + "sha256:b90f340cb6397ec7a854157fac03f0c82b744abdd1c0941a024c3c29d1340aff", + "sha256:c18a4da2f50050a03d1da5317388ef84a16013302a5281d6f64e4a3f406aabc4", + "sha256:c338ed69ad0b8f8f8920c13f529889fe0771abbb46550013e3c3d01e5174deef", + "sha256:c5a02360e73e7208a872bf65a7554c9f15df5fe063dc047f79738998b0506a14", + "sha256:c62b6fa2961a1dcc51ebe88771be5319a93fd89bd247c9ddf732bc250507bc2b", + "sha256:c812312847867b6335cfb264772f2a7e85b3b502d3a6b0586aa35e1858528ab1", + "sha256:c943b35ecdf7123b2d81d225397efddf0bce2e81db2f3ae633ead38e85cd5ade", + "sha256:ce0a29c28dfb8eccd0f16219360530bc3cfdf6bf70ca384dacd36e6c650ef8e8", + "sha256:cf80b550092cc480a0cbd0750e8189247ff45457e5a023305f7ef1bcec811616", + "sha256:cff7570d492bcf4b64cc862a6e2fb77edd5e5748ad715f487628f102815165e9", + "sha256:d2c1e559d96a7f94a4f581e2a32d6d610df5840881a8cba8f25e446f4d792df3", + "sha256:deeb3922a7a804755bbe6b5be9b312e746137a03600f488290318936c1a2d4dc", + "sha256:e28a50b5be854e18d54f75ef1bb13e1abf4bc650ab9d635e4258c58e71eb6ad5", + "sha256:e99c625b8c95d7741fe057585176b1b8783d46ed4b8932cf98ee145c4facf499", + "sha256:ec6f18f96b47299c11203edfbdc34e1b69085070d9a3d1f302810cc23ad36bf3", + "sha256:ed8bc367f725dfc5cabeed1ae079d00369900231fbb5a5280cf0736c30e2adf7", + "sha256:ee5926746232f627a3be1cc175b2cfad24d0170d520361f4ce3fa2fd83f09e1d", + "sha256:f295efcd47b6124b01255d1491f9e46f17ef40d3d7eabf7364099e463fb45f0f", + "sha256:fb0b361d73f6b8eeceba47cd37070b5e6c9de5beaeaa63a1cb35c7e1a73ef088" + ], + "version": "==3.9.10" + }, "packaging": { "hashes": [ "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==23.2" }, "parsedatetime": { @@ -610,6 +768,63 @@ "markers": "python_version >= '3.8'", "version": "==10.1.0" }, + "pycares": { + "hashes": [ + "sha256:112a4979c695b1c86f6782163d7dec58d57a3b9510536dcf4826550f9053dd9a", + "sha256:1168a48a834813aa80f412be2df4abaf630528a58d15c704857448b20b1675c0", + "sha256:21a5a0468861ec7df7befa69050f952da13db5427ae41ffe4713bc96291d1d95", + "sha256:229a1675eb33bc9afb1fc463e73ee334950ccc485bc83a43f6ae5839fb4d5fa3", + "sha256:22c00bf659a9fa44d7b405cf1cd69b68b9d37537899898d8cbe5dffa4016b273", + "sha256:23aa3993a352491a47fcf17867f61472f32f874df4adcbb486294bd9fbe8abee", + "sha256:24da119850841d16996713d9c3374ca28a21deee056d609fbbed29065d17e1f6", + "sha256:2eeec144bcf6a7b6f2d74d6e70cbba7886a84dd373c886f06cb137a07de4954c", + "sha256:34736a2ffaa9c08ca9c707011a2d7b69074bbf82d645d8138bba771479b2362f", + "sha256:3aebc73e5ad70464f998f77f2da2063aa617cbd8d3e8174dd7c5b4518f967153", + "sha256:3eaa6681c0a3e3f3868c77aca14b7760fed35fdfda2fe587e15c701950e7bc69", + "sha256:4afc2644423f4eef97857a9fd61be9758ce5e336b4b0bd3d591238bb4b8b03e0", + "sha256:52084961262232ec04bd75f5043aed7e5d8d9695e542ff691dfef0110209f2d4", + "sha256:56cf3349fa3a2e67ed387a7974c11d233734636fe19facfcda261b411af14d80", + "sha256:5ed4e04af4012f875b78219d34434a6d08a67175150ac1b79eb70ab585d4ba8c", + "sha256:64965dc19c578a683ea73487a215a8897276224e004d50eeb21f0bc7a0b63c88", + "sha256:6ef64649eba56448f65e26546d85c860709844d2fc22ef14d324fe0b27f761a9", + "sha256:77cf5a2fd5583c670de41a7f4a7b46e5cbabe7180d8029f728571f4d2e864084", + "sha256:7bddc6adba8f699728f7fc1c9ce8cef359817ad78e2ed52b9502cb5f8dc7f741", + "sha256:813d661cbe2e37d87da2d16b7110a6860e93ddb11735c6919c8a3545c7b9c8d8", + "sha256:82bba2ab77eb5addbf9758d514d9bdef3c1bfe7d1649a47bd9a0d55a23ef478b", + "sha256:8bf2eaa83a5987e48fa63302f0fe7ce3275cfda87b34d40fef9ce703fb3ac002", + "sha256:8d186dafccdaa3409194c0f94db93c1a5d191145a275f19da6591f9499b8e7b8", + "sha256:8f64cb58729689d4d0e78f0bfb4c25ce2f851d0274c0273ac751795c04b8798a", + "sha256:902461a92b6a80fd5041a2ec5235680c7cc35e43615639ec2a40e63fca2dfb51", + "sha256:917f08f0b5d9324e9a34211e68d27447c552b50ab967044776bbab7e42a553a2", + "sha256:94d6962db81541eb0396d2f0dfcbb18cdb8c8b251d165efc2d974ae652c547d4", + "sha256:97892cced5794d721fb4ff8765764aa4ea48fe8b2c3820677505b96b83d4ef47", + "sha256:9a0303428d013ccf5c51de59c83f9127aba6200adb7fd4be57eddb432a1edd2a", + "sha256:9dc04c54c6ea615210c1b9e803d0e2d2255f87a3d5d119b6482c8f0dfa15b26b", + "sha256:a0c5368206057884cde18602580083aeaad9b860e2eac14fd253543158ce1e93", + "sha256:ad58e284a658a8a6a84af2e0b62f2f961f303cedfe551854d7bd40c3cbb61912", + "sha256:afb91792f1556f97be7f7acb57dc7756d89c5a87bd8b90363a77dbf9ea653817", + "sha256:b61579cecf1f4d616e5ea31a6e423a16680ab0d3a24a2ffe7bb1d4ee162477ff", + "sha256:b7af06968cbf6851566e806bf3e72825b0e6671832a2cbe840be1d2d65350710", + "sha256:bce8db2fc6f3174bd39b81405210b9b88d7b607d33e56a970c34a0c190da0490", + "sha256:bfb89ca9e3d0a9b5332deeb666b2ede9d3469107742158f4aeda5ce032d003f4", + "sha256:c680fef1b502ee680f8f0b95a41af4ec2c234e50e16c0af5bbda31999d3584bd", + "sha256:c6a8bde63106f162fca736e842a916853cad3c8d9d137e11c9ffa37efa818b02", + "sha256:cb49d5805cd347c404f928c5ae7c35e86ba0c58ffa701dbe905365e77ce7d641", + "sha256:ceb12974367b0a68a05d52f4162b29f575d241bd53de155efe632bf2c943c7f6", + "sha256:d33e2a1120887e89075f7f814ec144f66a6ce06a54f5722ccefc62fbeda83cff", + "sha256:db24c4e7fea4a052c6e869cbf387dd85d53b9736cfe1ef5d8d568d1ca925e977", + "sha256:e3a6f7cfdfd11eb5493d6d632e582408c8f3b429f295f8799c584c108b28db6f", + "sha256:eb66c30eb11e877976b7ead13632082a8621df648c408b8e15cdb91a452dd502", + "sha256:ed2a38e34bec6f2586435f6ff0bc5fe11d14bebd7ed492cf739a424e81681540", + "sha256:f36bdc1562142e3695555d2f4ac0cb69af165eddcefa98efc1c79495b533481f", + "sha256:f47579d508f2f56eddd16ce72045782ad3b1b3b678098699e2b6a1b30733e1c2", + "sha256:f5f646eec041db6ffdbcaf3e0756fb92018f7af3266138c756bb09d2b5baadec", + "sha256:fd644505a8cfd7f6584d33a9066d4e3d47700f050ef1490230c962de5dfb28c6", + "sha256:fff16b09042ba077f7b8aa5868d1d22456f0002574d0ba43462b10a009331677" + ], + "markers": "python_version >= '3.8'", + "version": "==4.4.0" + }, "pycparser": { "hashes": [ "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", @@ -704,7 +919,7 @@ "sha256:fb1c56d891f9e34303c451998ef62ba52659648bb0d75b03c5e4ac223a3342c2", "sha256:fe03bf25fae4b95d8afe40004a321df644400fdcba4c8e5e1a19c1085b740888" ], - "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==4.6.0" }, "python-dateutil": { @@ -713,6 +928,7 @@ "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" ], "index": "pypi", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.2" }, "python-dotenv": { @@ -721,6 +937,7 @@ "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a" ], "index": "pypi", + "markers": "python_version >= '3.8'", "version": "==1.0.0" }, "requests": { @@ -729,6 +946,7 @@ "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==2.31.0" }, "six": { @@ -789,7 +1007,6 @@ "sha256:e27f100e1ff17f6feeb1f33968bc185bf8ce41ca557deee9d9bbbffeb72030b7", "sha256:f467a5fd23b4fc43ed86342641f3936a68ded707f4627622fa3f82a120e18256" ], - "index": "pypi", "markers": "sys_platform != 'win32'", "version": "==0.19.0" }, @@ -903,7 +1120,7 @@ "sha256:7d5895c9825e18079c5aeac0572bc2e4c83205c95d416e0b4fee8bc361d2d9ca", "sha256:86b0bb7d7da0be1a7c4aedb7974e391b32d4ed89e33de6ed6902b4b15c97577e" ], - "markers": "python_version >= '3.8'", + "markers": "python_full_version >= '3.8.0'", "version": "==3.0.1" }, "bandit": { @@ -912,6 +1129,7 @@ "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==1.7.5" }, "black": { @@ -936,6 +1154,7 @@ "sha256:fc7f6a44d52747e65a02558e1d807c82df1d66ffa80a601862040a43ec2e3142" ], "index": "pypi", + "markers": "python_version >= '3.8'", "version": "==23.11.0" }, "click": { @@ -975,7 +1194,7 @@ "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504", "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6" ], - "markers": "python_version >= '3.8'", + "markers": "python_full_version >= '3.8.0'", "version": "==5.12.0" }, "markdown-it-py": { @@ -1016,6 +1235,7 @@ "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==23.2" }, "pathspec": { @@ -1044,11 +1264,11 @@ }, "pygments": { "hashes": [ - "sha256:1b37f1b1e1bff2af52ecaf28cc601e2ef7077000b227a0675da25aef85784bc4", - "sha256:e45a0e74bf9c530f564ca81b8952343be986a29f6afe7f5ad95c5f06b7bdf5e8" + "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", + "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367" ], "markers": "python_version >= '3.7'", - "version": "==2.17.1" + "version": "==2.17.2" }, "pylint": { "hashes": [ @@ -1056,6 +1276,7 @@ "sha256:60ed5f3a9ff8b61839ff0348b3624ceeb9e6c2a92c514d81c9cc273da3b6bcda" ], "index": "pypi", + "markers": "python_full_version >= '3.8.0'", "version": "==3.0.2" }, "pyyaml": { @@ -1119,7 +1340,7 @@ "sha256:5cb5123b5cf9ee70584244246816e9114227e0b98ad9176eede6ad54bf5403fa", "sha256:6da14c108c4866ee9520bbffa71f6fe3962e193b7da68720583850cd4548e235" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==13.7.0" }, "smmap": { @@ -1160,6 +1381,7 @@ "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef" ], "index": "pypi", + "markers": "python_version >= '3.8'", "version": "==4.8.0" } } diff --git a/requirements.txt b/requirements.txt index 3c712a43a0..2c7bdb7880 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,34 +1,38 @@ -i https://pypi.org/simple -aiohttp==3.9.0 +aiodns==3.1.1 +aiohttp==3.9.0; python_version >= '3.8' aiosignal==1.3.1; python_version >= '3.7' async-timeout==4.0.3; python_version < '3.11' attrs==23.1.0; python_version >= '3.7' +brotli==1.1.0 cairocffi==1.6.1; python_version >= '3.7' cairosvg==2.7.1; python_version >= '3.5' certifi==2023.11.17; python_version >= '3.6' cffi==1.16.0; python_version >= '3.8' -charset-normalizer==3.3.2; python_version >= '3.7' -colorama==0.4.6 +charset-normalizer==3.3.2; python_full_version >= '3.7.0' +colorama==0.4.6; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6' cssselect2==0.7.0; python_version >= '3.7' defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -discord.py==2.3.2 +discord.py[speed]==2.3.2; python_full_version >= '3.8.0' dnspython==2.4.2; python_version >= '3.8' and python_version < '4.0' -emoji==2.8.0 +emoji==2.8.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' frozenlist==1.4.0; python_version >= '3.8' idna==3.4; python_version >= '3.5' isodate==0.6.1 -lottie[pdf]==0.7.0 -motor==3.3.2 +lottie[pdf]==0.7.0; python_version >= '3' +motor==3.3.2; python_version >= '3.7' multidict==6.0.4; python_version >= '3.7' natural==0.2.0 -packaging==23.2 +orjson==3.9.10 +packaging==23.2; python_version >= '3.7' parsedatetime==2.6 pillow==10.1.0; python_version >= '3.8' +pycares==4.4.0; python_version >= '3.8' pycparser==2.21 -pymongo[srv]==4.6.0 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -requests==2.31.0 +pymongo[srv]==4.6.0; python_version >= '3.7' +python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +python-dotenv==1.0.0; python_version >= '3.8' +requests==2.31.0; python_version >= '3.7' six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' tinycss2==1.2.1; python_version >= '3.7' urllib3==2.1.0; python_version >= '3.8' From 768d4daf81f826015420f2d5d3da770e4e7924e7 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 26 Nov 2023 13:51:47 -0800 Subject: [PATCH 219/225] Bump version to 4.1.0 --- CHANGELOG.md | 2 +- README.md | 2 +- bot.py | 2 +- pyproject.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ef7e87d6d..cb334e4e8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html); however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/modmail-dev/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section. -# [UNRELEASED] +# v4.1.0 Drops support for Python 3.9. Python 3.10 and Python 3.11 are now the only supported versions. diff --git a/README.md b/README.md index 319a9742cf..ea6cb3eae0 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ <br> <a href="#"> - <img src="https://img.shields.io/badge/Latest%20Version-v4.0.2-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> + <img src="https://img.shields.io/badge/Latest%20Version-v4.1.0-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs="> </a> <br> diff --git a/bot.py b/bot.py index 3c24681d12..bb47c75283 100644 --- a/bot.py +++ b/bot.py @@ -1,4 +1,4 @@ -__version__ = "4.0.2" +__version__ = "4.1.0" import asyncio diff --git a/pyproject.toml b/pyproject.toml index 389c24e3d5..cc43b4a54c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ extend-exclude = ''' [tool.poetry] name = 'Modmail' -version = '4.0.2' +version = '4.1.0' description = "Modmail is similar to Reddit's Modmail, both in functionality and purpose. It serves as a shared inbox for server staff to communicate with their users in a seamless way." license = 'AGPL-3.0-only' authors = [ From 285e336cece0c87f43cb19959b6da28b0ea91ac7 Mon Sep 17 00:00:00 2001 From: Raiden <raidensakurajima@gmail.com> Date: Wed, 15 May 2024 19:48:26 +0800 Subject: [PATCH 220/225] Fix Docker file permission issue (#3323) * Update Dockerfile * Use the slim-bookworm image, refactored some steps * Disable user login * Capitalize comment --------- Co-authored-by: Taku <45324516+Taaku18@users.noreply.github.com> --- Dockerfile | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index 96a398fad4..246d3cf7a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,38 @@ -FROM python:3.10 as py +FROM python:3.11-slim-bookworm as base -FROM py as build +RUN apt-get update && \ + apt-get install --no-install-recommends -y \ + # Install CairoSVG dependencies. + libcairo2 && \ + # Cleanup APT. + apt-get clean && \ + rm -rf /var/lib/apt/lists/* && \ + # Create a non-root user. + useradd --shell /usr/sbin/nologin --create-home -d /opt/modmail modmail -RUN apt update && apt install -y g++ git +FROM base as builder -COPY requirements.txt / -RUN pip install --prefix=/inst -U -r /requirements.txt +COPY requirements.txt . -FROM py +RUN pip install --root-user-action=ignore --no-cache-dir --upgrade pip wheel && \ + python -m venv /opt/modmail/.venv && \ + . /opt/modmail/.venv/bin/activate && \ + pip install --no-cache-dir --upgrade -r requirements.txt -COPY --from=build /inst /usr/local +FROM base -ENV USING_DOCKER yes -RUN useradd --system --no-create-home modmail -USER modmail +# Copy the entire venv. +COPY --from=builder --chown=modmail:modmail /opt/modmail/.venv /opt/modmail/.venv + +# Copy repository files. +WORKDIR /opt/modmail +USER modmail:modmail +COPY --chown=modmail:modmail . . + +# This sets some Python runtime variables and disables the internal auto-update. +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PATH=/opt/modmail/.venv/bin:$PATH \ + USING_DOCKER=yes -WORKDIR /modmailbot CMD ["python", "bot.py"] -COPY --chown=modmail:modmail . /modmailbot From 30bd95843ff5950790645141883f6f194f2a3c74 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 26 May 2024 03:18:21 -0700 Subject: [PATCH 221/225] Updated sponsors --- README.md | 7 +++++++ SPONSORS.json | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/README.md b/README.md index ea6cb3eae0..980066ca7e 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,13 @@ Advertise Your Server: </a> <br> <br> +Help Us โ€ข Help Other's: +<br> +<a href='https://discord.gg/5yQCFzY6HU'> + <img height=100 src='https://i.imgur.com/Gi3jxeH.gif' style='margin:5px'> +</a> +<br> +<br> Discord Advice Center: <br> <a href='https://discord.gg/zmwZy5fd9v'> diff --git a/SPONSORS.json b/SPONSORS.json index ce34dc3f9d..3a964dc3cf 100644 --- a/SPONSORS.json +++ b/SPONSORS.json @@ -128,5 +128,32 @@ "url": "https://discord.gg/uncommon", "title": "uncommon community" } + }, + { + "embed": { + "author": { + "name": "Help us โ€ข Help Others" + }, + "title": "Join Today", + "url": "https://discord.gg/5yQCFzY6HU", + "description": "At Help Us โ€ข Help Others, we accept as true with inside the transformative electricity of cooperation and kindness. Each one people has the capability to make a meaningful impact by means of helping and caring for others. Whether you want assistance or want to offer it, this is the right region for you!", + "fields": [ + { + "name": "What we offer:", + "value": "`๐ŸŽฌ` - Active community\n`๐Ÿ‘ฎ` - Active staff around the globe! \n`๐Ÿ›œ` - 40+ Advertising channels to grow your socials!\n`๐Ÿ’Ž` - Boosting Perks\n`๐ŸŽ‰` - Event's monthly especially bank holiday roles!!\n`๐Ÿ”ข` - Unique levelling systems\n`๐Ÿ“ž` - Multiple voice channels including gaming!\n`๐ŸŽ` - Exclusive giveaways!" + }, + { + "name": "We Are Hiring", + "value": "`๐Ÿ”ต` - Moderators\n`๐Ÿ”ต` - Human Resources\n`๐Ÿ”ต` - Community Team\n`๐Ÿ”ต` - Partnership Manager\n`๐Ÿ”ต` - Growth Manager\n`๐Ÿš€` Much more to come!\n\n\nJoin Today!" + } + ], + "image": { + "url": "https://cdn.discordapp.com/attachments/1218338794416246874/1243635366326567002/AD_animated.gif" + }, + "color": 45300, + "footer": { + "text": "Help Us โ€ข Help Others" + } + } } ] From 8c04d25c917916f65a536687a6b8dc9398904c4e Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Sun, 23 Jun 2024 09:14:20 -0700 Subject: [PATCH 222/225] Update sponsors --- SPONSORS.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/SPONSORS.json b/SPONSORS.json index 3a964dc3cf..80e3539f87 100644 --- a/SPONSORS.json +++ b/SPONSORS.json @@ -81,7 +81,7 @@ "icon_url": "https://i.imgur.com/cjVtRw5.jpg" }, "image": { - "url": "https://i.imgur.com/1hrjcHd.png" + "url": "https://i.imgur.com/1hrjcHd.png" }, "fields": [ { @@ -155,5 +155,18 @@ "text": "Help Us โ€ข Help Others" } } + }, + { + "embed": { + "description": "> Be apart of our community as we start to grow! and embark on a long journey.\nโ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”-\n**What we offer?**\n\nโžบใ€š๐Ÿ–Œ๏ธใ€›Custom Liveries \nโžบใ€šโค๏ธใ€›Friendly and Growing community.\nโžบใ€š๐Ÿคใ€›Partnerships.\nโžบใ€š๐ŸŽฎใ€›Daily SSUs. \nโžบใ€š๐Ÿšจใ€›Great roleplays.\nโžบใ€š๐Ÿ’ฌใ€›Kind and Professional staff\nโžบใ€š๐ŸŽ‰ใ€›Giveaways!!! \nโ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”-\n**Emergency Services**\n\nโžบใ€š๐Ÿš”ใ€›NY Police Force\nโžบใ€š๐Ÿš’ใ€›Fire & Emergency NY\nโžบใ€š๐Ÿšงใ€›NY department of transportation \n\nโ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”-\n**Whitelisted**\nComing soon!\nโ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”-\n**What are we looking for!**\n\nโžบใ€š๐Ÿ’ฌใ€›More members\nโžบใ€šโญใ€›Staff Members - **WE'RE HIRING!**\nโžบใ€š๐Ÿคใ€›Partnerships\nโžบใ€š๐Ÿ’Žใ€›Boosters\nโ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”\n\n**[Join now](https://discord.com/invite/qt62qSnKVa)**", + "author": { + "name": "New York Roleplay", + "icon_url": "https://cdn.discordapp.com/icons/1172553254882775111/648d5bc50393a21216527a1aaa61286d.webp" + }, + "color": 431075, + "thumbnail": { + "url": "https://cdn.discordapp.com/icons/1172553254882775111/648d5bc50393a21216527a1aaa61286d.webp" + } + } } ] From 19ff5a035cd05cc639aae91036581ee485649ed6 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 26 Aug 2024 00:07:16 +0200 Subject: [PATCH 223/225] Update sponsorship info --- SPONSORS.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/SPONSORS.json b/SPONSORS.json index 80e3539f87..eb43227f6b 100644 --- a/SPONSORS.json +++ b/SPONSORS.json @@ -168,5 +168,15 @@ "url": "https://cdn.discordapp.com/icons/1172553254882775111/648d5bc50393a21216527a1aaa61286d.webp" } } + }, + { + "embeds": { + "title": "Pixelmark TM PLC", + "description": "Hi there! Welcome to PixelMark PLC! \nI'm so glad you're here. I started PixelMark PLC on May 24, 2023. Our team is dedicated to providing top-quality products and a great shopping experience. But more than that, PixelMark PLC is a community. We're here to share, create, and have fun together. Thanks for joining us on this exciting journey! Our current Goal is to reach 100 Human Members, you can help us achieve that Goal by joining or/and inviting your Friends!\n\nBest regards, \n*Felixpro202110 / Chief Executive Officer (Founder)* \n-----------------------------------------------------------------------\n> https://discord.gg/RVzNVRaFeE\n> https://www.roblox.com/groups/16031525/PixelMark-PLC", + "color": 10634504, + "image": { + "url": "https://imgur.com/iTl1dXm.png" + } + } } ] From 041c4fdc78b2391d481ddeee50d0883b645557e7 Mon Sep 17 00:00:00 2001 From: Taku <45324516+Taaku18@users.noreply.github.com> Date: Mon, 26 Aug 2024 00:07:51 +0200 Subject: [PATCH 224/225] Update sponsorship info --- SPONSORS.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPONSORS.json b/SPONSORS.json index eb43227f6b..22cf0d44f1 100644 --- a/SPONSORS.json +++ b/SPONSORS.json @@ -170,7 +170,7 @@ } }, { - "embeds": { + "embed": { "title": "Pixelmark TM PLC", "description": "Hi there! Welcome to PixelMark PLC! \nI'm so glad you're here. I started PixelMark PLC on May 24, 2023. Our team is dedicated to providing top-quality products and a great shopping experience. But more than that, PixelMark PLC is a community. We're here to share, create, and have fun together. Thanks for joining us on this exciting journey! Our current Goal is to reach 100 Human Members, you can help us achieve that Goal by joining or/and inviting your Friends!\n\nBest regards, \n*Felixpro202110 / Chief Executive Officer (Founder)* \n-----------------------------------------------------------------------\n> https://discord.gg/RVzNVRaFeE\n> https://www.roblox.com/groups/16031525/PixelMark-PLC", "color": 10634504, From da97bdc0c78daaf6a3b052346c5a5eb4a4062744 Mon Sep 17 00:00:00 2001 From: andy <andy@ondrya.com> Date: Sun, 27 Oct 2024 10:02:56 -0400 Subject: [PATCH 225/225] Update SPONSORS.json (#3348) Removal of Advertise Your Server. Company has been closed. Signed-off-by: andy <andy@ondrya.com> --- SPONSORS.json | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/SPONSORS.json b/SPONSORS.json index 22cf0d44f1..491b30eb9f 100644 --- a/SPONSORS.json +++ b/SPONSORS.json @@ -91,23 +91,6 @@ ] } }, - { - "embed": { - "title": "Advertise Your Server", - "description": "Advertise Your Server is the leading advertising and growth Discord Server. With over 60,000 members we can help grow your community with our range of services.\n\n__**Advertise Your Server offers everything you need to grow and find servers:**__\n\n:chart_with_upwards_trend: **Discord Growth Experts** to give you advice on how to __grow your server.__ (server/advert reviews, growth tips)\n:dividers: Over 40 different channels for **different server categories.**\n:robot: Our own __custom__ **bump bot.** (Liam)\n:bar_chart: Currently the __BIGGEST__ advertising server on Discord.\n:computer: Our own server __Listing Site__!\n:ticket: Small Servers Program for servers with less than 300 members.\n:dvd: Weekly Podcast, Blog, Email Newsletter and YouTube Tutorials. \n\nhttps://discord.gg/zP8KcF4VQz\nhttps://aysdiscord.com", - "author": { - "name": "Advertise Your Server", - "icon_url": "https://cdn.discordapp.com/attachments/563522692418895872/907067815486427176/logo4.png" - }, - "color": 431075, - "footer": { - "text": "Grow Your Discord Server" - }, - "image": { - "url": "https://cdn.discordapp.com/attachments/472811257913933834/907068966311166043/unknown_2.png" - } - } - }, { "embed": { "footer": {