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/148] 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/148] 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/148] 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/148] 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/148] 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/148] 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/148] 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/148] 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/148] 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/148] 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/148] 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/148] 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/148] 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/148] 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/148] 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\d{17,21})\b"
+ r"(\nOther Recipients:\s*(?P(\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/148] 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 3d494bb32b7b0578406c5a8f5e62b1c20d642791 Mon Sep 17 00:00:00 2001
From: kato <78689486+TheDiscordHistorian@users.noreply.github.com>
Date: Thu, 21 Oct 2021 09:39:16 +0600
Subject: [PATCH 017/148] Add phish checker plugin
---
plugins/registry.json | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/plugins/registry.json b/plugins/registry.json
index b39ac345bd..ad8dbebaf9 100644
--- a/plugins/registry.json
+++ b/plugins/registry.json
@@ -247,5 +247,13 @@
"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"
}
}
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 018/148] 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.*)\n)?"
+ r"(?:\bTitle:\s*(?P.*)\n)?"
r"\bUser ID:\s*(?P\d{17,21})\b"
- r"(\nOther Recipients:\s*(?P(\d{17,21},?)+))?",
+ r"(?:\nOther Recipients:\s*(?P\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 b02934dc64ad4fd272bd37370eb613ab66b94ef4 Mon Sep 17 00:00:00 2001
From: Taku 3 Animals <45324516+Taaku18@users.noreply.github.com>
Date: Sun, 7 Nov 2021 18:05:15 -0800
Subject: [PATCH 019/148] Added sponsor
---
README.md | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/README.md b/README.md
index f4b8e8d2ff..2b4f44ea62 100644
--- a/README.md
+++ b/README.md
@@ -190,12 +190,20 @@ Real Madrid:
+Advertise Your Server:
+
+
+
+
+
+
Discord Advice Center:
+
Become a sponsor on [Patreon](https://patreon.com/kyber).
## Plugins
From 80dafcad0c689888d3e1a8e86f99b04f045ab7ed Mon Sep 17 00:00:00 2001
From: Taku 3 Animals <45324516+Taaku18@users.noreply.github.com>
Date: Sun, 7 Nov 2021 18:14:07 -0800
Subject: [PATCH 020/148] Update SPONSORS.json
---
SPONSORS.json | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/SPONSORS.json b/SPONSORS.json
index 30081e24e5..a1ec35d6dd 100644
--- a/SPONSORS.json
+++ b/SPONSORS.json
@@ -90,5 +90,20 @@
}
]
}
+ },
+ {
+ "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": "https://cdn.discordapp.com/attachments/472811257913933834/907068966311166043/unknown_2.png"
+ }
}
]
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 021/148] 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 022/148] 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 023/148] 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 @@
-
+
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 024/148] [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 @@
-
+
-
+
@@ -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 025/148] 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 a1aacbfb817f6410d9c8b4fce41bbd0e1e55b6b3 Mon Sep 17 00:00:00 2001
From: Yee Jia Rong <28086837+fourjr@users.noreply.github.com>
Date: Sat, 20 Nov 2021 19:07:11 +0200
Subject: [PATCH 026/148] Update bandit baseline:
---
.bandit_baseline.json | 60 +++++++++++++++++--------------------------
1 file changed, 24 insertions(+), 36 deletions(-)
diff --git a/.bandit_baseline.json b/.bandit_baseline.json
index 28a4e47b9c..76153c873f 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-20T17:06:28Z",
"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": 1406,
"nosec": 0
},
"./cogs/modmail.py": {
@@ -23,7 +23,7 @@
"SEVERITY.LOW": 0.0,
"SEVERITY.MEDIUM": 0.0,
"SEVERITY.UNDEFINED": 0.0,
- "loc": 1273,
+ "loc": 1678,
"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": 1768,
"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": 375,
"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": {
@@ -155,7 +155,7 @@
"SEVERITY.LOW": 0.0,
"SEVERITY.MEDIUM": 0.0,
"SEVERITY.UNDEFINED": 0.0,
- "loc": 996,
+ "loc": 1097,
"nosec": 0
},
"./core/time.py": {
@@ -167,7 +167,7 @@
"SEVERITY.LOW": 0.0,
"SEVERITY.MEDIUM": 0.0,
"SEVERITY.UNDEFINED": 0.0,
- "loc": 158,
+ "loc": 156,
"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": 351,
"nosec": 0
},
"_totals": {
@@ -203,20 +191,20 @@
"SEVERITY.LOW": 5.0,
"SEVERITY.MEDIUM": 1.0,
"SEVERITY.UNDEFINED": 0.0,
- "loc": 9214,
+ "loc": 9878,
"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": "12 from json import JSONDecodeError, loads\n13 from subprocess import PIPE\n14 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": 13,
"line_range": [
- 14
+ 13
],
"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": "2061 try:\n2062 exec(to_compile, env) # pylint: disable=exec-used\n2063 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": 2062,
"line_range": [
- 2040
+ 2062
],
"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 027/148] 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 028/148] 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 029/148] 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 030/148] 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 031/148] 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 @@
-
+
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 032/148] 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 033/148] 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 034/148] 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 @@
-
+
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 035/148] 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 036/148] 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 037/148] 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 038/148] 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 039/148] 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 040/148] 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 041/148] 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 042/148] 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 043/148] 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""
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 044/148] 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 045/148] 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 046/148] 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 047/148] 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 @@
-
+
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 048/148] 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 049/148] 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 050/148] 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 051/148] 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 052/148] 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 053/148] 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 054/148] 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 055/148] 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 056/148] 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 057/148] 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 058/148] 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 059/148] 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 060/148] 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 061/148] 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 062/148] 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 063/148] 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 064/148] 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 065/148] 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 066/148] 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 067/148] 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
Date: Sun, 5 Dec 2021 21:28:56 +0000
Subject: [PATCH 068/148] 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
Date: Sun, 5 Dec 2021 23:04:15 +0000
Subject: [PATCH 069/148] 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 9b58b99cbc2dc7deb84aad73bfbab09ed696ef80 Mon Sep 17 00:00:00 2001
From: Taku <45324516+Taaku18@users.noreply.github.com>
Date: Tue, 8 Feb 2022 01:59:54 -0800
Subject: [PATCH 070/148] 3.10.3 contact fix
---
CHANGELOG.md | 8 ++++++++
README.md | 2 +-
bot.py | 2 +-
core/models.py | 13 ++++++++-----
pyproject.toml | 2 +-
5 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index af6e0cc407..8f9b461169 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.
+# v3.10.3
+This is a hotfix for contact command.
+
+### Fixed
+
+- Fixed a bug where contacting with no category argument defaults to the top category.
+
+
# v3.10.2
This is a hotfix for react to contact.
diff --git a/README.md b/README.md
index 2b4f44ea62..465b13f1ab 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
-
+
diff --git a/bot.py b/bot.py
index 7d4248173c..0ee38be340 100644
--- a/bot.py
+++ b/bot.py
@@ -1,4 +1,4 @@
-__version__ = "3.10.2"
+__version__ = "3.10.3"
import asyncio
diff --git a/core/models.py b/core/models.py
index 445f7793ae..670a23c743 100644
--- a/core/models.py
+++ b/core/models.py
@@ -2,6 +2,7 @@
import re
import sys
import os
+from difflib import get_close_matches
from enum import IntEnum
from logging.handlers import RotatingFileHandler
from string import Formatter
@@ -202,13 +203,15 @@ async def convert(self, ctx, argument):
return await super().convert(ctx, argument)
except commands.ChannelNotFound:
- def check(c):
- return isinstance(c, discord.CategoryChannel) and c.name.lower().startswith(argument.lower())
-
if guild:
- result = discord.utils.find(check, guild.categories)
+ categories = {c.name.casefold(): c for c in guild.categories}
else:
- result = discord.utils.find(check, bot.get_all_channels())
+ categories = {c.name.casefold(): c for c in bot.get_all_channels()
+ if isinstance(c, discord.CategoryChannel)}
+
+ result = get_close_matches(argument.casefold(), categories.keys(), n=1, cutoff=0.75)
+ if result:
+ result = categories[result[0]]
if not isinstance(result, discord.CategoryChannel):
raise commands.ChannelNotFound(argument)
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 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 071/148] 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 d6a3982b823a6cd9cbcb979db5d8503d3edaad46 Mon Sep 17 00:00:00 2001
From: Taku 3 Animals <45324516+Taaku18@users.noreply.github.com>
Date: Mon, 28 Mar 2022 13:46:32 -0700
Subject: [PATCH 072/148] Update SPONSORS.json
---
SPONSORS.json | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/SPONSORS.json b/SPONSORS.json
index a1ec35d6dd..2cd08053ec 100644
--- a/SPONSORS.json
+++ b/SPONSORS.json
@@ -105,5 +105,27 @@
},
"image": "https://cdn.discordapp.com/attachments/472811257913933834/907068966311166043/unknown_2.png"
}
+ },
+ {
+ "embed": {
+ "footer": {
+ "text": "Join noch heute!"
+ },
+ "thumbnail": {
+ "url": "https://i.imgur.com/bp0xfyK.png"
+ },
+ "fields": [
+ {
+ "inline": false,
+ "name": "Viele Verschiedene Talks",
+ "value": "Gro\u00dfe Community\nGewinnspiele"
+ }
+ ],
+ "color": 61532,
+ "type": "rich",
+ "description": "Die etwas andere Community",
+ "url": "https://discord.gg/uncommon",
+ "title": "uncommon community"
+ }
}
]
From e0032fd9b9806db75f21167e2c50f36258fbbc99 Mon Sep 17 00:00:00 2001
From: Taku 3 Animals <45324516+Taaku18@users.noreply.github.com>
Date: Mon, 28 Mar 2022 13:47:43 -0700
Subject: [PATCH 073/148] Update SPONSORS.json
---
SPONSORS.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/SPONSORS.json b/SPONSORS.json
index 2cd08053ec..1177699d10 100644
--- a/SPONSORS.json
+++ b/SPONSORS.json
@@ -122,7 +122,6 @@
}
],
"color": 61532,
- "type": "rich",
"description": "Die etwas andere Community",
"url": "https://discord.gg/uncommon",
"title": "uncommon community"
From 57349c6eafa8c8af0f285bd907968669ac60439b Mon Sep 17 00:00:00 2001
From: Taku 3 Animals <45324516+Taaku18@users.noreply.github.com>
Date: Fri, 15 Apr 2022 17:45:28 -0700
Subject: [PATCH 074/148] Update sponsors list
---
README.md | 7 -------
1 file changed, 7 deletions(-)
diff --git a/README.md b/README.md
index 465b13f1ab..b95dc335a4 100644
--- a/README.md
+++ b/README.md
@@ -162,13 +162,6 @@ $ docker run --env-file .env kyb3rr/modmail
Special thanks to our sponsors for supporting the project.
-Kingdom Gaming Discord:
-
-
-
-
-
-
SirReddit:
From be14cca89742cd691f6b91f0d0931a074ad81e3b Mon Sep 17 00:00:00 2001
From: Taku 3 Animals <45324516+Taaku18@users.noreply.github.com>
Date: Fri, 15 Apr 2022 17:50:10 -0700
Subject: [PATCH 075/148] Update sponsors syntax issue
---
SPONSORS.json | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/SPONSORS.json b/SPONSORS.json
index 1177699d10..ce34dc3f9d 100644
--- a/SPONSORS.json
+++ b/SPONSORS.json
@@ -103,7 +103,9 @@
"footer": {
"text": "Grow Your Discord Server"
},
- "image": "https://cdn.discordapp.com/attachments/472811257913933834/907068966311166043/unknown_2.png"
+ "image": {
+ "url": "https://cdn.discordapp.com/attachments/472811257913933834/907068966311166043/unknown_2.png"
+ }
}
},
{
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 076/148] 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 077/148] 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 078/148] 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 079/148] 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 080/148] 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 081/148] 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 082/148] 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 083/148] 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 084/148] 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 085/148] 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 086/148] 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 087/148] 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 088/148] 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 089/148] 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 090/148] 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 091/148] 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 092/148] 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 093/148] 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 094/148] 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 095/148] 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 096/148] 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 097/148] 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 098/148] 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 099/148] 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 100/148] 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 101/148] 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 102/148] 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 103/148] 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 104/148] 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 105/148] 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 106/148] 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 107/148] 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 108/148] 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 109/148] 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
Date: Tue, 7 Jun 2022 00:52:22 +0000
Subject: [PATCH 110/148] 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
Date: Tue, 7 Jun 2022 14:36:09 +0000
Subject: [PATCH 111/148] 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 112/148] 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 113/148] 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 114/148] 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
Date: Sat, 25 Jun 2022 08:24:35 +0000
Subject: [PATCH 115/148] 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 116/148] 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 117/148] 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 118/148] 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 119/148] 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 120/148] 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 121/148] 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 122/148] 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 123/148] 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 124/148] 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 125/148] 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 126/148] 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 127/148] 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
Date: Wed, 24 Aug 2022 14:10:48 +0000
Subject: [PATCH 128/148] 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 129/148] 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: "
+ if after.dt > now:
+ reason += f" until "
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""
+ return f""
class ShortTime:
compiled = re.compile(
- r"""
- (?:(?P[0-9])(?:years?|y))? # e.g. 2y
- (?:(?P[0-9]{1,2})(?:months?|mo))? # e.g. 9mo
- (?:(?P[0-9]{1,4})(?:weeks?|w))? # e.g. 10w
- (?:(?P[0-9]{1,5})(?:days?|d))? # e.g. 14d
- (?:(?P[0-9]{1,5})(?:hours?|h))? # e.g. 12h
- (?:(?P[0-9]{1,5})(?:min(?:ute)?s?|m))? # e.g. 10m
- (?:(?P[0-9]{1,5})(?:sec(?:ond)?s?|s))? # e.g. 15s
- """,
+ """
+ (?:(?P[0-9])(?:years?|y))? # e.g. 2y
+ (?:(?P[0-9]{1,2})(?:months?|mo))? # e.g. 2months
+ (?:(?P[0-9]{1,4})(?:weeks?|w))? # e.g. 10w
+ (?:(?P[0-9]{1,5})(?:days?|d))? # e.g. 14d
+ (?:(?P[0-9]{1,5})(?:hours?|h))? # e.g. 12h
+ (?:(?P[0-9]{1,5})(?:minutes?|m))? # e.g. 10m
+ (?:(?P[0-9]{1,5})(?:seconds?|s))? # e.g. 15s
+ """,
re.VERBOSE,
)
- def __init__(self, argument):
+ discord_fmt = re.compile(r"[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""
+ 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 130/148] 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 131/148] 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 132/148] 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 133/148] 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 134/148] 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 135/148] 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 136/148] 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: "
- if after.dt > now:
+ if after.dt > after.now:
reason += f" until "
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 137/148] 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 138/148] 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 139/148] 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 140/148] 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 141/148] 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 ."
+ end_time = re.search(r"until .$", 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: "
+ fmt_dt = discord.utils.format_dt(after.dt, "R")
if after.dt > after.now:
- reason += f" until "
+ 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""
- return f""
-
-
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 142/148] 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 143/148] 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 ."
- end_time = re.search(r"until .$", 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 ."
+ now = discord.utils.utcnow()
+ end_time = re.search(r"until .$", 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 144/148] 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 145/148] 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 146/148] 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 147/148] 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 148/148] 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