Migrate to beanie

This commit is contained in:
Zeva Rose 2023-03-24 11:48:36 -06:00 committed by Zevaryx
parent 645432c0d4
commit c73732432b
31 changed files with 818 additions and 782 deletions

View file

@ -13,5 +13,6 @@ extend-ignore =
# Plugins we don't currently include: flake8-return
R502, # do not implicitly return None in function able to return non-None value.
R503, # missing explicit return at the end of function ableto return non-None value.
R504, # unnecessary variable assignment, causes issues with Config
R505, B023, # Temporary
max-line-length=100

View file

@ -8,12 +8,12 @@ from interactions import Intents
from jarvis_core.db import connect
from jarvis_core.log import get_logger
from redis import asyncio as aioredis
from statipy.db import init_db
from statipy.db import Stat, StaticStat
from jarvis import const
from jarvis.client import Jarvis
from jarvis.cogs import __path__ as cogs_path
from jarvis.config import JarvisConfig
from jarvis.config import load_config
from jarvis.utils import get_extensions
__version__ = const.__version__
@ -58,25 +58,25 @@ def jlogger(logger: logging.Logger, event: Any) -> None:
async def run() -> None:
"""Run JARVIS"""
# Configure logger
jconfig = JarvisConfig.from_yaml()
config = load_config()
logger = get_logger("jarvis", show_locals=False) # jconfig.log_level == "DEBUG")
logger.setLevel(jconfig.log_level)
logger.setLevel(config.log_level)
file_handler = logging.FileHandler(filename="jarvis.log", encoding="UTF-8", mode="w")
file_handler.setFormatter(logging.Formatter("[%(asctime)s] [%(name)s] [%(levelname)8s] %(message)s"))
logger.addHandler(file_handler)
# Configure client
intents = Intents.DEFAULT | Intents.MESSAGES | Intents.GUILD_MEMBERS | Intents.GUILD_MESSAGES
redis_config = jconfig.redis.copy()
redis_config = config.redis.dict()
redis_host = redis_config.pop("host")
redis = await aioredis.from_url(redis_host, decode_responses=True, **redis_config)
await init_db(**jconfig.mongo["connect"])
await connect(**config.mongo.dict(), testing=config.environment.value == "develop", extra_models=[StaticStat, Stat])
jarvis = Jarvis(
intents=intents,
sync_interactions=jconfig.sync,
sync_interactions=config.sync,
delete_unused_application_cmds=True,
send_command_tracebacks=False,
redis=redis,
@ -84,16 +84,15 @@ async def run() -> None:
)
# External modules
if jconfig.jurigged:
if config.jurigged:
logging.addLevelName(11, "\033[35mJURIG\033[0m ")
if jconfig.log_level == "INFO":
if config.log_level == "INFO":
logger.setLevel(11)
jurigged.watch(pattern="jarvis/*.py", logger=partial(jlogger, logger))
# Initialize bot
logger.info("Starting JARVIS")
logger.debug("Connecting to database")
connect(**jconfig.mongo["connect"], testing=jconfig.mongo["database"] != "jarvis")
logger.debug("Loading configuration from database")
# jconfig.get_db_config()
@ -106,6 +105,5 @@ async def run() -> None:
logger.debug("Loading statipy")
jarvis.load_extension("statipy.ext")
jarvis.max_messages = jconfig.max_messages
logger.debug("Running JARVIS")
await jarvis.astart(jconfig.token)
await jarvis.astart(config.token)

View file

@ -12,7 +12,6 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Autoreact
from jarvis.data.unicode import emoji_list
@ -41,7 +40,7 @@ class AutoReactCog(Extension):
Returns:
Tuple of success? and error message
"""
exists = await Autoreact.find_one(q(guild=ctx.guild.id, channel=channel.id))
exists = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id)
if exists:
return False, f"Autoreact already exists for {channel.mention}."
@ -51,7 +50,7 @@ class AutoReactCog(Extension):
reactions=[],
thread=thread,
admin=ctx.author.id,
).commit()
).save()
return True, None
@ -66,7 +65,7 @@ class AutoReactCog(Extension):
Returns:
Success?
"""
ar = await Autoreact.find_one(q(guild=ctx.guild.id, channel=channel.id))
ar = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id)
if ar:
await ar.delete()
return True
@ -105,10 +104,10 @@ class AutoReactCog(Extension):
if not find(lambda x: x.id == emoji_id, await ctx.guild.fetch_all_custom_emojis()):
await ctx.send("Please use a custom emote from this server.", ephemeral=True)
return
autoreact = await Autoreact.find_one(q(guild=ctx.guild.id, channel=channel.id))
autoreact = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id)
if not autoreact:
await self.create_autoreact(ctx, channel, thread)
autoreact = await Autoreact.find_one(q(guild=ctx.guild.id, channel=channel.id))
autoreact = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id)
if emote and emote in autoreact.reactions:
await ctx.send(
f"Emote already added to {channel.mention} autoreactions.",
@ -124,7 +123,7 @@ class AutoReactCog(Extension):
if emote:
autoreact.reactions.append(emote)
autoreact.thread = thread
await autoreact.commit()
await autoreact.save()
message = ""
if emote:
message += f" Added {emote} to {channel.mention} autoreact."
@ -149,7 +148,7 @@ class AutoReactCog(Extension):
)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _autoreact_remove(self, ctx: InteractionContext, channel: GuildText, emote: str) -> None:
autoreact = await Autoreact.find_one(q(guild=ctx.guild.id, channel=channel.id))
autoreact = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id)
if not autoreact:
await ctx.send(
f"Please create autoreact first with /autoreact add {channel.mention} {emote}",
@ -167,7 +166,7 @@ class AutoReactCog(Extension):
return
else:
autoreact.reactions.remove(emote)
await autoreact.commit()
await autoreact.save()
if len(autoreact.reactions) == 0 and not autoreact.thread:
await self.delete_autoreact(ctx, channel)
await ctx.send(f"Removed {emote} from {channel.mention} autoreact.")
@ -201,7 +200,7 @@ class AutoReactCog(Extension):
required=True,
)
async def _autoreact_list(self, ctx: InteractionContext, channel: GuildText) -> None:
exists = await Autoreact.find_one(q(guild=ctx.guild.id, channel=channel.id))
exists = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id)
if not exists:
await ctx.send(
f"Please create autoreact first with /autoreact add {channel.mention} <emote>",

View file

@ -15,7 +15,6 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Ban, Unban
from jarvis.branding import get_command_color
@ -53,7 +52,7 @@ class BanCog(ModcaseCog):
duration=duration,
active=active,
)
await b.commit()
await b.save()
embed = ban_embed(
user=user,
@ -77,7 +76,7 @@ class BanCog(ModcaseCog):
admin=ctx.author.id,
reason=reason,
)
await u.commit()
await u.save()
embed = unban_embed(user=user, admin=ctx.author, reason=reason)
@ -248,7 +247,9 @@ class BanCog(ModcaseCog):
# We take advantage of the previous checks to save CPU cycles
if not discord_ban_info:
if isinstance(user, User):
database_ban_info = await Ban.find_one(q(guild=ctx.guild.id, user=user.id, active=True))
database_ban_info = await Ban.find_one(
Ban.guild == ctx.guild.id, Ban.user == user.id, Ban.active is True
)
else:
search = {
"guild": ctx.guild.id,
@ -257,7 +258,8 @@ class BanCog(ModcaseCog):
}
if discrim:
search["discrim"] = discrim
database_ban_info = await Ban.find_one(q(**search))
database_ban_info = await Ban.find_one(*[getattr(Ban, k) == v for k, v in search.items])
if not discord_ban_info and not database_ban_info:
await ctx.send(f"Unable to find user {orig_user}", ephemeral=True)
@ -311,7 +313,7 @@ class BanCog(ModcaseCog):
search["active"] = True
if btype > 0:
search["type"] = types[btype]
bans = await Ban.find(search).sort([("created_at", -1)]).to_list(None)
bans = await Ban.find(*[getattr(Ban, k) == v for k, v in search.items]).sort(-Ban.created_at).to_list()
db_bans = []
fields = []
for ban in bans:

View file

@ -18,7 +18,6 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Filter
from thefuzz import process
@ -36,7 +35,7 @@ class FilterCog(Extension):
content = ""
f: Filter = None
if search:
if f := await Filter.find_one(q(name=name, guild=ctx.guild.id)):
if f := await Filter.find_one(Filter.name == name, Filter.guild == ctx.guild.id):
content = "\n".join(f.filters)
kw = "Updating" if search else "Creating"
@ -68,7 +67,7 @@ class FilterCog(Extension):
else:
f.name = new_name
f.filters = filters
await f.commit()
await f.save()
except Exception as e:
await data.send(f"{e}", ephemeral=True)
return
@ -114,7 +113,7 @@ class FilterCog(Extension):
required=True,
)
async def _filter_view(self, ctx: InteractionContext, name: str) -> None:
f = await Filter.find_one(q(name=name, guild=ctx.guild.id))
f = await Filter.find_one(Filter.name == name, Filter.guild == ctx.guild.id)
if not f:
await ctx.send("That filter doesn't exist", ephemeral=True)
return
@ -133,7 +132,7 @@ class FilterCog(Extension):
)
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
async def _filter_delete(self, ctx: InteractionContext, name: str) -> None:
f = await Filter.find_one(q(name=name, guild=ctx.guild.id))
f = await Filter.find_one(Filter.name == name, Filter.guild == ctx.guild.id)
if not f:
await ctx.send("That filter doesn't exist", ephemeral=True)
return
@ -151,7 +150,7 @@ class FilterCog(Extension):
@_filter_delete.autocomplete("name")
async def _autocomplete(self, ctx: AutocompleteContext, name: str) -> None:
if not self.cache.get(ctx.guild.id):
filters = await Filter.find(q(guild=ctx.guild.id)).to_list(None)
filters = await Filter.find(Filter.guild == ctx.guild.id).to_list()
self.cache[ctx.guild.id] = [f.name for f in filters]
results = process.extract(name, self.cache.get(ctx.guild.id), limit=25)
choices = [{"name": r[0], "value": r[0]} for r in results]

View file

@ -55,5 +55,5 @@ class KickCog(ModcaseCog):
admin=ctx.author.id,
guild=ctx.guild.id,
)
await k.commit()
await k.save()
await ctx.send(embeds=embed)

View file

@ -12,7 +12,6 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Lock, Permission
from jarvis.utils.permissions import admin_or_permissions
@ -82,7 +81,7 @@ class LockCog(Extension):
reason=reason,
duration=duration,
original_perms=current,
).commit()
).save()
await ctx.send(f"{channel.mention} locked for {duration} minute(s)")
@slash_command(name="unlock", description="Unlock a channel")
@ -100,7 +99,7 @@ class LockCog(Extension):
) -> None:
if not channel:
channel = ctx.channel
lock = await Lock.find_one(q(guild=ctx.guild.id, channel=channel.id, active=True))
lock = await Lock.find_one(Lock.guild == ctx.guild.id, Lock.channel == channel.id, Lock.active is True)
if not lock:
await ctx.send(f"{channel.mention} not locked.", ephemeral=True)
return
@ -114,5 +113,5 @@ class LockCog(Extension):
await channel.delete_permission(target=overwrite, reason="Unlock")
lock.active = False
await lock.commit()
await lock.save()
await ctx.send(f"{channel.mention} unlocked")

View file

@ -13,7 +13,6 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Lock, Lockdown, Permission
from jarvis.utils.permissions import admin_or_permissions
@ -41,7 +40,7 @@ async def lock(bot: Client, target: GuildChannel, admin: Member, reason: str, du
reason=reason,
duration=duration,
original_perms=current,
).commit()
).save()
async def lock_all(bot: Client, guild: Guild, admin: Member, reason: str, duration: int) -> None:
@ -73,7 +72,7 @@ async def unlock_all(bot: Client, guild: Guild, admin: Member) -> None:
target: Target channel
admin: Admin who ended lockdown
"""
locks = Lock.find(q(guild=guild.id, active=True))
locks = Lock.find(Lock.guild == guild.id, Lock.active is True)
async for lock in locks:
target = await guild.fetch_channel(lock.channel)
if target:
@ -85,11 +84,11 @@ async def unlock_all(bot: Client, guild: Guild, admin: Member) -> None:
elif overwrite and not lock.original_perms:
await target.delete_permission(target=overwrite, reason="Lockdown end")
lock.active = False
await lock.commit()
lockdown = await Lockdown.find_one(q(guild=guild.id, active=True))
await lock.save()
lockdown = await Lockdown.find_one(Lockdown.guild == guild.id, Lockdown.active is True)
if lockdown:
lockdown.active = False
await lockdown.commit()
await lockdown.save()
class LockdownCog(Extension):
@ -130,7 +129,7 @@ class LockdownCog(Extension):
await ctx.send("Duration must be <= 7 days", ephemeral=True)
return
exists = await Lockdown.find_one(q(guild=ctx.guild.id, active=True))
exists = await Lockdown.find_one(Lockdown.guild == ctx.guild.id, Lockdown.active is True)
if exists:
await ctx.send("Server already in lockdown", ephemeral=True)
return
@ -146,7 +145,7 @@ class LockdownCog(Extension):
guild=ctx.guild.id,
reason=reason,
original_perms=int(original_perms),
).commit()
).save()
await ctx.send("Server now in lockdown.")
@lockdown.subcommand(sub_cmd_name="end", sub_cmd_description="End a lockdown")
@ -157,7 +156,7 @@ class LockdownCog(Extension):
) -> None:
await ctx.defer()
lockdown = await Lockdown.find_one(q(guild=ctx.guild.id, active=True))
lockdown = await Lockdown.find_one(Lockdown.guild == ctx.guild.id, Lockdown.active is True)
if not lockdown:
await ctx.send("Server not in lockdown", ephemeral=True)
return

View file

@ -11,7 +11,6 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Modlog, Note, actions
from rich.console import Console
from rich.table import Table
@ -56,7 +55,8 @@ class CaseCog(Extension):
action_output = ""
action_output_extra = ""
for idx, action in enumerate(mod_case.actions):
parent_action = await ACTIONS_LOOKUP[action.action_type].find_one(q(id=action.parent))
atype = ACTIONS_LOOKUP[action.action_type]
parent_action = await atype.find_one(atype.id == action.parent)
if not parent_action:
action.orphaned = True
action_table.add_row(action.action_type.title(), "[N/A]", "[N/A]")
@ -155,7 +155,8 @@ class CaseCog(Extension):
for action in mod_case.actions:
if action.orphaned:
continue
parent_action = await ACTIONS_LOOKUP[action.action_type].find_one(q(id=action.parent))
atype = ACTIONS_LOOKUP[action.action_type]
parent_action = await atype.find_one(atype.id == action.parent)
if not parent_action:
action.orphaned = True
continue
@ -195,12 +196,13 @@ class CaseCog(Extension):
)
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
async def _cases_list(self, ctx: InteractionContext, user: Optional[Member] = None, closed: bool = False) -> None:
query = q(guild=ctx.guild.id)
query = [Modlog.guild == ctx.guild.id]
if not closed:
query.update(q(open=True))
query.append(Modlog.open is True)
if user:
query.update(q(user=user.id))
cases = await Modlog.find(query).sort("created_at", -1).to_list(None)
query.append(Modlog.user == user.id)
cases = await Modlog.find(*query).sort(+Modlog.created_at).to_list()
if len(cases) == 0:
await ctx.send("No cases to view", ephemeral=True)
@ -217,7 +219,7 @@ class CaseCog(Extension):
@slash_option(name="cid", description="Case ID", opt_type=OptionType.STRING, required=True)
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
async def _case_show_summary(self, ctx: InteractionContext, cid: str) -> None:
case = await Modlog.find_one(q(guild=ctx.guild.id, nanoid=cid))
case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.nanoid == cid)
if not case:
await ctx.send(f"Could not find case with ID {cid}", ephemeral=True)
return
@ -229,7 +231,7 @@ class CaseCog(Extension):
@slash_option(name="cid", description="Case ID", opt_type=OptionType.STRING, required=True)
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
async def _case_show_actions(self, ctx: InteractionContext, cid: str) -> None:
case = await Modlog.find_one(q(guild=ctx.guild.id, nanoid=cid))
case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.nanoid == cid)
if not case:
await ctx.send(f"Could not find case with ID {cid}", ephemeral=True)
return
@ -242,13 +244,13 @@ class CaseCog(Extension):
@slash_option(name="cid", description="Case ID", opt_type=OptionType.STRING, required=True)
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
async def _case_close(self, ctx: InteractionContext, cid: str) -> None:
case = await Modlog.find_one(q(guild=ctx.guild.id, nanoid=cid))
case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.nanoid == cid)
if not case:
await ctx.send(f"Could not find case with ID {cid}", ephemeral=True)
return
case.open = False
await case.commit()
await case.save()
embed = await self.get_summary_embed(case, ctx.guild)
await ctx.send(embeds=embed)
@ -257,13 +259,13 @@ class CaseCog(Extension):
@slash_option(name="cid", description="Case ID", opt_type=OptionType.STRING, required=True)
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
async def _case_reopen(self, ctx: InteractionContext, cid: str) -> None:
case = await Modlog.find_one(q(guild=ctx.guild.id, nanoid=cid))
case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.nanoid == cid)
if not case:
await ctx.send(f"Could not find case with ID {cid}", ephemeral=True)
return
case.open = True
await case.commit()
await case.save()
embed = await self.get_summary_embed(case, ctx.guild)
await ctx.send(embeds=embed)
@ -273,7 +275,7 @@ class CaseCog(Extension):
@slash_option(name="note", description="Note to add", opt_type=OptionType.STRING, required=True)
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
async def _case_note(self, ctx: InteractionContext, cid: str, note: str) -> None:
case = await Modlog.find_one(q(guild=ctx.guild.id, nanoid=cid))
case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.nanoid == cid)
if not case:
await ctx.send(f"Could not find case with ID {cid}", ephemeral=True)
return
@ -289,7 +291,7 @@ class CaseCog(Extension):
note = Note(admin=ctx.author.id, content=note)
case.notes.append(note)
await case.commit()
await case.save()
embed = await self.get_summary_embed(case, ctx.guild)
await ctx.send(embeds=embed)
@ -299,7 +301,7 @@ class CaseCog(Extension):
@slash_option(name="note", description="Note to add", opt_type=OptionType.STRING, required=True)
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
async def _case_new(self, ctx: InteractionContext, user: Member, note: str) -> None:
case = await Modlog.find_one(q(guild=ctx.guild.id, user=user.id, open=True))
case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.user == user.id, Modlog.open is True)
if case:
await ctx.send(f"Case already open with ID `{case.nanoid}`", ephemeral=True)
return
@ -315,8 +317,7 @@ class CaseCog(Extension):
note = Note(admin=ctx.author.id, content=note)
case = Modlog(user=user.id, guild=ctx.guild.id, admin=ctx.author.id, notes=[note], actions=[])
await case.commit()
await case.reload()
await case.save()
embed = await self.get_summary_embed(case, ctx.guild)
await ctx.send(embeds=embed)

View file

@ -37,7 +37,7 @@ class MuteCog(ModcaseCog):
guild=ctx.guild.id,
duration=duration,
active=True,
).commit()
).save()
return mute_embed(user=user, admin=ctx.author, reason=reason, guild=ctx.guild)

View file

@ -9,7 +9,6 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Autopurge, Purge
from jarvis.utils.permissions import admin_or_permissions
@ -45,7 +44,7 @@ class PurgeCog(Extension):
guild=ctx.guild.id,
admin=ctx.author.id,
count=amount,
).commit()
).save()
@slash_command(name="autopurge", sub_cmd_name="add", sub_cmd_description="Automatically purge messages")
@slash_option(
@ -72,7 +71,7 @@ class PurgeCog(Extension):
await ctx.send("Delay must be < 5 minutes", ephemeral=True)
return
autopurge = await Autopurge.find_one(q(guild=ctx.guild.id, channel=channel.id))
autopurge = await Autopurge.find_one(Autopurge.guild == ctx.guild.id, Autopurge.channel == channel.id)
if autopurge:
await ctx.send("Autopurge already exists.", ephemeral=True)
return
@ -82,7 +81,7 @@ class PurgeCog(Extension):
channel=channel.id,
admin=ctx.author.id,
delay=delay,
).commit()
).save()
await ctx.send(f"Autopurge set up on {channel.mention}, delay is {delay} seconds")
@ -95,7 +94,7 @@ class PurgeCog(Extension):
)
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
async def _autopurge_remove(self, ctx: InteractionContext, channel: GuildText) -> None:
autopurge = await Autopurge.find_one(q(guild=ctx.guild.id, channel=channel.id))
autopurge = await Autopurge.find_one(Autopurge.guild == ctx.guild.id, Autopurge.channel == channel.id)
if not autopurge:
await ctx.send("Autopurge does not exist.", ephemeral=True)
return
@ -121,12 +120,12 @@ class PurgeCog(Extension):
)
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
async def _autopurge_update(self, ctx: InteractionContext, channel: GuildText, delay: int) -> None:
autopurge = await Autopurge.find_one(q(guild=ctx.guild.id, channel=channel.id))
autopurge = await Autopurge.find_one(Autopurge.guild == ctx.guild.id, Autopurge.channel == channel.id)
if not autopurge:
await ctx.send("Autopurge does not exist.", ephemeral=True)
return
autopurge.delay = delay
await autopurge.commit()
await autopurge.save()
await ctx.send(f"Autopurge delay updated to {delay} seconds on {channel.mention}.")

View file

@ -13,8 +13,7 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Roleping
from jarvis_core.db.models import Bypass, Roleping
from jarvis.utils import build_embed
from jarvis.utils.permissions import admin_or_permissions
@ -36,7 +35,7 @@ class RolepingCog(Extension):
@slash_option(name="role", description="Role to add", opt_type=OptionType.ROLE, required=True)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _roleping_add(self, ctx: InteractionContext, role: Role) -> None:
roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
roleping = await Roleping.find_one(Roleping.guild == ctx.guild.id, Roleping.role == role.id)
if roleping:
await ctx.send(f"Role `{role.name}` already in roleping.", ephemeral=True)
return
@ -50,15 +49,15 @@ class RolepingCog(Extension):
guild=ctx.guild.id,
admin=ctx.author.id,
active=True,
bypass={"roles": [], "users": []},
).commit()
bypass=Bypass(),
).save()
await ctx.send(f"Role `{role.name}` added to roleping.")
@roleping.subcommand(sub_cmd_name="remove", sub_cmd_description="Remove a role")
@slash_option(name="role", description="Role to remove", opt_type=OptionType.ROLE, required=True)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _roleping_remove(self, ctx: InteractionContext, role: Role) -> None:
roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
roleping = await Roleping.find_one(Roleping.guild == ctx.guild.id, Roleping.role == role.id)
if not roleping:
await ctx.send("Roleping does not exist", ephemeral=True)
return
@ -71,8 +70,7 @@ class RolepingCog(Extension):
@roleping.subcommand(sub_cmd_name="list", sub_cmd_description="Lick all blocklisted roles")
async def _roleping_list(self, ctx: InteractionContext) -> None:
rolepings = await Roleping.find(q(guild=ctx.guild.id)).to_list(None)
rolepings = await Roleping.find(Roleping.guild == ctx.guild.id).to_list()
if not rolepings:
await ctx.send("No rolepings configured", ephemeral=True)
return
@ -83,10 +81,10 @@ class RolepingCog(Extension):
if not role:
await roleping.delete()
continue
broles = find_all(lambda x: x.id in roleping.bypass["roles"], ctx.guild.roles) # noqa: B023
broles = find_all(lambda x: x.id in roleping.bypass.roles, ctx.guild.roles) # noqa: B023
bypass_roles = [r.mention or "||`[redacted]`||" for r in broles]
bypass_users = [
(await ctx.guild.fetch_member(u)).mention or "||`[redacted]`||" for u in roleping.bypass["users"]
(await ctx.guild.fetch_member(u)).mention or "||`[redacted]`||" for u in roleping.bypass.users
]
bypass_roles = bypass_roles or ["None"]
bypass_users = bypass_users or ["None"]
@ -137,23 +135,23 @@ class RolepingCog(Extension):
@slash_option(name="role", description="Rolepinged role", opt_type=OptionType.ROLE, required=True)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _roleping_bypass_user(self, ctx: InteractionContext, bypass: Member, role: Role) -> None:
roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
roleping = await Roleping.find_one(Roleping.guild == ctx.guild.id, role=role.id)
if not roleping:
await ctx.send(f"Roleping not configured for {role.mention}", ephemeral=True)
return
if bypass.id in roleping.bypass["users"]:
if bypass.id in roleping.bypass.users:
await ctx.send(f"{bypass.mention} already in bypass", ephemeral=True)
return
if len(roleping.bypass["users"]) == 10:
if len(roleping.bypass.users) == 10:
await ctx.send(
"Already have 10 users in bypass. Please consider using roles for roleping bypass",
ephemeral=True,
)
return
matching_role = list(filter(lambda x: x.id in roleping.bypass["roles"], bypass.roles))
matching_role = list(filter(lambda x: x.id in roleping.bypass.roles, bypass.roles))
if matching_role:
await ctx.send(
@ -162,8 +160,8 @@ class RolepingCog(Extension):
)
return
roleping.bypass["users"].append(bypass.id)
await roleping.commit()
roleping.bypass.users.append(bypass.id)
await roleping.save()
await ctx.send(f"{bypass.display_name} user bypass added for `{role.name}`")
@bypass.subcommand(
@ -177,24 +175,24 @@ class RolepingCog(Extension):
if bypass.id == ctx.guild.id:
await ctx.send("Cannot add `@everyone` as a bypass", ephemeral=True)
return
roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
roleping = await Roleping.find_one(Roleping.guild == ctx.guild.id, Roleping.role == role.id)
if not roleping:
await ctx.send(f"Roleping not configured for {role.mention}", ephemeral=True)
return
if bypass.id in roleping.bypass["roles"]:
if bypass.id in roleping.bypass.roles:
await ctx.send(f"{bypass.mention} already in bypass", ephemeral=True)
return
if len(roleping.bypass["roles"]) == 10:
if len(roleping.bypass.roles) == 10:
await ctx.send(
"Already have 10 roles in bypass. " "Please consider consolidating roles for roleping bypass",
ephemeral=True,
)
return
roleping.bypass["roles"].append(bypass.id)
await roleping.commit()
roleping.bypass.roles.append(bypass.id)
await roleping.save()
await ctx.send(f"{bypass.name} role bypass added for `{role.name}`")
restore = roleping.group(name="restore", description="Remove a roleping bypass")
@ -207,7 +205,7 @@ class RolepingCog(Extension):
@slash_option(name="role", description="Rolepinged role", opt_type=OptionType.ROLE, required=True)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _roleping_restore_user(self, ctx: InteractionContext, bypass: Member, role: Role) -> None:
roleping: Roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
roleping: Roleping = await Roleping.find_one(Roleping.guild == ctx.guild.id, Roleping.role == role.id)
if not roleping:
await ctx.send(f"Roleping not configured for {role.mention}", ephemeral=True)
return
@ -217,7 +215,7 @@ class RolepingCog(Extension):
return
roleping.bypass.users.remove(bypass.id)
await roleping.commit()
await roleping.save()
await ctx.send(f"{bypass.display_name} user bypass removed for `{role.name}`")
@restore.subcommand(
@ -228,7 +226,7 @@ class RolepingCog(Extension):
@slash_option(name="role", description="Rolepinged role", opt_type=OptionType.ROLE, required=True)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _roleping_restore_role(self, ctx: InteractionContext, bypass: Role, role: Role) -> None:
roleping: Roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
roleping: Roleping = await Roleping.find_one(Roleping.guild == ctx.guild.id, Roleping.role == role.id)
if not roleping:
await ctx.send(f"Roleping not configured for {role.mention}", ephemeral=True)
return
@ -238,5 +236,5 @@ class RolepingCog(Extension):
return
roleping.bypass.roles.remove(bypass.id)
await roleping.commit()
await roleping.save()
await ctx.send(f"{bypass.display_name} user bypass removed for `{role.name}`")

View file

@ -15,7 +15,6 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Setting
from thefuzz import process
@ -32,17 +31,17 @@ class SettingsCog(Extension):
async def update_settings(self, setting: str, value: Any, guild: int) -> bool:
"""Update a guild setting."""
existing = await Setting.find_one(q(setting=setting, guild=guild))
existing = await Setting.find_one(Setting.setting == setting, Setting.guild == guild)
if not existing:
existing = Setting(setting=setting, guild=guild, value=value)
existing.value = value
updated = await existing.commit()
updated = await existing.save()
return updated is not None
async def delete_settings(self, setting: str, guild: int) -> bool:
"""Delete a guild setting."""
existing = await Setting.find_one(q(setting=setting, guild=guild))
existing = await Setting.find_one(Setting.setting == setting, Setting.guild == guild)
if existing:
return await existing.delete()
return False
@ -152,7 +151,7 @@ class SettingsCog(Extension):
if not isinstance(channel, GuildText):
await ctx.send("Channel must be a GuildText", ephemeral=True)
return
setting = await Setting.find_one(q(guild=ctx.guild.id, setting="log_ignore"))
setting: Setting = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "log_ignore")
if not setting:
setting = Setting(guild=ctx.guild.id, setting="log_ignore", value=[])
if not setting.value:
@ -161,7 +160,7 @@ class SettingsCog(Extension):
await ctx.send("Channel already ignored", ephemeral=True)
return
setting.value.append(channel.id)
await setting.commit(replace=True)
await setting.save()
await ctx.send("Channel added to ActivityLog ignore list")
# Unset
@ -231,17 +230,17 @@ class SettingsCog(Extension):
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _remove_log_ignore(self, ctx: InteractionContext, channel: str) -> None:
channel = int(channel)
setting = await Setting.find_one(q(guild=ctx.guild.id, setting="log_ignore"))
setting = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "log_ignore")
if not setting or channel not in setting.value:
await ctx.send("Channel not being ignored", ephemeral=True)
return
setting.value.remove(channel)
await setting.commit(replace=True)
await setting.save()
await ctx.send("Channel no longer being ignored")
@_remove_log_ignore.autocomplete(option_name="channel")
async def _channel_search(self, ctx: AutocompleteContext, channel: str) -> None:
setting = await Setting.find_one(q(guild=ctx.guild.id, setting="log_ignore"))
setting = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "log_ignore")
if not setting:
return {}
channels = [ctx.guild.get_channel(x) for x in setting.value]
@ -252,7 +251,7 @@ class SettingsCog(Extension):
@settings.subcommand(sub_cmd_name="view", sub_cmd_description="View settings")
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _view(self, ctx: InteractionContext) -> None:
settings = Setting.find(q(guild=ctx.guild.id))
settings = Setting.find(Setting.guild == ctx.guild.id)
fields = []
async for setting in settings:
@ -305,7 +304,7 @@ class SettingsCog(Extension):
timeout=60 * 5,
)
if context.ctx.custom_id == f"{ctx.guild.id}|set_clear|yes":
async for setting in Setting.find(q(guild=ctx.guild.id)):
async for setting in Setting.find(Setting.guild == ctx.guild.id):
await setting.delete()
content = "Guild settings cleared"
else:

View file

@ -92,9 +92,7 @@ class TemproleCog(Extension):
return
await user.add_role(role, reason=reason)
await Temprole(
guild=ctx.guild.id, user=user.id, role=role.id, admin=ctx.author.id, expires_at=duration
).commit()
await Temprole(guild=ctx.guild.id, user=user.id, role=role.id, admin=ctx.author.id, expires_at=duration).save()
ts = int(duration.timestamp())

View file

@ -8,7 +8,6 @@ from interactions.models.discord.components import Button, ButtonStyle, spread_t
from interactions.models.internal.application_commands import slash_command
from interactions.models.internal.command import cooldown
from interactions.models.internal.cooldowns import Buckets
from jarvis_core.db import q
from jarvis_core.db.models import Setting
@ -40,7 +39,7 @@ class VerifyCog(Extension):
@slash_command(name="verify", description="Verify that you've read the rules")
@cooldown(bucket=Buckets.USER, rate=1, interval=30)
async def _verify(self, ctx: InteractionContext) -> None:
role = await Setting.find_one(q(guild=ctx.guild.id, setting="verified"))
role = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "verified")
if not role:
message = await ctx.send("This guild has not enabled verification", ephemeral=True)
return
@ -73,13 +72,13 @@ class VerifyCog(Extension):
for row in components:
for component in row.components:
component.disabled = True
setting = await Setting.find_one(q(guild=ctx.guild.id, setting="verified"))
setting = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "verified")
try:
role = await ctx.guild.fetch_role(setting.value)
await ctx.author.add_role(role, reason="Verification passed")
except AttributeError:
self.logger.warning("Verified role deleted before verification finished")
setting = await Setting.find_one(q(guild=ctx.guild.id, setting="unverified"))
setting = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "unverified")
if setting:
try:
role = await ctx.guild.fetch_role(setting.value)

View file

@ -12,7 +12,6 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Warning
from jarvis.embeds.admin import warning_embed
@ -62,7 +61,7 @@ class WarningCog(ModcaseCog):
duration=duration,
expires_at=expires_at,
active=True,
).commit()
).save()
embed = warning_embed(user, reason, ctx.author)
await ctx.send(embeds=embed)
@ -78,13 +77,11 @@ class WarningCog(ModcaseCog):
async def _warnings(self, ctx: InteractionContext, user: Member, active: bool = True) -> None:
warnings = (
await Warning.find(
q(
user=user.id,
guild=ctx.guild.id,
)
Warning.user == user.id,
Warning.guild == ctx.guild.id,
)
.sort("created_at", -1)
.to_list(None)
.sort(-Warning.created_at)
.to_list()
)
if len(warnings) == 0:
await ctx.send("That user has no warnings.", ephemeral=True)

View file

@ -18,7 +18,6 @@ from interactions.models.internal.application_commands import (
SlashCommand,
slash_option,
)
from jarvis_core.db import q
from jarvis_core.db.models import Reminder
from thefuzz import process
@ -205,7 +204,7 @@ class RemindmeCog(Extension):
@reminders.subcommand(sub_cmd_name="list", sub_cmd_description="List reminders")
async def _list(self, ctx: InteractionContext) -> None:
reminders = await Reminder.find(q(user=ctx.author.id, active=True)).to_list(None)
reminders = await Reminder.find(Reminder.user == ctx.author.id, Reminder.active is True).to_list()
if not reminders:
await ctx.send("You have no reminders set.", ephemeral=True)
return
@ -223,7 +222,7 @@ class RemindmeCog(Extension):
autocomplete=True,
)
async def _delete(self, ctx: InteractionContext, content: str) -> None:
reminder = await Reminder.find_one(q(_id=content))
reminder = await Reminder.find_one(Reminder.id == content)
if not reminder:
await ctx.send(f"Reminder `{content}` does not exist", ephemeral=True)
return
@ -263,7 +262,7 @@ class RemindmeCog(Extension):
autocomplete=True,
)
async def _fetch(self, ctx: InteractionContext, content: str) -> None:
reminder = await Reminder.find_one(q(_id=content))
reminder = await Reminder.find_one(Reminder.id == content)
if not reminder:
await ctx.send(f"Reminder `{content}` does not exist", ephemeral=True)
return
@ -294,7 +293,7 @@ class RemindmeCog(Extension):
@_fetch.autocomplete("content")
@_delete.autocomplete("content")
async def _search_reminders(self, ctx: AutocompleteContext, content: str) -> None:
reminders = await Reminder.find(q(user=ctx.author.id)).to_list(None)
reminders = await Reminder.find(Reminder.user == ctx.author.id).to_list()
lookup = {r.message: str(r.id) for r in reminders}
results = process.extract(content, list(lookup.keys()), limit=5)
choices = [{"name": r[0], "value": lookup[r[0]]} for r in results]

View file

@ -24,17 +24,10 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import (
Redditor,
RedditorFollow,
Subreddit,
SubredditFollow,
UserSetting,
)
from jarvis_core.db.models import Subreddit, SubredditFollow, UserSetting
from jarvis import const
from jarvis.config import JarvisConfig
from jarvis.config import load_config
from jarvis.utils import build_embed
from jarvis.utils.permissions import admin_or_permissions
@ -50,9 +43,9 @@ class RedditCog(Extension):
def __init__(self, bot: Client):
self.bot = bot
self.logger = logging.getLogger(__name__)
config = JarvisConfig.from_yaml()
config.reddit["user_agent"] = config.reddit.get("user_agent", DEFAULT_USER_AGENT)
self.api = Reddit(**config.reddit)
config = load_config()
config.reddit.user_agent = config.reddit.user_agent or DEFAULT_USER_AGENT
self.api = Reddit(**config.reddit.dict())
async def post_embeds(self, sub: Sub, post: Submission) -> Optional[List[Embed]]:
"""
@ -139,117 +132,122 @@ class RedditCog(Extension):
follow = reddit.group(name="follow", description="Add a follow")
unfollow = reddit.group(name="unfollow", description="Remove a follow")
@follow.subcommand(sub_cmd_name="redditor", sub_cmd_description="Follow a Redditor")
@slash_option(
name="name",
description="Redditor name",
opt_type=OptionType.STRING,
required=True,
)
@slash_option(
name="channel",
description="Channel to post to",
opt_type=OptionType.CHANNEL,
channel_types=[ChannelType.GUILD_TEXT],
required=True,
)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _redditor_follow(self, ctx: InteractionContext, name: str, channel: GuildText) -> None:
if not user_name.match(name):
await ctx.send("Invalid Redditor name", ephemeral=True)
return
# Due to bugs and missing models, this section is commented out for the time being
# TODO:
# 1. Fix bugs
# 2. Migrate to beanie
#
# @follow.subcommand(sub_cmd_name="redditor", sub_cmd_description="Follow a Redditor")
# @slash_option(
# name="name",
# description="Redditor name",
# opt_type=OptionType.STRING,
# required=True,
# )
# @slash_option(
# name="channel",
# description="Channel to post to",
# opt_type=OptionType.CHANNEL,
# channel_types=[ChannelType.GUILD_TEXT],
# required=True,
# )
# @check(admin_or_permissions(Permissions.MANAGE_GUILD))
# async def _redditor_follow(self, ctx: InteractionContext, name: str, channel: GuildText) -> None:
# if not user_name.match(name):
# await ctx.send("Invalid Redditor name", ephemeral=True)
# return
if not isinstance(channel, GuildText):
await ctx.send("Channel must be a text channel", ephemeral=True)
return
# if not isinstance(channel, GuildText):
# await ctx.send("Channel must be a text channel", ephemeral=True)
# return
try:
redditor = await self.api.redditor(name)
await redditor.load()
except (NotFound, Forbidden, Redirect) as e:
self.logger.debug(f"Redditor {name} raised {e.__class__.__name__} on add")
await ctx.send("Redditor may be deleted or nonexistent.", ephemeral=True)
return
# try:
# redditor = await self.api.redditor(name)
# await redditor.load()
# except (NotFound, Forbidden, Redirect) as e:
# self.logger.debug(f"Redditor {name} raised {e.__class__.__name__} on add")
# await ctx.send("Redditor may be deleted or nonexistent.", ephemeral=True)
# return
exists = await RedditorFollow.find_one(q(name=redditor.name, guild=ctx.guild.id))
if exists:
await ctx.send("Redditor already being followed in this guild", ephemeral=True)
return
# exists = await RedditorFollow.find_one(q(name=redditor.name, guild=ctx.guild.id))
# if exists:
# await ctx.send("Redditor already being followed in this guild", ephemeral=True)
# return
count = len([i async for i in SubredditFollow.find(q(guild=ctx.guild.id))])
if count >= 12:
await ctx.send("Cannot follow more than 12 Redditors", ephemeral=True)
return
# count = len([i async for i in SubredditFollow.find(q(guild=ctx.guild.id))])
# if count >= 12:
# await ctx.send("Cannot follow more than 12 Redditors", ephemeral=True)
# return
sr = await Redditor.find_one(q(name=redditor.name))
if not sr:
sr = Redditor(name=redditor.name)
await sr.commit()
# sr = await Redditor.find_one(q(name=redditor.name))
# if not sr:
# sr = Redditor(name=redditor.name)
# await sr.commit()
srf = RedditorFollow(
name=redditor.name,
channel=channel.id,
guild=ctx.guild.id,
admin=ctx.author.id,
)
await srf.commit()
# srf = RedditorFollow(
# name=redditor.name,
# channel=channel.id,
# guild=ctx.guild.id,
# admin=ctx.author.id,
# )
# await srf.commit()
await ctx.send(f"Now following `u/{name}` in {channel.mention}")
# await ctx.send(f"Now following `u/{name}` in {channel.mention}")
@unfollow.subcommand(sub_cmd_name="redditor", sub_cmd_description="Unfollow Redditor")
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _redditor_unfollow(self, ctx: InteractionContext) -> None:
subs = RedditorFollow.find(q(guild=ctx.guild.id))
redditors = []
async for sub in subs:
redditors.append(sub)
if not redditors:
await ctx.send("You need to follow a redditor first", ephemeral=True)
return
# @unfollow.subcommand(sub_cmd_name="redditor", sub_cmd_description="Unfollow Redditor")
# @check(admin_or_permissions(Permissions.MANAGE_GUILD))
# async def _redditor_unfollow(self, ctx: InteractionContext) -> None:
# subs = RedditorFollow.find(q(guild=ctx.guild.id))
# redditors = []
# async for sub in subs:
# redditors.append(sub)
# if not redditors:
# await ctx.send("You need to follow a redditor first", ephemeral=True)
# return
options = []
names = []
for idx, redditor in enumerate(redditors):
sub = await Redditor.find_one(q(name=redditor.name))
names.append(sub.name)
option = StringSelectOption(label=sub.name, value=str(idx))
options.append(option)
# options = []
# names = []
# for idx, redditor in enumerate(redditors):
# sub = await Redditor.find_one(q(name=redditor.name))
# names.append(sub.name)
# option = StringSelectOption(label=sub.name, value=str(idx))
# options.append(option)
select = StringSelectMenu(options=options, custom_id="to_delete", min_values=1, max_values=len(redditors))
# select = StringSelectMenu(options=options, custom_id="to_delete", min_values=1, max_values=len(redditors))
components = [ActionRow(select)]
block = "\n".join(x for x in names)
message = await ctx.send(
content=f"You are following the following redditors:\n```\n{block}\n```\n\n"
"Please choose redditors to unfollow",
components=components,
)
# components = [ActionRow(select)]
# block = "\n".join(x for x in names)
# message = await ctx.send(
# content=f"You are following the following redditors:\n```\n{block}\n```\n\n"
# "Please choose redditors to unfollow",
# components=components,
# )
try:
context = await self.bot.wait_for_component(
check=lambda x: ctx.author.id == x.ctx.author.id,
messages=message,
timeout=60 * 5,
)
for to_delete in context.ctx.values:
follow = get(redditors, guild=ctx.guild.id, name=names[int(to_delete)])
try:
await follow.delete()
except Exception:
self.logger.debug("Ignoring deletion error")
for row in components:
for component in row.components:
component.disabled = True
# try:
# context = await self.bot.wait_for_component(
# check=lambda x: ctx.author.id == x.ctx.author.id,
# messages=message,
# timeout=60 * 5,
# )
# for to_delete in context.ctx.values:
# follow = get(redditors, guild=ctx.guild.id, name=names[int(to_delete)])
# try:
# await follow.delete()
# except Exception:
# self.logger.debug("Ignoring deletion error")
# for row in components:
# for component in row.components:
# component.disabled = True
block = "\n".join(names[int(x)] for x in context.ctx.values)
await context.ctx.edit_origin(
content=f"Unfollowed the following:\n```\n{block}\n```", components=components
)
except asyncio.TimeoutError:
for row in components:
for component in row.components:
component.disabled = True
await message.edit(components=components)
# block = "\n".join(names[int(x)] for x in context.ctx.values)
# await context.ctx.edit_origin(
# content=f"Unfollowed the following:\n```\n{block}\n```", components=components
# )
# except asyncio.TimeoutError:
# for row in components:
# for component in row.components:
# component.disabled = True
# await message.edit(components=components)
@follow.subcommand(sub_cmd_name="subreddit", sub_cmd_description="Follow a Subreddit")
@slash_option(
@ -283,12 +281,14 @@ class RedditCog(Extension):
await ctx.send("Subreddit may be private, quarantined, or nonexistent.", ephemeral=True)
return
exists = await SubredditFollow.find_one(q(display_name=subreddit.display_name, guild=ctx.guild.id))
exists = await SubredditFollow.find_one(
SubredditFollow.display_name == subreddit.display_name, SubredditFollow.guild == ctx.guild.id
)
if exists:
await ctx.send("Subreddit already being followed in this guild", ephemeral=True)
return
count = len([i async for i in SubredditFollow.find(q(guild=ctx.guild.id))])
count = await SubredditFollow.find(SubredditFollow.guild == ctx.guild.id).count()
if count >= 12:
await ctx.send("Cannot follow more than 12 Subreddits", ephemeral=True)
return
@ -300,10 +300,10 @@ class RedditCog(Extension):
)
return
sr = await Subreddit.find_one(q(display_name=subreddit.display_name))
sr = await Subreddit.find_one(Subreddit.display_name == subreddit.display_name)
if not sr:
sr = Subreddit(display_name=subreddit.display_name, over18=subreddit.over18)
await sr.commit()
await sr.save()
srf = SubredditFollow(
display_name=subreddit.display_name,
@ -311,17 +311,14 @@ class RedditCog(Extension):
guild=ctx.guild.id,
admin=ctx.author.id,
)
await srf.commit()
await srf.save()
await ctx.send(f"Now following `r/{name}` in {channel.mention}")
@unfollow.subcommand(sub_cmd_name="subreddit", sub_cmd_description="Unfollow Subreddits")
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _subreddit_unfollow(self, ctx: InteractionContext) -> None:
subs = SubredditFollow.find(q(guild=ctx.guild.id))
subreddits = []
async for sub in subs:
subreddits.append(sub)
subreddits = await SubredditFollow.find(SubredditFollow.guild == ctx.guild.id).to_list()
if not subreddits:
await ctx.send("You need to follow a Subreddit first", ephemeral=True)
return
@ -329,7 +326,7 @@ class RedditCog(Extension):
options = []
names = []
for idx, subreddit in enumerate(subreddits):
sub = await Subreddit.find_one(q(display_name=subreddit.display_name))
sub = await Subreddit.find_one(Subreddit.display_name == subreddit.display_name)
names.append(sub.display_name)
option = StringSelectOption(label=sub.display_name, value=str(idx))
options.append(option)
@ -393,7 +390,9 @@ class RedditCog(Extension):
embeds = await self.post_embeds(subreddit, post)
if post.over_18 and not ctx.channel.nsfw:
setting = await UserSetting.find_one(q(user=ctx.author.id, type="reddit", setting="dm_nsfw"))
setting = await UserSetting.find_one(
UserSetting.user == ctx.author.id, UserSetting.type == "reddit", UserSetting.setting == "dm_nsfw"
)
if setting and setting.value:
try:
await ctx.author.send(embeds=embeds)
@ -440,7 +439,9 @@ class RedditCog(Extension):
embeds = await self.post_embeds(subreddit, post)
if post.over_18 and not ctx.channel.nsfw:
setting = await UserSetting.find_one(q(user=ctx.author.id, type="reddit", setting="dm_nsfw"))
setting = await UserSetting.find_one(
UserSetting.user == ctx.author.id, UserSetting.type == "reddit", UserSetting.setting == "dm_nsfw"
)
if setting and setting.value:
try:
await ctx.author.send(embeds=embeds)
@ -473,7 +474,9 @@ class RedditCog(Extension):
embeds = await self.post_embeds(subreddit, post)
if post.over_18 and not ctx.channel.nsfw:
setting = await UserSetting.find_one(q(user=ctx.author.id, type="reddit", setting="dm_nsfw"))
setting = await UserSetting.find_one(
UserSetting.user == ctx.author.id, UserSetting.type == "reddit", UserSetting.setting == "dm_nsfw"
)
if setting and setting.value:
try:
await ctx.author.send(embeds=embeds)
@ -506,7 +509,9 @@ class RedditCog(Extension):
embeds = await self.post_embeds(subreddit, post)
if post.over_18 and not ctx.channel.nsfw:
setting = await UserSetting.find_one(q(user=ctx.author.id, type="reddit", setting="dm_nsfw"))
setting = await UserSetting.find_one(
UserSetting.user == ctx.author.id, UserSetting.type == "reddit", UserSetting.setting == "dm_nsfw"
)
if setting and setting.value:
try:
await ctx.author.send(embeds=embeds)
@ -530,7 +535,9 @@ class RedditCog(Extension):
embeds = await self.post_embeds(post.subreddit, post)
if post.over_18 and not ctx.channel.nsfw:
setting = await UserSetting.find_one(q(user=ctx.author.id, type="reddit", setting="dm_nsfw"))
setting = await UserSetting.find_one(
UserSetting.user == ctx.author.id, UserSetting.type == "reddit", UserSetting.setting == "dm_nsfw"
)
if setting and setting.value:
try:
await ctx.author.send(embeds=embeds)
@ -543,15 +550,19 @@ class RedditCog(Extension):
@reddit.subcommand(sub_cmd_name="dm_nsfw", sub_cmd_description="DM NSFW posts if channel isn't NSFW")
@slash_option(name="dm", description="Send DM?", opt_type=OptionType.BOOLEAN, required=True)
async def _reddit_dm(self, ctx: InteractionContext, dm: bool) -> None:
setting = await UserSetting.find_one(q(user=ctx.author.id, type="reddit", setting="dm_nsfw"))
setting = await UserSetting.find_one(
UserSetting.user == ctx.author.id, UserSetting.type == "reddit", UserSetting.setting == "dm_nsfw"
)
if not setting:
setting = UserSetting(user=ctx.author.id, type="reddit", setting="dm_nsfw", value=dm)
setting.value = dm
await setting.commit()
await setting.save()
await ctx.send(f"Reddit DM NSFW setting is now set to {dm}", ephemeral=True)
def setup(bot: Client) -> None:
"""Add RedditCog to JARVIS"""
if JarvisConfig.from_yaml().reddit:
if load_config().reddit:
RedditCog(bot)
else:
bot.logger.info("Missing Reddit configuration, not loading")

View file

@ -17,10 +17,9 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import TwitterAccount, TwitterFollow
from jarvis.config import JarvisConfig
from jarvis.config import load_config
from jarvis.utils.permissions import admin_or_permissions
@ -30,8 +29,8 @@ class TwitterCog(Extension):
def __init__(self, bot: Client):
self.bot = bot
self.logger = logging.getLogger(__name__)
config = JarvisConfig.from_yaml()
auth = tweepy.AppAuthHandler(config.twitter["consumer_key"], config.twitter["consumer_secret"])
config = load_config()
auth = tweepy.AppAuthHandler(config.twitter.consumer_key, config.twitter.consumer_secret)
self.api = tweepy.API(auth)
self._guild_cache = {}
self._channel_cache = {}
@ -78,24 +77,26 @@ class TwitterCog(Extension):
await ctx.send("Unable to get user timeline. Are you sure the handle is correct?", ephemeral=True)
return
exists = await TwitterFollow.find_one(q(twitter_id=account.id, guild=ctx.guild.id))
exists = await TwitterFollow.find_one(
TwitterFollow.twitter_id == account.id, TwitterFollow.guild == ctx.guild.id
)
if exists:
await ctx.send("Twitter account already being followed in this guild", ephemeral=True)
return
count = len([i async for i in TwitterFollow.find(q(guild=ctx.guild.id))])
count = await TwitterFollow.find(TwitterFollow.guild == ctx.guild.id).count()
if count >= 12:
await ctx.send("Cannot follow more than 12 Twitter accounts", ephemeral=True)
return
ta = await TwitterAccount.find_one(q(twitter_id=account.id))
ta = await TwitterAccount.find_one(TwitterAccount.twitter_id == account.id)
if not ta:
ta = TwitterAccount(
handle=account.screen_name,
twitter_id=account.id,
last_tweet=latest_tweet.id,
)
await ta.commit()
await ta.save()
tf = TwitterFollow(
twitter_id=account.id,
@ -105,14 +106,14 @@ class TwitterCog(Extension):
retweets=retweets,
)
await tf.commit()
await tf.save()
await ctx.send(f"Now following `@{handle}` in {channel.mention}")
@twitter.subcommand(sub_cmd_name="unfollow", sub_cmd_description="Unfollow Twitter accounts")
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _twitter_unfollow(self, ctx: InteractionContext) -> None:
t = TwitterFollow.find(q(guild=ctx.guild.id))
t = TwitterFollow.find(TwitterFollow.guild == ctx.guild.id)
twitters = []
async for twitter in t:
twitters.append(twitter)
@ -123,7 +124,7 @@ class TwitterCog(Extension):
options = []
handlemap = {}
for twitter in twitters:
account = await TwitterAccount.find_one(q(twitter_id=twitter.twitter_id))
account = await TwitterAccount.find_one(TwitterAccount.twitter_id == twitter.twitter_id)
handlemap[str(twitter.twitter_id)] = account.handle
option = StringSelectOption(label=account.handle, value=str(twitter.twitter_id))
options.append(option)
@ -176,7 +177,7 @@ class TwitterCog(Extension):
)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _twitter_modify(self, ctx: InteractionContext, retweets: bool = True) -> None:
t = TwitterFollow.find(q(guild=ctx.guild.id))
t = TwitterFollow.find(TwitterFollow.guild == ctx.guild.id)
twitters = []
async for twitter in t:
twitters.append(twitter)
@ -187,7 +188,7 @@ class TwitterCog(Extension):
options = []
handlemap = {}
for twitter in twitters:
account = await TwitterAccount.find_one(q(twitter_id=twitter.id))
account = await TwitterAccount.find_one(TwitterAccount.twitter_id == twitter.id)
handlemap[str(twitter.twitter_id)] = account.handle
option = StringSelectOption(label=account.handle, value=str(twitter.twitter_id))
options.append(option)
@ -211,11 +212,11 @@ class TwitterCog(Extension):
handlemap = {}
for to_update in context.ctx.values:
account = await TwitterAccount.find_one(q(twitter_id=int(to_update)))
account = await TwitterAccount.find_one(TwitterAccount.twitter_id == int(to_update))
handlemap[str(twitter.twitter_id)] = account.handle
t = get(twitters, guild=ctx.guild.id, twitter_id=int(to_update))
t.update(q(retweets=True))
await t.commit()
t.retweets = True
await t.save()
for row in components:
for component in row.components:
@ -239,5 +240,7 @@ class TwitterCog(Extension):
def setup(bot: Client) -> None:
"""Add TwitterCog to JARVIS"""
if JarvisConfig.from_yaml().twitter:
if load_config().twitter:
TwitterCog(bot)
else:
bot.logger.info("No Twitter configuration, not loading")

View file

@ -21,8 +21,7 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from interactions.models.internal.command import check
from jarvis_core.db import q
from jarvis_core.db.models import Star, Starboard
from jarvis_core.db.models import Pin, Pinboard
from jarvis.utils import build_embed
from jarvis.utils.permissions import admin_or_permissions
@ -43,16 +42,16 @@ class PinboardCog(Extension):
self.bot = bot
self.logger = logging.getLogger(__name__)
async def _purge_starboard(self, ctx: InteractionContext, board: Starboard) -> None:
async def _purge_starboard(self, ctx: InteractionContext, board: Pinboard) -> None:
channel = await ctx.guild.fetch_channel(board.channel)
async for star in Star.find(q(starboard=channel.id, guild=ctx.guild.id)):
if message := await channel.fetch_message(star.message):
async for pin in Pin.find(Pin.pinboard == channel.id, Pin.guild == ctx.guild.id):
if message := await channel.fetch_message(pin.message):
try:
await message.delete()
await asyncio.sleep(1) # Avoid rate limits
except (errors.Forbidden, errors.NotFound):
self.logger.debug(f"Failed to delete star {star.id}'s message.")
await star.delete()
self.logger.debug(f"Failed to delete star {pin.id}'s message.")
await pin.delete()
pinboard = SlashCommand(name="pinboard", description="Extra pins! Manage pinboards")
@ -60,12 +59,12 @@ class PinboardCog(Extension):
sub_cmd_name="list",
sub_cmd_description="List all pinboards",
)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
@check(admin_or_permissions(Permissions.MANAGE_GUILD, Permissions.MANAGE_MESSAGES))
async def _list(self, ctx: InteractionContext) -> None:
starboards = await Starboard.find(q(guild=ctx.guild.id)).to_list(None)
if starboards != []:
pinboards = await Pinboard.find(Pinboard.guild == ctx.guild.id).to_list()
if pinboards != []:
message = "Available Pinboards:\n"
for s in starboards:
for s in pinboards:
message += f"<#{s.channel}>\n"
await ctx.send(message)
else:
@ -78,7 +77,7 @@ class PinboardCog(Extension):
opt_type=OptionType.CHANNEL,
required=True,
)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
@check(admin_or_permissions(Permissions.MANAGE_GUILD, Permissions.MANAGE_MESSAGES))
async def _create(self, ctx: InteractionContext, channel: GuildText) -> None:
if channel not in ctx.guild.channels:
await ctx.send(
@ -90,21 +89,21 @@ class PinboardCog(Extension):
await ctx.send("Channel must be a GuildText", ephemeral=True)
return
exists = await Starboard.find_one(q(channel=channel.id, guild=ctx.guild.id))
exists = await Pinboard.find_one(Pinboard.channel == channel.id, Pinboard.guild == ctx.guild.id)
if exists:
await ctx.send(f"Pinboard already exists at {channel.mention}.", ephemeral=True)
return
count = await Starboard.count_documents(q(guild=ctx.guild.id))
count = await Pinboard.find(Pinboard.guild == ctx.guild.id).count()
if count >= 25:
await ctx.send("25 pinboard limit reached", ephemeral=True)
return
await Starboard(
await Pinboard(
guild=ctx.guild.id,
channel=channel.id,
admin=ctx.author.id,
).commit()
).save()
await ctx.send(f"Pinboard created. Check it out at {channel.mention}.")
@pinboard.subcommand(sub_cmd_name="delete", sub_cmd_description="Delete a pinboard")
@ -114,9 +113,9 @@ class PinboardCog(Extension):
opt_type=OptionType.CHANNEL,
required=True,
)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
@check(admin_or_permissions(Permissions.MANAGE_GUILD, Permissions.MANAGE_MESSAGES))
async def _delete(self, ctx: InteractionContext, channel: GuildText) -> None:
found = await Starboard.find_one(q(channel=channel.id, guild=ctx.guild.id))
found = await Pinboard.find_one(Pinboard.channel == channel.id, Pinboard.guild == ctx.guild.id)
if found:
await found.delete()
asyncio.create_task(self._purge_starboard(ctx, found))
@ -132,8 +131,8 @@ class PinboardCog(Extension):
) -> None:
if not channel:
channel = ctx.channel
starboards = await Starboard.find(q(guild=ctx.guild.id)).to_list(None)
if not starboards:
pinboards = await Pinboard.find(Pinboard.guild == ctx.guild.id).to_list()
if not pinboards:
await ctx.send("No pinboards exist.", ephemeral=True)
return
@ -149,18 +148,19 @@ class PinboardCog(Extension):
return
channel_list = []
to_delete = []
for starboard in starboards:
c = await ctx.guild.fetch_channel(starboard.channel)
to_delete: list[Pinboard] = []
for pinboard in pinboards:
c = await ctx.guild.fetch_channel(pinboard.channel)
if c and isinstance(c, GuildText):
channel_list.append(c)
else:
self.logger.warning(f"Pinboard {starboard.channel} no longer valid in {ctx.guild.name}")
to_delete.append(starboard)
self.logger.warning(f"Pinboard {pinboard.channel} no longer valid in {ctx.guild.name}")
to_delete.append(pinboard)
for starboard in to_delete:
for pinboard in to_delete:
try:
await starboard.delete()
await pinboard.delete()
except Exception:
self.logger.debug("Ignoring deletion error")
@ -187,25 +187,23 @@ class PinboardCog(Extension):
check=lambda x: ctx.author.id == x.context.author.id,
)
starboard = channel_list[int(com_ctx.context.values[0])]
pinboard = channel_list[int(com_ctx.context.values[0])]
exists = await Star.find_one(
q(
message=message.id,
channel=channel.id,
guild=ctx.guild.id,
starboard=starboard.id,
)
exists = await Pin.find_one(
Pin.message == message.id,
Pin.channel == channel.id,
Pin.guild == ctx.guild.id,
Pin.pinboard == pinboard.id,
)
if exists:
await ctx.send(
f"Message already sent to Pinboard {starboard.mention}",
f"Message already sent to Pinboard {pinboard.mention}",
ephemeral=True,
)
return
count = await Star.count_documents(q(guild=ctx.guild.id, starboard=starboard.id))
count = await Pin.find(Pin.guild == ctx.guild.id, Pin.pinboard == pinboard.id).count()
content = message.content
attachments = message.attachments
@ -234,28 +232,28 @@ class PinboardCog(Extension):
if image_url:
embed.set_image(url=image_url)
star_components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
star = await starboard.send(embeds=embed, components=star_components)
pin = await pinboard.send(embeds=embed, components=star_components)
await Star(
await Pin(
index=count,
message=message.id,
channel=channel.id,
guild=ctx.guild.id,
starboard=starboard.id,
pinboard=pinboard.id,
admin=ctx.author.id,
star=star.id,
pin=pin.id,
active=True,
).commit()
).save()
components[0].components[0].disabled = True
await com_ctx.context.edit_origin(
content=f"Message saved to Pinboard.\nSee it in {starboard.mention}",
content=f"Message saved to Pinboard.\nSee it in {pinboard.mention}",
components=components,
)
@context_menu(name="Pin Message", context_type=CommandType.MESSAGE)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
@check(admin_or_permissions(Permissions.MANAGE_GUILD, Permissions.MANAGE_MESSAGES))
async def _star_message(self, ctx: InteractionContext) -> None:
await self._star_add(ctx, message=str(ctx.target_id))

View file

@ -28,7 +28,6 @@ from interactions.models.internal.application_commands import (
)
from interactions.models.internal.command import check, cooldown
from interactions.models.internal.cooldowns import Buckets
from jarvis_core.db import q
from jarvis_core.db.models import Rolegiver
from thefuzz import process
@ -47,8 +46,7 @@ class RolegiverCog(Extension):
@listen()
async def on_ready(self) -> None:
"""NAFF on_ready hook for loading cache."""
all_rolegivers = await Rolegiver.find({}).to_list(None)
for rolegiver in all_rolegivers:
async for rolegiver in Rolegiver.find():
guild = await self.bot.fetch_guild(rolegiver.guild)
if not guild:
await rolegiver.delete()
@ -64,7 +62,7 @@ class RolegiverCog(Extension):
self.cache[guild.id] = {}
self.cache[guild.id][role.name] = role.id
rolegiver.roles = roles
await rolegiver.commit()
await rolegiver.save()
rolegiver = SlashCommand(name="rolegiver", description="Allow users to choose their own roles")
@ -86,7 +84,7 @@ class RolegiverCog(Extension):
)
return
setting = await Rolegiver.find_one(q(guild=ctx.guild.id))
setting = await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id)
if setting and setting.roles and role.id in setting.roles:
await ctx.send("Role already in rolegiver", ephemeral=True)
return
@ -97,7 +95,7 @@ class RolegiverCog(Extension):
setting.roles = setting.roles or []
setting.roles.append(role.id)
await setting.commit()
await setting.save()
roles = []
for role_id in setting.roles:
@ -142,7 +140,7 @@ class RolegiverCog(Extension):
)
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _rolegiver_remove(self, ctx: InteractionContext, role: str) -> None:
setting = await Rolegiver.find_one(q(guild=ctx.guild.id))
setting = await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id)
if not setting or (setting and not setting.roles):
await ctx.send("Rolegiver has no roles", ephemeral=True)
return
@ -155,7 +153,7 @@ class RolegiverCog(Extension):
return
setting.value.remove(role_id)
await setting.commit()
await setting.save()
role = await ctx.guild.fetch_role(role_id)
if not role:
await ctx.send("Role not found in guild", ephemeral=True)
@ -169,7 +167,7 @@ class RolegiverCog(Extension):
to_remove.append(id_)
setting.value = [x for x in setting.value if x not in to_remove]
await setting.commit()
await setting.save()
fields = [
EmbedField(name="Removed Role", value=role.mention),
@ -191,7 +189,7 @@ class RolegiverCog(Extension):
@rolegiver.subcommand(sub_cmd_name="list", sub_cmd_description="List rolegiver roles")
async def _rolegiver_list(self, ctx: InteractionContext) -> None:
setting = await Rolegiver.find_one(q(guild=ctx.guild.id))
setting = await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id)
if not setting or (setting and not setting.roles):
await ctx.send("Rolegiver has no roles", ephemeral=True)
return
@ -223,7 +221,7 @@ class RolegiverCog(Extension):
@rolegiver.subcommand(sub_cmd_name="get", sub_cmd_description="Get a role")
@cooldown(bucket=Buckets.USER, rate=1, interval=10)
async def _role_get(self, ctx: InteractionContext) -> None:
setting = await Rolegiver.find_one(q(guild=ctx.guild.id))
setting = await Rolegiver.find_one(Rolegiver.quild == ctx.guild.id)
if not setting or (setting and not setting.roles):
await ctx.send("Rolegiver has no roles", ephemeral=True)
return
@ -299,7 +297,7 @@ class RolegiverCog(Extension):
async def _role_remove(self, ctx: InteractionContext) -> None:
user_roles = ctx.author.roles
setting = await Rolegiver.find_one(q(guild=ctx.guild.id))
setting = await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id)
if not setting or (setting and not setting.roles):
await ctx.send("Rolegiver has no roles", ephemeral=True)
return
@ -374,14 +372,14 @@ class RolegiverCog(Extension):
@rolegiver.subcommand(sub_cmd_name="cleanup", sub_cmd_description="Removed deleted roles from rolegiver")
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
async def _rolegiver_cleanup(self, ctx: InteractionContext) -> None:
setting = await Rolegiver.find_one(q(guild=ctx.guild.id))
setting = await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id)
if not setting or not setting.roles:
await ctx.send("Rolegiver has no roles", ephemeral=True)
guild_role_ids = [r.id for r in ctx.guild.roles]
for role_id in setting.roles:
if role_id not in guild_role_ids:
setting.roles.remove(role_id)
await setting.commit()
await setting.save()
await ctx.send("Rolegiver cleanup finished")
self.cache.pop(ctx.guild.id, None)
@ -389,8 +387,7 @@ class RolegiverCog(Extension):
@_rolegiver_remove.autocomplete("role")
async def _autocomplete(self, ctx: AutocompleteContext, role: str) -> None:
if not self.cache.get(ctx.guild.id):
rolegivers = await Rolegiver.find(q(guild=ctx.guild.id)).to_list(None)
for rolegiver in rolegivers:
async for rolegiver in Rolegiver.find(Rolegiver.guild == ctx.guild.id):
role = await ctx.guild.fetch_role(rolegiver.role)
if not role:
await rolegiver.delete()

View file

@ -14,7 +14,6 @@ from interactions.models.internal.application_commands import (
SlashCommand,
slash_option,
)
from jarvis_core.db import q
from jarvis_core.db.models import Setting, Tag
from thefuzz import process
@ -43,7 +42,7 @@ class TagCog(Extension):
required=True,
)
async def _get(self, ctx: InteractionContext, name: str) -> None:
tag = await Tag.find_one(q(guild=ctx.guild.id, name=name))
tag = await Tag.find_one(Tag.guild == ctx.guild.id, Tag.name == name)
if not tag:
await ctx.send("Well this is awkward, looks like the tag was deleted just now", ephemeral=True)
return
@ -80,7 +79,7 @@ class TagCog(Extension):
except asyncio.TimeoutError:
return
noinvite = await Setting.find_one(q(guild=ctx.guild.id, setting="noinvite"))
noinvite = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "noinvite")
if (
(invites.search(content) or invites.search(name))
@ -99,7 +98,7 @@ class TagCog(Extension):
await response.send("Tag name must only contain: [A-Za-z0-9_- ]", ephemeral=True)
return
tag = await Tag.find_one(q(guild=ctx.guild.id, name=name))
tag = await Tag.find_one(Tag.guild == ctx.guild.id, Tag.name == name)
if tag:
await response.send("That tag already exists", ephemeral=True)
return
@ -112,7 +111,7 @@ class TagCog(Extension):
content=content,
guild=ctx.guild.id,
)
await tag.commit()
await tag.save()
embed = build_embed(
title="Tag Created",
@ -142,7 +141,7 @@ class TagCog(Extension):
)
async def _edit(self, ctx: InteractionContext, name: str) -> None:
old_name = name
tag = await Tag.find_one(q(guild=ctx.guild.id, name=name))
tag = await Tag.find_one(Tag.guild == ctx.guild.id, Tag.name == name)
if not tag:
await ctx.send("Tag not found", ephemeral=True)
return
@ -181,12 +180,12 @@ class TagCog(Extension):
except asyncio.TimeoutError:
return
new_tag = await Tag.find_one(q(guild=ctx.guild.id, name=name))
new_tag = await Tag.find_one(Tag.guild == ctx.guild.id, Tag.name == name)
if new_tag and new_tag.id != tag.id:
await ctx.send("That tag name is used by another tag, choose another name", ephemeral=True)
return
noinvite = await Setting.find_one(q(guild=ctx.guild.id, setting="noinvite"))
noinvite = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "noinvite")
if (
(invites.search(content) or invites.search(name))
@ -210,7 +209,7 @@ class TagCog(Extension):
tag.edited_at = datetime.now(tz=timezone.utc)
tag.editor = ctx.author.id
await tag.commit()
await tag.save()
embed = build_embed(
title="Tag Updated",
@ -240,7 +239,7 @@ class TagCog(Extension):
autocomplete=True,
)
async def _delete(self, ctx: InteractionContext, name: str) -> None:
tag = await Tag.find_one(q(guild=ctx.guild.id, name=name))
tag = await Tag.find_one(Tag.guild == ctx.guild.id, Tag.name == name)
if not tag:
await ctx.send("Tag not found", ephemeral=True)
return
@ -264,7 +263,7 @@ class TagCog(Extension):
autocomplete=True,
)
async def _info(self, ctx: InteractionContext, name: str) -> None:
tag = await Tag.find_one(q(guild=ctx.guild.id, name=name))
tag = await Tag.find_one(Tag.guild == ctx.guild.id, Tag.name == name)
if not tag:
await ctx.send("Tag not found", ephemeral=True)
return
@ -307,7 +306,7 @@ class TagCog(Extension):
@tag.subcommand(sub_cmd_name="list", sub_cmd_description="List tag names")
async def _list(self, ctx: InteractionContext) -> None:
tags = await Tag.find(q(guild=ctx.guild.id)).to_list(None)
tags = await Tag.find(Tag.guild == ctx.guild.id).to_list()
names = "\n".join(f"`{t.name}`" for t in tags)
embed = build_embed(title="All Tags", description=names, fields=[])
components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
@ -319,7 +318,7 @@ class TagCog(Extension):
@_info.autocomplete("name")
async def _autocomplete(self, ctx: AutocompleteContext, name: str) -> None:
if not self.cache.get(ctx.guild.id):
tags = await Tag.find(q(guild=ctx.guild.id)).to_list(None)
tags = await Tag.find(Tag.guild == ctx.guild.id).to_list()
self.cache[ctx.guild.id] = [tag.name for tag in tags]
results = process.extract(name, self.cache.get(ctx.guild.id), limit=25)
choices = [{"name": r[0], "value": r[0]} for r in results]

View file

@ -15,7 +15,6 @@ from interactions.models.internal.application_commands import (
)
from interactions.models.internal.command import cooldown
from interactions.models.internal.cooldowns import Buckets
from jarvis_core.db import q
from jarvis_core.db.models import Guess
from jarvis.utils import build_embed
@ -74,7 +73,7 @@ class CTCCog(Extension):
ephemeral=True,
)
return
guessed = await Guess.find_one(q(guess=guess))
guessed = await Guess.find_one(Guess.guess == guess)
if guessed:
await ctx.send("Already guessed, dipshit.", ephemeral=True)
return
@ -86,7 +85,7 @@ class CTCCog(Extension):
correct = True
else:
await ctx.send("Nope.", ephemeral=True)
await Guess(guess=guess, user=ctx.author.id, correct=correct).commit()
await Guess(guess=guess, user=ctx.author.id, correct=correct).save()
@ctc2.subcommand(
sub_cmd_name="guesses",
@ -96,21 +95,21 @@ class CTCCog(Extension):
async def _guesses(self, ctx: InteractionContext) -> None:
await ctx.defer()
cache = {}
guesses = Guess.find().sort("correct", -1).sort("id", -1)
guesses = Guess.find().sort(-Guess.correct, -Guess.id)
fields = []
async for guess in guesses:
user = cache.get(guess["user"]) or await self.bot.fetch_user(guess["user"])
user = cache.get(guess.user) or await self.bot.fetch_user(guess.user)
if not user:
user = "[redacted]"
if isinstance(user, (Member, User)):
user = user.username + "#" + user.discriminator
cache[guess["user"]] = user
cache[guess.user] = user
name = "Correctly" if guess["correct"] else "Incorrectly"
name += " guessed by: " + user
fields.append(
EmbedField(
name=name,
value=guess["guess"] + "\n\u200b",
value=guess.guess + "\n\u200b",
inline=False,
)
)

View file

@ -18,7 +18,7 @@ from interactions.models.internal.cooldowns import Buckets
from thefuzz import process
from jarvis.branding import CUSTOM_EMOJIS
from jarvis.config import JarvisConfig
from jarvis.config import load_config
from jarvis.data.dbrand import shipping_lookup
from jarvis.utils import build_embed
@ -80,7 +80,7 @@ class DbrandCog(Extension):
self.base_url = "https://dbrand.com/"
self._session = aiohttp.ClientSession()
self._session.headers.update({"Content-Type": "application/json"})
self.api_url = JarvisConfig.from_yaml().urls["dbrand_shipping"]
self.api_url = load_config().urls["dbrand_shipping"]
self.cache = {}
def __del__(self):
@ -350,5 +350,7 @@ class DbrandCog(Extension):
def setup(bot: Client) -> None:
"""Add dbrandcog to JARVIS"""
if JarvisConfig.from_yaml().urls.get("dbrand_shipping"):
if load_config().urls.get("dbrand_shipping"):
DbrandCog(bot)
else:
bot.logger.info("Missing dbrand shipping URL, not loading dbrand cog")

View file

@ -17,7 +17,7 @@ from interactions.models.internal.application_commands import (
slash_option,
)
from jarvis.config import JarvisConfig
from jarvis.config import load_config
from jarvis.utils import build_embed
guild_ids = [862402786116763668]
@ -29,7 +29,7 @@ class GitlabCog(Extension):
def __init__(self, bot: Client):
self.bot = bot
self.logger = logging.getLogger(__name__)
config = JarvisConfig.from_yaml()
config = load_config()
self._gitlab = gitlab.Gitlab("https://git.zevaryx.com", private_token=config.gitlab_token)
# JARVIS GitLab ID is 29
self.project = self._gitlab.projects.get(29)
@ -436,5 +436,7 @@ class GitlabCog(Extension):
def setup(bot: Client) -> None:
"""Add GitlabCog to JARVIS if Gitlab token exists."""
if JarvisConfig.from_yaml().gitlab_token:
if load_config().gitlab_token:
GitlabCog(bot)
else:
bot.logger.info("Missing GitLab token, ignoring GitLab cog")

View file

@ -1,90 +1,196 @@
"""Load the config for JARVIS"""
from enum import Enum
from os import environ
from pathlib import Path
from typing import Optional
import orjson as json
import yaml
from dotenv import load_dotenv
from jarvis_core.util import find_all
from pydantic import BaseModel
try:
from yaml import CLoader as Loader
except ImportError:
from yaml import Loader
from jarvis_core.config import Config
class Mongo(BaseModel):
"""MongoDB config."""
host: list[str] | str = "localhost"
username: Optional[str] = None
password: Optional[str] = None
port: int = 27017
class JarvisConfig(Config):
REQUIRED = ("token", "mongo", "redis")
OPTIONAL = {
"urls": None,
"sync": False,
"log_level": "INFO",
"cogs": None,
"events": True,
"gitlab_token": None,
"max_messages": 1000,
"twitter": None,
"reddit": None,
"rook_token": None,
"jurigged": False,
}
ENV_REQUIRED = [
"TOKEN",
"MONGODB_HOST",
"MONGODB_USER",
"MONGODB_PASS",
"MONGODB_PORT",
"MONGODB_DATABASE",
"REDIS_HOST",
"REDIS_USER",
"REDIS_PASS",
]
ENV_OPTIONAL = {
"MAX_MESSAGES": 10000,
"GITLAB_TOKEN": None,
"LOG_LEVEL": "INFO",
"SYNC": False,
"ROOK": None,
"REDDIT_SECRET": None,
"REDDIT_CLIENT": None,
"TWITTER_CONSUMER_KEY": None,
"TWITTER_CONSUMER_SECRET": None,
"TWITTER_ACCESS_TOKEN": None,
"TWITTER_ACCESS_SECRET": None,
"URLS_DBRAND_SHIPPING": None,
"JURIGGED": False,
}
class Redis(BaseModel):
"""Redis config."""
@classmethod
def _process_env(cls, **kwargs) -> dict:
"""Process environment variables into usable info."""
data = {}
mongo = {"connect": {}, "database": ""}
redis = {}
twitter = {}
reddit = {}
urls = {}
for item, value in kwargs.items():
if item.startswith("MONGODB"):
key = item.split("_")[1].lower()
if key == "database":
mongo[key] = value
else:
mongo["connect"][key] = value
elif item.startswith("REDIS"):
key = item.split("_")[1].lower()
redis[key] = value
elif item.startswith("TWITTER"):
key = "_".join(item.split("_")[1:]).lower()
twitter[key] = value
elif item.startswith("REDDIT"):
key = item.split("_")[1].lower()
reddit[key] = value
elif item.startswith("URLS_"):
key = "_".join(item.split("_")[1:]).lower()
urls[key] = value
else:
if item == "SYNC":
value = value.lower() == "True"
data[item.lower()] = value
host: str = "localhost"
username: Optional[str] = None
password: Optional[str] = None
data["mongo"] = mongo
data["redis"] = redis
if all(x is not None for x in reddit.values()):
data["reddit"] = reddit
if all(x is not None for x in twitter.values()):
data["twitter"] = twitter
data["urls"] = {k: v for k, v in urls if v}
return data
class Mastodon(BaseModel):
"""Mastodon config."""
token: str
url: str
class Reddit(BaseModel):
"""Reddit config."""
user_agent: Optional[str] = None
client_secret: str
client_id: str
class Twitter(BaseModel):
"""Twitter config."""
consumer_key: str
consumer_secret: str
access_token: str
access_secret: str
bearer_token: str
class Environment(Enum):
"""JARVIS running environment."""
production = "production"
develop = "develop"
class Config(BaseModel):
"""JARVIS config model."""
token: str
environment: Environment = Environment.develop
mongo: Mongo
redis: Redis
mastodon: Optional[Mastodon] = None
reddit: Optional[Reddit] = None
twitter: Optional[Twitter] = None
urls: Optional[dict[str, str]] = None
sync: bool = False
log_level: str = "INFO"
jurigged: bool = False
_config: Config = None
def _load_json() -> Config | None:
path = Path("config.json")
config = None
if path.exists():
with path.open() as f:
j = json.loads(f.read())
config = Config(**j)
return config
def _load_yaml() -> Config | None:
path = Path("config.yaml")
config = None
if path.exists():
with path.open() as f:
y = yaml.load(f.read(), Loader=Loader)
config = Config(**y)
return config
def _load_env() -> Config | None:
load_dotenv()
data = {}
mongo = {}
redis = {}
mastodon = {}
twitter = {}
reddit = {}
urls = {}
mongo_keys = find_all(lambda x: x.upper().startswith("MONGO"), environ.keys())
redis_keys = find_all(lambda x: x.upper().startswith("REDIS"), environ.keys())
mastodon_keys = find_all(lambda x: x.upper().startswith("MASTODON"), environ.keys())
reddit_keys = find_all(lambda x: x.upper().startswith("REDDIT"), environ.keys())
twitter_keys = find_all(lambda x: x.upper().startswith("TWITTER"), environ.keys())
url_keys = find_all(lambda x: x.upper().startswith("URLS"), environ.keys())
config_keys = (
mongo_keys
+ redis_keys
+ mastodon_keys
+ reddit_keys
+ twitter_keys
+ url_keys
+ ["TOKEN", "SYNC", "LOG_LEVEL", "JURIGGED"]
)
for item, value in environ.items():
if item not in config_keys:
continue
if item in mongo_keys:
key = "_".join(item.split("_")[1:]).lower()
mongo[key] = value
elif item in redis_keys:
key = "_".join(item.split("_")[1:]).lower()
redis[key] = value
elif item in mastodon_keys:
key = "_".join(item.split("_")[1:]).lower()
mastodon[key] = value
elif item in twitter_keys:
key = "_".join(item.split("_")[1:]).lower()
twitter[key] = value
elif item in reddit_keys:
key = "_".join(item.split("_")[1:]).lower()
reddit[key] = value
elif item in url_keys:
key = "_".join(item.split("_")[1:]).lower()
urls[key] = value
else:
if item == "SYNC":
value = value.lower() in ["yes", "true"]
data[item.lower()] = value
data["mongo"] = mongo
data["redis"] = redis
if all(x is not None for x in reddit.values()):
data["reddit"] = reddit
if all(x is not None for x in twitter.values()):
data["twitter"] = twitter
if all(x is not None for x in mastodon.values()):
data["mastodon"] = mastodon
data["urls"] = {k: v for k, v in urls if v}
return Config(**data)
def load_config(method: Optional[str] = None) -> Config:
"""
Load the config using the specified method first
Args:
method: Method to use first
"""
global _config
if _config is not None:
return _config
methods = {"yaml": _load_yaml, "json": _load_json, "env": _load_env}
method_names = list(methods.keys())
if method and method in method_names:
method_names.remove(method)
method_names.insert(0, method)
for method in method_names:
if _config := methods[method]():
return _config
raise FileNotFoundError("Missing one of: config.yaml, config.json, .env")

View file

@ -8,7 +8,6 @@ from interactions.models.discord.guild import AuditLogEntry
from interactions.models.discord.user import Member
from jarvis.branding import PRIMARY_COLOR
from jarvis.config import JarvisConfig
def build_embed(
@ -66,8 +65,7 @@ def modlog_embed(
def get_extensions(path: str) -> list:
"""Get JARVIS cogs."""
config = JarvisConfig.from_yaml()
vals = config.cogs or [x.name for x in iter_modules(path)]
vals = [x.name for x in iter_modules(path)]
return [f"jarvis.cogs.{x}" for x in vals]

View file

@ -6,7 +6,6 @@ from interactions import Client, Extension, InteractionContext
from interactions.models.discord.components import ActionRow, Button, ButtonStyle
from interactions.models.discord.embed import EmbedField
from interactions.models.discord.user import Member
from jarvis_core.db import q
from jarvis_core.db.models import Action, Ban, Kick, Modlog, Mute, Setting, Warning
from statipy.db import Stat
@ -45,13 +44,12 @@ class ModcaseCog(Extension):
md = WarningMetadata(
client_id=self.user.id,
client_name=self.client_name,
name="warning",
type="manual",
guild_id=message.guild.id,
guild_name=message.guild.name,
guild_id=ctx.guild.id,
guild_name=ctx.guild.name,
value=1,
)
await Stat(meta=md).insert()
await Stat(meta=md, name="warning").insert()
user = kwargs.pop("user", None)
if not user and not ctx.target_id:
self.logger.warning("Admin action %s missing user, exiting", name)
@ -69,12 +67,16 @@ class ModcaseCog(Extension):
self.logger.warning("Unsupported action %s, exiting", name)
return
action = await coll.find_one(q(user=user.id, guild=ctx.guild_id, active=True), sort=[("_id", -1)])
action = await coll.find_one(
coll.user == user.id, coll.guild == ctx.guild.id, coll.active is True, sort=[("_id", -1)]
)
if not action:
self.logger.warning("Missing action %s, exiting", name)
return
notify = await Setting.find_one(q(guild=ctx.guild.id, setting="notify", value=True))
notify = await Setting.find_one(
Setting.guild == ctx.guild.id, Setting.setting == "notify", Setting.value is True
)
if notify and name not in ("Kick", "Ban"): # Ignore Kick and Ban, as these are unique
fields = (
EmbedField(name="Action Type", value=name, inline=False),
@ -96,14 +98,15 @@ class ModcaseCog(Extension):
except Exception:
self.logger.debug("User not warned of action due to closed DMs")
modlog = await Modlog.find_one(q(user=user.id, guild=ctx.guild.id, open=True))
modlog = await Modlog.find_one(Modlog.user == user.id, Modlog.guild == ctx.guild.id, Modlog.open is True)
if modlog:
m_action = Action(action_type=name.lower(), parent=action.id)
modlog.actions.append(m_action)
await modlog.commit()
await modlog.save()
return
modlog = await Setting.find_one(q(guild=ctx.guild.id, setting="modlog"))
modlog = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "modlog")
if not modlog:
return

View file

@ -1,22 +1,6 @@
"""Permissions wrappers."""
from interactions import InteractionContext, Permissions
from jarvis.config import JarvisConfig
def user_is_bot_admin() -> bool:
"""Check if a user is a JARVIS admin."""
async def predicate(ctx: InteractionContext) -> bool:
"""Command check predicate."""
cfg = JarvisConfig.from_yaml()
if getattr(cfg, "admins", None):
return ctx.author.id in cfg.admins
else:
return False
return predicate
def admin_or_permissions(*perms: list) -> bool:
"""Check if a user is an admin or has other perms."""

564
poetry.lock generated
View file

@ -1,21 +1,22 @@
# This file is automatically @generated by Poetry and should not be changed by hand.
# This file is automatically @generated by Poetry 1.4.0 and should not be changed by hand.
[[package]]
name = "aiofile"
version = "3.8.1"
version = "3.8.5"
description = "Asynchronous file operations."
category = "main"
optional = false
python-versions = ">=3.7, <4"
files = [
{file = "aiofile-3.8.1.tar.gz", hash = "sha256:1623b98d88fbd16bbd2808d010de4e185a700e950ed3f17455dd851aa2455f40"},
{file = "aiofile-3.8.5-py3-none-any.whl", hash = "sha256:6644b61ab143a8e516920cdb02d5b46f89c0a37ef036417720f653b5ed31a8c9"},
{file = "aiofile-3.8.5.tar.gz", hash = "sha256:bb1ca0b2c4ef3b78f5012a2a3919a4151f873b6aabdc73a7b9b8e94edb2e01ae"},
]
[package.dependencies]
caio = ">=0.9.0,<0.10.0"
[package.extras]
develop = ["aiomisc", "pytest", "pytest-cov"]
develop = ["aiomisc-pytest", "coveralls", "pytest", "pytest-cov", "pytest-rst"]
[[package]]
name = "aiofiles"
@ -341,14 +342,14 @@ toml = "*"
[[package]]
name = "beautifulsoup4"
version = "4.11.2"
version = "4.12.0"
description = "Screen-scraping library"
category = "main"
optional = false
python-versions = ">=3.6.0"
files = [
{file = "beautifulsoup4-4.11.2-py3-none-any.whl", hash = "sha256:0e79446b10b3ecb499c1556f7e228a53e64a2bfcebd455f370d8927cb5b59e39"},
{file = "beautifulsoup4-4.11.2.tar.gz", hash = "sha256:bc4bdda6717de5a2987436fb8d72f45dc90dd856bdfd512a1314ce90349a0106"},
{file = "beautifulsoup4-4.12.0-py3-none-any.whl", hash = "sha256:2130a5ad7f513200fae61a17abb5e338ca980fa28c439c0571014bc0217e9591"},
{file = "beautifulsoup4-4.12.0.tar.gz", hash = "sha256:c5fceeaec29d09c84970e47c65f2f0efe57872f7cff494c9691a26ec0ff13234"},
]
[package.dependencies]
@ -360,32 +361,46 @@ lxml = ["lxml"]
[[package]]
name = "black"
version = "22.12.0"
version = "23.1.0"
description = "The uncompromising code formatter."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"},
{file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"},
{file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"},
{file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"},
{file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"},
{file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"},
{file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"},
{file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"},
{file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"},
{file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"},
{file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"},
{file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"},
{file = "black-23.1.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:b6a92a41ee34b883b359998f0c8e6eb8e99803aa8bf3123bf2b2e6fec505a221"},
{file = "black-23.1.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:57c18c5165c1dbe291d5306e53fb3988122890e57bd9b3dcb75f967f13411a26"},
{file = "black-23.1.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:9880d7d419bb7e709b37e28deb5e68a49227713b623c72b2b931028ea65f619b"},
{file = "black-23.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6663f91b6feca5d06f2ccd49a10f254f9298cc1f7f49c46e498a0771b507104"},
{file = "black-23.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:9afd3f493666a0cd8f8df9a0200c6359ac53940cbde049dcb1a7eb6ee2dd7074"},
{file = "black-23.1.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:bfffba28dc52a58f04492181392ee380e95262af14ee01d4bc7bb1b1c6ca8d27"},
{file = "black-23.1.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c1c476bc7b7d021321e7d93dc2cbd78ce103b84d5a4cf97ed535fbc0d6660648"},
{file = "black-23.1.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:382998821f58e5c8238d3166c492139573325287820963d2f7de4d518bd76958"},
{file = "black-23.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bf649fda611c8550ca9d7592b69f0637218c2369b7744694c5e4902873b2f3a"},
{file = "black-23.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:121ca7f10b4a01fd99951234abdbd97728e1240be89fde18480ffac16503d481"},
{file = "black-23.1.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:a8471939da5e824b891b25751955be52ee7f8a30a916d570a5ba8e0f2eb2ecad"},
{file = "black-23.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8178318cb74f98bc571eef19068f6ab5613b3e59d4f47771582f04e175570ed8"},
{file = "black-23.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a436e7881d33acaf2536c46a454bb964a50eff59b21b51c6ccf5a40601fbef24"},
{file = "black-23.1.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:a59db0a2094d2259c554676403fa2fac3473ccf1354c1c63eccf7ae65aac8ab6"},
{file = "black-23.1.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:0052dba51dec07ed029ed61b18183942043e00008ec65d5028814afaab9a22fd"},
{file = "black-23.1.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:49f7b39e30f326a34b5c9a4213213a6b221d7ae9d58ec70df1c4a307cf2a1580"},
{file = "black-23.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:162e37d49e93bd6eb6f1afc3e17a3d23a823042530c37c3c42eeeaf026f38468"},
{file = "black-23.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b70eb40a78dfac24842458476135f9b99ab952dd3f2dab738c1881a9b38b753"},
{file = "black-23.1.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:a29650759a6a0944e7cca036674655c2f0f63806ddecc45ed40b7b8aa314b651"},
{file = "black-23.1.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:bb460c8561c8c1bec7824ecbc3ce085eb50005883a6203dcfb0122e95797ee06"},
{file = "black-23.1.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c91dfc2c2a4e50df0026f88d2215e166616e0c80e86004d0003ece0488db2739"},
{file = "black-23.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a951cc83ab535d248c89f300eccbd625e80ab880fbcfb5ac8afb5f01a258ac9"},
{file = "black-23.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:0680d4380db3719ebcfb2613f34e86c8e6d15ffeabcf8ec59355c5e7b85bb555"},
{file = "black-23.1.0-py3-none-any.whl", hash = "sha256:7a0f701d314cfa0896b9001df70a530eb2472babb76086344e688829efd97d32"},
{file = "black-23.1.0.tar.gz", hash = "sha256:b0bd97bea8903f5a2ba7219257a44e3f1f9d00073d6cc1add68f0beec69692ac"},
]
[package.dependencies]
click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
packaging = ">=22.0"
pathspec = ">=0.9.0"
platformdirs = ">=2"
tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""}
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
[package.extras]
colorama = ["colorama (>=0.4.3)"]
@ -625,14 +640,14 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
[[package]]
name = "dateparser"
version = "1.1.7"
version = "1.1.8"
description = "Date parsing library designed to parse dates from HTML pages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "dateparser-1.1.7-py2.py3-none-any.whl", hash = "sha256:fbed8b738a24c9cd7f47c4f2089527926566fe539e1a06125eddba75917b1eef"},
{file = "dateparser-1.1.7.tar.gz", hash = "sha256:ff047d9cffad4d3113ead8ec0faf8a7fc43bab7d853ac8715e071312b53c465a"},
{file = "dateparser-1.1.8-py2.py3-none-any.whl", hash = "sha256:070b29b5bbf4b1ec2cd51c96ea040dc68a614de703910a91ad1abba18f9f379f"},
{file = "dateparser-1.1.8.tar.gz", hash = "sha256:86b8b7517efcc558f085a142cdb7620f0921543fcabdb538c8a4c4001d8178e3"},
]
[package.dependencies]
@ -710,19 +725,19 @@ dev = ["coverage", "coveralls", "pytest"]
[[package]]
name = "filelock"
version = "3.10.0"
version = "3.10.3"
description = "A platform independent file lock."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "filelock-3.10.0-py3-none-any.whl", hash = "sha256:e90b34656470756edf8b19656785c5fea73afa1953f3e1b0d645cef11cab3182"},
{file = "filelock-3.10.0.tar.gz", hash = "sha256:3199fd0d3faea8b911be52b663dfccceb84c95949dd13179aa21436d1a79c4ce"},
{file = "filelock-3.10.3-py3-none-any.whl", hash = "sha256:99d6282f732410d44242ca02aa49835cf5473e2dd4d6734a2a785c8889dc191e"},
{file = "filelock-3.10.3.tar.gz", hash = "sha256:a26bfa34d26293e04886dff13fa8dd0c8c6e1a786b723c689755fe8939297410"},
]
[package.extras]
docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"]
testing = ["covdefaults (>=2.3)", "coverage (>=7.2.1)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"]
testing = ["covdefaults (>=2.3)", "coverage (>=7.2.2)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"]
[[package]]
name = "frozenlist"
@ -840,14 +855,14 @@ gitdb = ">=4.0.1,<5"
[[package]]
name = "identify"
version = "2.5.20"
version = "2.5.21"
description = "File identification library for Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "identify-2.5.20-py2.py3-none-any.whl", hash = "sha256:5dfef8a745ca4f2c95f27e9db74cb4c8b6d9916383988e8791f3595868f78a33"},
{file = "identify-2.5.20.tar.gz", hash = "sha256:c8b288552bc5f05a08aff09af2f58e6976bf8ac87beb38498a0e3d98ba64eb18"},
{file = "identify-2.5.21-py2.py3-none-any.whl", hash = "sha256:69edcaffa8e91ae0f77d397af60f148b6b45a8044b2cc6d99cafa5b04793ff00"},
{file = "identify-2.5.21.tar.gz", hash = "sha256:7671a05ef9cfaf8ff63b15d45a91a1147a03aaccb2976d4e9bd047cbbc508471"},
]
[package.extras]
@ -867,14 +882,14 @@ files = [
[[package]]
name = "importlib-metadata"
version = "6.0.0"
version = "6.1.0"
description = "Read metadata from Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "importlib_metadata-6.0.0-py3-none-any.whl", hash = "sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad"},
{file = "importlib_metadata-6.0.0.tar.gz", hash = "sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d"},
{file = "importlib_metadata-6.1.0-py3-none-any.whl", hash = "sha256:ff80f3b5394912eb1b108fcfd444dc78b7f1f3e16b16188054bd01cb9cb86f09"},
{file = "importlib_metadata-6.1.0.tar.gz", hash = "sha256:43ce9281e097583d758c2c708c4376371261a02c34682491a8e98352365aad20"},
]
[package.dependencies]
@ -891,32 +906,33 @@ version = "5.0.0"
description = "Easy, simple, scalable and modular: a Python API wrapper for interactions."
category = "main"
optional = false
python-versions = ">=3.10,<4.0"
python-versions = ">=3.10"
files = []
develop = false
[package.dependencies]
aiohttp = "^3.8.3"
attrs = ">=22.1.0"
discord-typings = "^0.5.1"
emoji = "^2.1.0"
mypy = ">0.930"
tomli = "^2.0.1"
aiohttp = "*"
attrs = "*"
discord-typings = ">=0.5.1"
emoji = "*"
tomli = "*"
[package.extras]
console = []
docs = ["mkdocs-autorefs", "mkdocs-awesome-pages-plugin", "mkdocs-git-committers-plugin-2", "mkdocs-git-revision-date-localized-plugin", "mkdocs-material", "mkdocs-minify-plugin", "mkdocstrings-python"]
jurigged = []
sentry = []
all = ["Brotli", "PyNaCl (>=1.5.0,<1.6)", "aioconsole (>=0.6.0)", "aiodns", "faust-cchardet", "jurigged", "orjson", "sentry-sdk", "uvloop"]
console = ["aioconsole (>=0.6.0)"]
dev = ["Brotli", "PyNaCl (>=1.5.0,<1.6)", "aioconsole (>=0.6.0)", "aiodns", "faust-cchardet", "jurigged", "mkdocs-autorefs", "mkdocs-awesome-pages-plugin", "mkdocs-git-committers-plugin-2", "mkdocs-git-revision-date-localized-plugin", "mkdocs-material", "mkdocs-minify-plugin", "mkdocstrings-python", "orjson", "pre-commit", "pytest", "pytest-asyncio", "pytest-cov", "pytest-recording", "python-dotenv", "sentry-sdk", "typeguard", "uvloop"]
docs = ["Brotli", "PyNaCl (>=1.5.0,<1.6)", "aioconsole (>=0.6.0)", "aiodns", "faust-cchardet", "jurigged", "mkdocs-autorefs", "mkdocs-awesome-pages-plugin", "mkdocs-git-committers-plugin-2", "mkdocs-git-revision-date-localized-plugin", "mkdocs-material", "mkdocs-minify-plugin", "mkdocstrings-python", "orjson", "sentry-sdk", "uvloop"]
jurigged = ["jurigged"]
sentry = ["sentry-sdk"]
speedup = ["Brotli", "aiodns", "faust-cchardet", "orjson", "uvloop"]
tests = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-recording", "python-dotenv", "typeguard"]
voice = []
voice = ["PyNaCl (>=1.5.0,<1.6)"]
[package.source]
type = "git"
url = "https://github.com/interactions-py/interactions.py"
reference = "5.x"
resolved_reference = "316388be6d608e12e64c93af2cc1b03fc0acfa97"
resolved_reference = "dc2554a61387c953bcaad79a7166f93b98dd0eab"
[[package]]
name = "jarvis-core"
@ -943,7 +959,7 @@ umongo = "^3.1.0"
type = "git"
url = "https://git.zevaryx.com/stark-industries/jarvis/jarvis-core.git"
reference = "main"
resolved_reference = "392797c4aea76db0dff8772d95acea3ff3094b46"
resolved_reference = "ec4219e5a54bea78ff19f23f1754a036e8d0eae3"
[[package]]
name = "jinxed"
@ -1240,58 +1256,11 @@ files = [
{file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"},
]
[[package]]
name = "mypy"
version = "1.1.1"
description = "Optional static typing for Python"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "mypy-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39c7119335be05630611ee798cc982623b9e8f0cff04a0b48dfc26100e0b97af"},
{file = "mypy-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61bf08362e93b6b12fad3eab68c4ea903a077b87c90ac06c11e3d7a09b56b9c1"},
{file = "mypy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbb19c9f662e41e474e0cff502b7064a7edc6764f5262b6cd91d698163196799"},
{file = "mypy-1.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:315ac73cc1cce4771c27d426b7ea558fb4e2836f89cb0296cbe056894e3a1f78"},
{file = "mypy-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:5cb14ff9919b7df3538590fc4d4c49a0f84392237cbf5f7a816b4161c061829e"},
{file = "mypy-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:26cdd6a22b9b40b2fd71881a8a4f34b4d7914c679f154f43385ca878a8297389"},
{file = "mypy-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b5f81b40d94c785f288948c16e1f2da37203c6006546c5d947aab6f90aefef2"},
{file = "mypy-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b437be1c02712a605591e1ed1d858aba681757a1e55fe678a15c2244cd68a5"},
{file = "mypy-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d809f88734f44a0d44959d795b1e6f64b2bbe0ea4d9cc4776aa588bb4229fc1c"},
{file = "mypy-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:a380c041db500e1410bb5b16b3c1c35e61e773a5c3517926b81dfdab7582be54"},
{file = "mypy-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b7c7b708fe9a871a96626d61912e3f4ddd365bf7f39128362bc50cbd74a634d5"},
{file = "mypy-1.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1c10fa12df1232c936830839e2e935d090fc9ee315744ac33b8a32216b93707"},
{file = "mypy-1.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0a28a76785bf57655a8ea5eb0540a15b0e781c807b5aa798bd463779988fa1d5"},
{file = "mypy-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ef6a01e563ec6a4940784c574d33f6ac1943864634517984471642908b30b6f7"},
{file = "mypy-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d64c28e03ce40d5303450f547e07418c64c241669ab20610f273c9e6290b4b0b"},
{file = "mypy-1.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:64cc3afb3e9e71a79d06e3ed24bb508a6d66f782aff7e56f628bf35ba2e0ba51"},
{file = "mypy-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce61663faf7a8e5ec6f456857bfbcec2901fbdb3ad958b778403f63b9e606a1b"},
{file = "mypy-1.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2b0c373d071593deefbcdd87ec8db91ea13bd8f1328d44947e88beae21e8d5e9"},
{file = "mypy-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:2888ce4fe5aae5a673386fa232473014056967f3904f5abfcf6367b5af1f612a"},
{file = "mypy-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:19ba15f9627a5723e522d007fe708007bae52b93faab00f95d72f03e1afa9598"},
{file = "mypy-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:59bbd71e5c58eed2e992ce6523180e03c221dcd92b52f0e792f291d67b15a71c"},
{file = "mypy-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9401e33814cec6aec8c03a9548e9385e0e228fc1b8b0a37b9ea21038e64cdd8a"},
{file = "mypy-1.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b398d8b1f4fba0e3c6463e02f8ad3346f71956b92287af22c9b12c3ec965a9f"},
{file = "mypy-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:69b35d1dcb5707382810765ed34da9db47e7f95b3528334a3c999b0c90fe523f"},
{file = "mypy-1.1.1-py3-none-any.whl", hash = "sha256:4e4e8b362cdf99ba00c2b218036002bdcdf1e0de085cdb296a49df03fb31dfc4"},
{file = "mypy-1.1.1.tar.gz", hash = "sha256:ae9ceae0f5b9059f33dbc62dea087e942c0ccab4b7a003719cb70f9b8abfa32f"},
]
[package.dependencies]
mypy-extensions = ">=1.0.0"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
typing-extensions = ">=3.10"
[package.extras]
dmypy = ["psutil (>=4.0)"]
install-types = ["pip"]
python2 = ["typed-ast (>=1.4.0,<2)"]
reports = ["lxml"]
[[package]]
name = "mypy-extensions"
version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
category = "main"
category = "dev"
optional = false
python-versions = ">=3.5"
files = [
@ -1422,56 +1391,61 @@ numpy = [
[[package]]
name = "orjson"
version = "3.8.7"
version = "3.8.8"
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "orjson-3.8.7-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:f98c82850b7b4b7e27785ca43706fa86c893cdb88d54576bbb9b0d9c1070e421"},
{file = "orjson-3.8.7-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:1dee503c6c1a0659c5b46f5f39d9ca9d3657b11ca8bb4af8506086df416887d9"},
{file = "orjson-3.8.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc4fa83831f42ce5c938f8cefc2e175fa1df6f661fdeaba3badf26d2b8cfcf73"},
{file = "orjson-3.8.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e432c6c9c8b97ad825276d5795286f7cc9689f377a97e3b7ecf14918413303f"},
{file = "orjson-3.8.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee519964a5a0efb9633f38b1129fd242807c5c57162844efeeaab1c8de080051"},
{file = "orjson-3.8.7-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:109b539ce5bf60a121454d008fa67c3b67e5a3249e47d277012645922cf74bd0"},
{file = "orjson-3.8.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ad4d441fbde4133af6fee37f67dbf23181b9c537ecc317346ec8c3b4c8ec7705"},
{file = "orjson-3.8.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:89dc786419e1ce2588345f58dd6a434e6728bce66b94989644234bcdbe39b603"},
{file = "orjson-3.8.7-cp310-none-win_amd64.whl", hash = "sha256:697abde7350fb8076d44bcb6b4ab3ce415ae2b5a9bb91efc460e5ab0d96bb5d3"},
{file = "orjson-3.8.7-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:1c19f47b35b9966a3abadf341b18ee4a860431bf2b00fd8d58906d51cf78aa70"},
{file = "orjson-3.8.7-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:3ffaabb380cd0ee187b4fc362516df6bf739808130b1339445c7d8878fca36e7"},
{file = "orjson-3.8.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d88837002c5a8af970745b8e0ca1b0fdb06aafbe7f1279e110d338ea19f3d23"},
{file = "orjson-3.8.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff60187d1b7e0bfab376b6002b08c560b7de06c87cf3a8ac639ecf58f84c5f3b"},
{file = "orjson-3.8.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0110970aed35dec293f30ed1e09f8604afd5d15c5ef83de7f6c427619b3ba47b"},
{file = "orjson-3.8.7-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:51b275475d4e36118b65ad56f9764056a09d985c5d72e64579bf8816f1356a5e"},
{file = "orjson-3.8.7-cp311-none-win_amd64.whl", hash = "sha256:63144d27735f3b60f079f247ac9a289d80dfe49a7f03880dfa0c0ba64d6491d5"},
{file = "orjson-3.8.7-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:a16273d77db746bb1789a2bbfded81148a60743fd6f9d5185e02d92e3732fa18"},
{file = "orjson-3.8.7-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5bb32259ea22cc9dd47a6fdc4b8f9f1e2f798fcf56c7c1122a7df0f4c5d33bf3"},
{file = "orjson-3.8.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad02e9102d4ba67db30a136e631e32aeebd1dce26c9f5942a457b02df131c5d0"},
{file = "orjson-3.8.7-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dbcfcec2b7ac52deb7be3685b551addc28ee8fa454ef41f8b714df6ba0e32a27"},
{file = "orjson-3.8.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a0e5504a5fc86083cc210c6946e8d61e13fe9f1d7a7bf81b42f7050a49d4fb"},
{file = "orjson-3.8.7-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:7bd4fd37adb03b1f2a1012d43c9f95973a02164e131dfe3ff804d7e180af5653"},
{file = "orjson-3.8.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:188ed9f9a781333ad802af54c55d5a48991e292239aef41bd663b6e314377eb8"},
{file = "orjson-3.8.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:cc52f58c688cb10afd810280e450f56fbcb27f52c053463e625c8335c95db0dc"},
{file = "orjson-3.8.7-cp37-none-win_amd64.whl", hash = "sha256:403c8c84ac8a02c40613b0493b74d5256379e65196d39399edbf2ed3169cbeb5"},
{file = "orjson-3.8.7-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:7d6ac5f8a2a17095cd927c4d52abbb38af45918e0d3abd60fb50cfd49d71ae24"},
{file = "orjson-3.8.7-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:0295a7bfd713fa89231fd0822c995c31fc2343c59a1d13aa1b8b6651335654f5"},
{file = "orjson-3.8.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feb32aaaa34cf2f891eb793ad320d4bb6731328496ae59b6c9eb1b620c42b529"},
{file = "orjson-3.8.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7a3ab1a473894e609b6f1d763838c6689ba2b97620c256a32c4d9f10595ac179"},
{file = "orjson-3.8.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e8c430d82b532c5ab95634e034bbf6ca7432ffe175a3e63eadd493e00b3a555"},
{file = "orjson-3.8.7-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:366cc75f7e09106f9dac95a675aef413367b284f25507d21e55bd7f45f445e80"},
{file = "orjson-3.8.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:84d154d07e8b17d97e990d5d710b719a031738eb1687d8a05b9089f0564ff3e0"},
{file = "orjson-3.8.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06180014afcfdc167ca984b312218aa62ce20093965c437c5f9166764cb65ef7"},
{file = "orjson-3.8.7-cp38-none-win_amd64.whl", hash = "sha256:41244431ba13f2e6ef22b52c5cf0202d17954489f4a3c0505bd28d0e805c3546"},
{file = "orjson-3.8.7-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:b20f29fa8371b8023f1791df035a2c3ccbd98baa429ac3114fc104768f7db6f8"},
{file = "orjson-3.8.7-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:226bfc1da2f21ee74918cee2873ea9a0fec1a8830e533cb287d192d593e99d02"},
{file = "orjson-3.8.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e75c11023ac29e29fd3e75038d0e8dd93f9ea24d7b9a5e871967a8921a88df24"},
{file = "orjson-3.8.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:78604d3acfd7cd502f6381eea0c42281fe2b74755b334074ab3ebc0224100be1"},
{file = "orjson-3.8.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7129a6847f0494aa1427167486ef6aea2e835ba05f6c627df522692ee228f65"},
{file = "orjson-3.8.7-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1a1a8f4980059f48483782c608145b0f74538c266e01c183d9bcd9f8b71dbada"},
{file = "orjson-3.8.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d60304172a33705ce4bd25a6261ab84bed2dab0b3d3b79672ea16c7648af4832"},
{file = "orjson-3.8.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4f733062d84389c32c0492e5a4929056fac217034a94523debe0430bcc602cda"},
{file = "orjson-3.8.7-cp39-none-win_amd64.whl", hash = "sha256:010e2970ec9e826c332819e0da4b14b29b19641da0f1a6af4cec91629ef9b988"},
{file = "orjson-3.8.7.tar.gz", hash = "sha256:8460c8810652dba59c38c80d27c325b5092d189308d8d4f3e688dbd8d4f3b2dc"},
{file = "orjson-3.8.8-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:18fcdea75d8b571dc9b185652b81397b62878ae7934fd62e6a0103a5b8448e34"},
{file = "orjson-3.8.8-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:306618884929b596e2e083f82b5617da812df25b0c467542371f1d51f0c5a6f5"},
{file = "orjson-3.8.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edc65ddb6ae6f8fbb2bbf78ac98f75b729c9eeb0776d5508dd76d3a948dda1dd"},
{file = "orjson-3.8.8-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e6a6d55e01bce74516dff15302627a13b1f4edcb1c3942dd660978dee423ccf2"},
{file = "orjson-3.8.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28075c4b502d792fb6703e983d456b2a30d5d6f332d26092eb312dc782e64c64"},
{file = "orjson-3.8.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eda4c37e48ff549763183a1549c10eec6ea40439520b17d09359cd74a425069"},
{file = "orjson-3.8.8-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a3eac485a15493164867729f44e1e1247b3094ff19d37708e8cdc9c88a93c623"},
{file = "orjson-3.8.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:88bf40e5468444c04374d1b8f1877cebbaef6bb7406cb6b4a34a570c5cbb87bc"},
{file = "orjson-3.8.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:747bd4e09d8aa61e1ff677a7dd1cffd28a5d13c22f3769123c58ec988bf1b83d"},
{file = "orjson-3.8.8-cp310-none-win_amd64.whl", hash = "sha256:dd7d86c5f5f820ac9d4783477e86eb984b63bdb32359935609eb33cf65049c54"},
{file = "orjson-3.8.8-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:52293a6097750c2d434737966fe6e2a1ed489ac70cc8e584f5944af83de0b787"},
{file = "orjson-3.8.8-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:9322450f392dceb49810d2f820b1932af22d66f67f1d45c31f160067dd06359f"},
{file = "orjson-3.8.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68d59e3ae84a9b6f14b45a89f7fde4a08a87ea5eb76bfc854b354640de8156f5"},
{file = "orjson-3.8.8-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:022347dad2253081eaa25366834bb8b06a5aceb0e83b39c6b0aa865759e49d69"},
{file = "orjson-3.8.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddfcc54793e266056fe1c257d0804c336bca1c5c1ee7979d674e1fc19cfb0a6a"},
{file = "orjson-3.8.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:449d8ed1e0e6b24e9df5a06b59fd66ea7f7293e141257069601ae8ff9fad705c"},
{file = "orjson-3.8.8-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:0204bc414bc6f7a595211569840b422d96649fd8686efa1fbbcb12eed5dd9521"},
{file = "orjson-3.8.8-cp311-none-win_amd64.whl", hash = "sha256:e991a5c2c5f2f299c77e1d07ef2812ff5b68e1d97a2aab01aca29cf756473aa3"},
{file = "orjson-3.8.8-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:2006d9c046bbf335c951f61e016a27bd4f17323dd116f601e4a8a11739cd0a62"},
{file = "orjson-3.8.8-cp37-cp37m-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:4553d85bad4cbd634a40b7b5d36daaa197a6025f9ce3e2165b371e528759093d"},
{file = "orjson-3.8.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57ee45d2cc6c11c50afb5a0c09d7cd559aea76c77250dbe996be6a03464d4a50"},
{file = "orjson-3.8.8-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:02f5b5db1e424706eb9f70f1c25699ff4cef16fadfc64af5b70f8628eafe4771"},
{file = "orjson-3.8.8-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d7c9f3b1598a1ccd806ef02257a76a00c7ede09662ddb54eec2b4bd92874254"},
{file = "orjson-3.8.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b90d171932b6a9d50e79fa2762cb303e3556bbf25c08bb316fe346ec58af9c19"},
{file = "orjson-3.8.8-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:28dfe774c345130f1117c4d023644ec52d9d50e3eaadb9bd1c668d91dc109bb5"},
{file = "orjson-3.8.8-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8f84116fcc3714e7ba3cbeb1b11ac5e4549e7d2726c50142f8299fff9dea7d53"},
{file = "orjson-3.8.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:f989f8580db86166aaaa938ccd1597ba1817e3f5df14c047baafe783e3d24173"},
{file = "orjson-3.8.8-cp37-none-win_amd64.whl", hash = "sha256:66045850f286090800a18662d81d44f88c3fcb60ea3a9947d5caeab5d1efc92e"},
{file = "orjson-3.8.8-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:2c2c5f3d3bbd61dba646e2b9c54a0dd7941b03fba49726bd31c1c23fedf0b9aa"},
{file = "orjson-3.8.8-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:9cb36d4a14f3a911369219d5abc19b907bc41ed2730f7bfe0847b0fd3e834c87"},
{file = "orjson-3.8.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:343124f84da0a33c83ee106a98b3e3c42767c88323d4a2809683cbe83816e8be"},
{file = "orjson-3.8.8-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:24ad122d8dd057acf2a9965a2ffc1bc12fb310ae1cfe2912db930cbb9ef7eaba"},
{file = "orjson-3.8.8-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2f28a92a9bcb4e8635524b20db1b539bda8613872f306b36cdfd9d3577d03ac"},
{file = "orjson-3.8.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81d3c5b253eebfc4a61cea1f255a576cb2b889afa99f4510f30ec13201d4f457"},
{file = "orjson-3.8.8-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:317164f7d4c0540a6eb8b0a0faeec84ef011d359da05188423db762b65f84e1d"},
{file = "orjson-3.8.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5e7e39357371d4ae5649f33c01886508a4c8e5fa5c7344554af041dc0f004c01"},
{file = "orjson-3.8.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:60fefd4bbd796b4296f478e705fe2c2c7defd28da98d3017743eb87c3238a380"},
{file = "orjson-3.8.8-cp38-none-win_amd64.whl", hash = "sha256:0dc4a52f1087baeec6b58248fd6b01f17c124fb99f6f770596851ea434a7be0b"},
{file = "orjson-3.8.8-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:a6bcb449537a99f55c5f05187bac00b4549a795e89c10dcca0d7629548852357"},
{file = "orjson-3.8.8-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:9c98dc791aa44268ba7f6e21124cf885c813b155316c6bf257560571d243fe15"},
{file = "orjson-3.8.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b2abf93b727a6af7c5ec8816168cbdff39c716af18ced425dd50ae46d69765c"},
{file = "orjson-3.8.8-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:23447d38375a19d57975d4e32d9ce9f533803c197fd4292e10d3234c052037a8"},
{file = "orjson-3.8.8-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c2e19d2b46cc93c7218bf8180807bf922ff61dc9883458a06edc66d22970fff"},
{file = "orjson-3.8.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e480d74d7bf415e6548a364669404119a85dbe0e3c6cd5f7cb4c7003eac20164"},
{file = "orjson-3.8.8-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:8e0bff5656b99dd975cae2e5230b39e5909d06c0692fd1f6f06dc46f1fe705d0"},
{file = "orjson-3.8.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:56bb6eb7a254eec3b15feba9b20f4172ccbe6ea50a54cf66cbc8e1e4a19585c2"},
{file = "orjson-3.8.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1af1cfad5d90b68e15fd625c889c4f9f91d7a88f49512cdb89f01c3881e0c9d9"},
{file = "orjson-3.8.8-cp39-none-win_amd64.whl", hash = "sha256:d5514dfe200356a1d5a6039e00dca78d87d063f3da1eb6a371253e5a8b7ab5b0"},
{file = "orjson-3.8.8.tar.gz", hash = "sha256:c096d7a523bae6ffb9c4a228ba4691d66113f0f2231579dc945523fbef09c6da"},
]
[[package]]
@ -1774,48 +1748,48 @@ files = [
[[package]]
name = "pydantic"
version = "1.10.6"
version = "1.10.7"
description = "Data validation and settings management using python type hints"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "pydantic-1.10.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9289065611c48147c1dd1fd344e9d57ab45f1d99b0fb26c51f1cf72cd9bcd31"},
{file = "pydantic-1.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c32b6bba301490d9bb2bf5f631907803135e8085b6aa3e5fe5a770d46dd0160"},
{file = "pydantic-1.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd9b9e98068fa1068edfc9eabde70a7132017bdd4f362f8b4fd0abed79c33083"},
{file = "pydantic-1.10.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c84583b9df62522829cbc46e2b22e0ec11445625b5acd70c5681ce09c9b11c4"},
{file = "pydantic-1.10.6-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b41822064585fea56d0116aa431fbd5137ce69dfe837b599e310034171996084"},
{file = "pydantic-1.10.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:61f1f08adfaa9cc02e0cbc94f478140385cbd52d5b3c5a657c2fceb15de8d1fb"},
{file = "pydantic-1.10.6-cp310-cp310-win_amd64.whl", hash = "sha256:32937835e525d92c98a1512218db4eed9ddc8f4ee2a78382d77f54341972c0e7"},
{file = "pydantic-1.10.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bbd5c531b22928e63d0cb1868dee76123456e1de2f1cb45879e9e7a3f3f1779b"},
{file = "pydantic-1.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e277bd18339177daa62a294256869bbe84df1fb592be2716ec62627bb8d7c81d"},
{file = "pydantic-1.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f15277d720aa57e173954d237628a8d304896364b9de745dcb722f584812c7"},
{file = "pydantic-1.10.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b243b564cea2576725e77aeeda54e3e0229a168bc587d536cd69941e6797543d"},
{file = "pydantic-1.10.6-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3ce13a558b484c9ae48a6a7c184b1ba0e5588c5525482681db418268e5f86186"},
{file = "pydantic-1.10.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3ac1cd4deed871dfe0c5f63721e29debf03e2deefa41b3ed5eb5f5df287c7b70"},
{file = "pydantic-1.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:b1eb6610330a1dfba9ce142ada792f26bbef1255b75f538196a39e9e90388bf4"},
{file = "pydantic-1.10.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4ca83739c1263a044ec8b79df4eefc34bbac87191f0a513d00dd47d46e307a65"},
{file = "pydantic-1.10.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea4e2a7cb409951988e79a469f609bba998a576e6d7b9791ae5d1e0619e1c0f2"},
{file = "pydantic-1.10.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53de12b4608290992a943801d7756f18a37b7aee284b9ffa794ee8ea8153f8e2"},
{file = "pydantic-1.10.6-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:60184e80aac3b56933c71c48d6181e630b0fbc61ae455a63322a66a23c14731a"},
{file = "pydantic-1.10.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:415a3f719ce518e95a92effc7ee30118a25c3d032455d13e121e3840985f2efd"},
{file = "pydantic-1.10.6-cp37-cp37m-win_amd64.whl", hash = "sha256:72cb30894a34d3a7ab6d959b45a70abac8a2a93b6480fc5a7bfbd9c935bdc4fb"},
{file = "pydantic-1.10.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3091d2eaeda25391405e36c2fc2ed102b48bac4b384d42b2267310abae350ca6"},
{file = "pydantic-1.10.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:751f008cd2afe812a781fd6aa2fb66c620ca2e1a13b6a2152b1ad51553cb4b77"},
{file = "pydantic-1.10.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12e837fd320dd30bd625be1b101e3b62edc096a49835392dcf418f1a5ac2b832"},
{file = "pydantic-1.10.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:587d92831d0115874d766b1f5fddcdde0c5b6c60f8c6111a394078ec227fca6d"},
{file = "pydantic-1.10.6-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:476f6674303ae7965730a382a8e8d7fae18b8004b7b69a56c3d8fa93968aa21c"},
{file = "pydantic-1.10.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3a2be0a0f32c83265fd71a45027201e1278beaa82ea88ea5b345eea6afa9ac7f"},
{file = "pydantic-1.10.6-cp38-cp38-win_amd64.whl", hash = "sha256:0abd9c60eee6201b853b6c4be104edfba4f8f6c5f3623f8e1dba90634d63eb35"},
{file = "pydantic-1.10.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6195ca908045054dd2d57eb9c39a5fe86409968b8040de8c2240186da0769da7"},
{file = "pydantic-1.10.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43cdeca8d30de9a897440e3fb8866f827c4c31f6c73838e3a01a14b03b067b1d"},
{file = "pydantic-1.10.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c19eb5163167489cb1e0161ae9220dadd4fc609a42649e7e84a8fa8fff7a80f"},
{file = "pydantic-1.10.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:012c99a9c0d18cfde7469aa1ebff922e24b0c706d03ead96940f5465f2c9cf62"},
{file = "pydantic-1.10.6-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:528dcf7ec49fb5a84bf6fe346c1cc3c55b0e7603c2123881996ca3ad79db5bfc"},
{file = "pydantic-1.10.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:163e79386c3547c49366e959d01e37fc30252285a70619ffc1b10ede4758250a"},
{file = "pydantic-1.10.6-cp39-cp39-win_amd64.whl", hash = "sha256:189318051c3d57821f7233ecc94708767dd67687a614a4e8f92b4a020d4ffd06"},
{file = "pydantic-1.10.6-py3-none-any.whl", hash = "sha256:acc6783751ac9c9bc4680379edd6d286468a1dc8d7d9906cd6f1186ed682b2b0"},
{file = "pydantic-1.10.6.tar.gz", hash = "sha256:cf95adb0d1671fc38d8c43dd921ad5814a735e7d9b4d9e437c088002863854fd"},
{file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"},
{file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"},
{file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"},
{file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"},
{file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"},
{file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"},
{file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"},
{file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"},
{file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"},
{file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"},
{file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"},
{file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"},
{file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"},
{file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"},
{file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"},
{file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"},
{file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"},
{file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"},
{file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"},
{file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"},
{file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"},
{file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"},
{file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"},
{file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"},
{file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"},
{file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"},
{file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"},
{file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"},
{file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"},
{file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"},
{file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"},
{file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"},
{file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"},
{file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"},
{file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"},
{file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"},
]
[package.dependencies]
@ -2214,18 +2188,18 @@ full = ["numpy"]
[[package]]
name = "redis"
version = "4.5.1"
version = "4.5.3"
description = "Python client for Redis database and key-value store"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "redis-4.5.1-py3-none-any.whl", hash = "sha256:5deb072d26e67d2be1712603bfb7947ec3431fb0eec9c578994052e33035af6d"},
{file = "redis-4.5.1.tar.gz", hash = "sha256:1eec3741cda408d3a5f84b78d089c8b8d895f21b3b050988351e925faf202864"},
{file = "redis-4.5.3-py3-none-any.whl", hash = "sha256:7df17a0a2b72a4c8895b462dd07616c51b1dcb48fdd7ecb7b6f4bf39ecb2e94e"},
{file = "redis-4.5.3.tar.gz", hash = "sha256:56732e156fe31801c4f43396bd3ca0c2a7f6f83d7936798531b9848d103381aa"},
]
[package.dependencies]
async-timeout = ">=4.0.2"
async-timeout = {version = ">=4.0.2", markers = "python_version < \"3.11\""}
[package.extras]
hiredis = ["hiredis (>=1.0.0)"]
@ -2233,100 +2207,72 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"
[[package]]
name = "regex"
version = "2022.10.31"
version = "2023.3.23"
description = "Alternative regular expression module, to replace re."
category = "main"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.8"
files = [
{file = "regex-2022.10.31-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8ff454ef0bb061e37df03557afda9d785c905dab15584860f982e88be73015f"},
{file = "regex-2022.10.31-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1eba476b1b242620c266edf6325b443a2e22b633217a9835a52d8da2b5c051f9"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0e5af9a9effb88535a472e19169e09ce750c3d442fb222254a276d77808620b"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d03fe67b2325cb3f09be029fd5da8df9e6974f0cde2c2ac6a79d2634e791dd57"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9d0b68ac1743964755ae2d89772c7e6fb0118acd4d0b7464eaf3921c6b49dd4"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a45b6514861916c429e6059a55cf7db74670eaed2052a648e3e4d04f070e001"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8b0886885f7323beea6f552c28bff62cbe0983b9fbb94126531693ea6c5ebb90"},
{file = "regex-2022.10.31-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5aefb84a301327ad115e9d346c8e2760009131d9d4b4c6b213648d02e2abe144"},
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:702d8fc6f25bbf412ee706bd73019da5e44a8400861dfff7ff31eb5b4a1276dc"},
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a3c1ebd4ed8e76e886507c9eddb1a891673686c813adf889b864a17fafcf6d66"},
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:50921c140561d3db2ab9f5b11c5184846cde686bb5a9dc64cae442926e86f3af"},
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:7db345956ecce0c99b97b042b4ca7326feeec6b75facd8390af73b18e2650ffc"},
{file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:763b64853b0a8f4f9cfb41a76a4a85a9bcda7fdda5cb057016e7706fde928e66"},
{file = "regex-2022.10.31-cp310-cp310-win32.whl", hash = "sha256:44136355e2f5e06bf6b23d337a75386371ba742ffa771440b85bed367c1318d1"},
{file = "regex-2022.10.31-cp310-cp310-win_amd64.whl", hash = "sha256:bfff48c7bd23c6e2aec6454aaf6edc44444b229e94743b34bdcdda2e35126cf5"},
{file = "regex-2022.10.31-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b4b1fe58cd102d75ef0552cf17242705ce0759f9695334a56644ad2d83903fe"},
{file = "regex-2022.10.31-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:542e3e306d1669b25936b64917285cdffcd4f5c6f0247636fec037187bd93542"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c27cc1e4b197092e50ddbf0118c788d9977f3f8f35bfbbd3e76c1846a3443df7"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8e38472739028e5f2c3a4aded0ab7eadc447f0d84f310c7a8bb697ec417229e"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:76c598ca73ec73a2f568e2a72ba46c3b6c8690ad9a07092b18e48ceb936e9f0c"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c28d3309ebd6d6b2cf82969b5179bed5fefe6142c70f354ece94324fa11bf6a1"},
{file = "regex-2022.10.31-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9af69f6746120998cd9c355e9c3c6aec7dff70d47247188feb4f829502be8ab4"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a5f9505efd574d1e5b4a76ac9dd92a12acb2b309551e9aa874c13c11caefbe4f"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5ff525698de226c0ca743bfa71fc6b378cda2ddcf0d22d7c37b1cc925c9650a5"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:4fe7fda2fe7c8890d454f2cbc91d6c01baf206fbc96d89a80241a02985118c0c"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2cdc55ca07b4e70dda898d2ab7150ecf17c990076d3acd7a5f3b25cb23a69f1c"},
{file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:44a6c2f6374e0033873e9ed577a54a3602b4f609867794c1a3ebba65e4c93ee7"},
{file = "regex-2022.10.31-cp311-cp311-win32.whl", hash = "sha256:d8716f82502997b3d0895d1c64c3b834181b1eaca28f3f6336a71777e437c2af"},
{file = "regex-2022.10.31-cp311-cp311-win_amd64.whl", hash = "sha256:61edbca89aa3f5ef7ecac8c23d975fe7261c12665f1d90a6b1af527bba86ce61"},
{file = "regex-2022.10.31-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0a069c8483466806ab94ea9068c34b200b8bfc66b6762f45a831c4baaa9e8cdd"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d26166acf62f731f50bdd885b04b38828436d74e8e362bfcb8df221d868b5d9b"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac741bf78b9bb432e2d314439275235f41656e189856b11fb4e774d9f7246d81"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75f591b2055523fc02a4bbe598aa867df9e953255f0b7f7715d2a36a9c30065c"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bddd61d2a3261f025ad0f9ee2586988c6a00c780a2fb0a92cea2aa702c54"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef4163770525257876f10e8ece1cf25b71468316f61451ded1a6f44273eedeb5"},
{file = "regex-2022.10.31-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7b280948d00bd3973c1998f92e22aa3ecb76682e3a4255f33e1020bd32adf443"},
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:d0213671691e341f6849bf33cd9fad21f7b1cb88b89e024f33370733fec58742"},
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:22e7ebc231d28393dfdc19b185d97e14a0f178bedd78e85aad660e93b646604e"},
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:8ad241da7fac963d7573cc67a064c57c58766b62a9a20c452ca1f21050868dfa"},
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:586b36ebda81e6c1a9c5a5d0bfdc236399ba6595e1397842fd4a45648c30f35e"},
{file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0653d012b3bf45f194e5e6a41df9258811ac8fc395579fa82958a8b76286bea4"},
{file = "regex-2022.10.31-cp36-cp36m-win32.whl", hash = "sha256:144486e029793a733e43b2e37df16a16df4ceb62102636ff3db6033994711066"},
{file = "regex-2022.10.31-cp36-cp36m-win_amd64.whl", hash = "sha256:c14b63c9d7bab795d17392c7c1f9aaabbffd4cf4387725a0ac69109fb3b550c6"},
{file = "regex-2022.10.31-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4cac3405d8dda8bc6ed499557625585544dd5cbf32072dcc72b5a176cb1271c8"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23cbb932cc53a86ebde0fb72e7e645f9a5eec1a5af7aa9ce333e46286caef783"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74bcab50a13960f2a610cdcd066e25f1fd59e23b69637c92ad470784a51b1347"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78d680ef3e4d405f36f0d6d1ea54e740366f061645930072d39bca16a10d8c93"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce6910b56b700bea7be82c54ddf2e0ed792a577dfaa4a76b9af07d550af435c6"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:659175b2144d199560d99a8d13b2228b85e6019b6e09e556209dfb8c37b78a11"},
{file = "regex-2022.10.31-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1ddf14031a3882f684b8642cb74eea3af93a2be68893901b2b387c5fd92a03ec"},
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b683e5fd7f74fb66e89a1ed16076dbab3f8e9f34c18b1979ded614fe10cdc4d9"},
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2bde29cc44fa81c0a0c8686992c3080b37c488df167a371500b2a43ce9f026d1"},
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4919899577ba37f505aaebdf6e7dc812d55e8f097331312db7f1aab18767cce8"},
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:9c94f7cc91ab16b36ba5ce476f1904c91d6c92441f01cd61a8e2729442d6fcf5"},
{file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ae1e96785696b543394a4e3f15f3f225d44f3c55dafe3f206493031419fedf95"},
{file = "regex-2022.10.31-cp37-cp37m-win32.whl", hash = "sha256:c670f4773f2f6f1957ff8a3962c7dd12e4be54d05839b216cb7fd70b5a1df394"},
{file = "regex-2022.10.31-cp37-cp37m-win_amd64.whl", hash = "sha256:8e0caeff18b96ea90fc0eb6e3bdb2b10ab5b01a95128dfeccb64a7238decf5f0"},
{file = "regex-2022.10.31-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:131d4be09bea7ce2577f9623e415cab287a3c8e0624f778c1d955ec7c281bd4d"},
{file = "regex-2022.10.31-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e613a98ead2005c4ce037c7b061f2409a1a4e45099edb0ef3200ee26ed2a69a8"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052b670fafbe30966bbe5d025e90b2a491f85dfe5b2583a163b5e60a85a321ad"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa62a07ac93b7cb6b7d0389d8ef57ffc321d78f60c037b19dfa78d6b17c928ee"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5352bea8a8f84b89d45ccc503f390a6be77917932b1c98c4cdc3565137acc714"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20f61c9944f0be2dc2b75689ba409938c14876c19d02f7585af4460b6a21403e"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29c04741b9ae13d1e94cf93fca257730b97ce6ea64cfe1eba11cf9ac4e85afb6"},
{file = "regex-2022.10.31-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:543883e3496c8b6d58bd036c99486c3c8387c2fc01f7a342b760c1ea3158a318"},
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7a8b43ee64ca8f4befa2bea4083f7c52c92864d8518244bfa6e88c751fa8fff"},
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6a9a19bea8495bb419dc5d38c4519567781cd8d571c72efc6aa959473d10221a"},
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6ffd55b5aedc6f25fd8d9f905c9376ca44fcf768673ffb9d160dd6f409bfda73"},
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4bdd56ee719a8f751cf5a593476a441c4e56c9b64dc1f0f30902858c4ef8771d"},
{file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ca88da1bd78990b536c4a7765f719803eb4f8f9971cc22d6ca965c10a7f2c4c"},
{file = "regex-2022.10.31-cp38-cp38-win32.whl", hash = "sha256:5a260758454580f11dd8743fa98319bb046037dfab4f7828008909d0aa5292bc"},
{file = "regex-2022.10.31-cp38-cp38-win_amd64.whl", hash = "sha256:5e6a5567078b3eaed93558842346c9d678e116ab0135e22eb72db8325e90b453"},
{file = "regex-2022.10.31-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5217c25229b6a85049416a5c1e6451e9060a1edcf988641e309dbe3ab26d3e49"},
{file = "regex-2022.10.31-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4bf41b8b0a80708f7e0384519795e80dcb44d7199a35d52c15cc674d10b3081b"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf0da36a212978be2c2e2e2d04bdff46f850108fccc1851332bcae51c8907cc"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d403d781b0e06d2922435ce3b8d2376579f0c217ae491e273bab8d092727d244"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a37d51fa9a00d265cf73f3de3930fa9c41548177ba4f0faf76e61d512c774690"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4f781ffedd17b0b834c8731b75cce2639d5a8afe961c1e58ee7f1f20b3af185"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d243b36fbf3d73c25e48014961e83c19c9cc92530516ce3c43050ea6276a2ab7"},
{file = "regex-2022.10.31-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:370f6e97d02bf2dd20d7468ce4f38e173a124e769762d00beadec3bc2f4b3bc4"},
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:597f899f4ed42a38df7b0e46714880fb4e19a25c2f66e5c908805466721760f5"},
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7dbdce0c534bbf52274b94768b3498abdf675a691fec5f751b6057b3030f34c1"},
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:22960019a842777a9fa5134c2364efaed5fbf9610ddc5c904bd3a400973b0eb8"},
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7f5a3ffc731494f1a57bd91c47dc483a1e10048131ffb52d901bfe2beb6102e8"},
{file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7ef6b5942e6bfc5706301a18a62300c60db9af7f6368042227ccb7eeb22d0892"},
{file = "regex-2022.10.31-cp39-cp39-win32.whl", hash = "sha256:395161bbdbd04a8333b9ff9763a05e9ceb4fe210e3c7690f5e68cedd3d65d8e1"},
{file = "regex-2022.10.31-cp39-cp39-win_amd64.whl", hash = "sha256:957403a978e10fb3ca42572a23e6f7badff39aa1ce2f4ade68ee452dc6807692"},
{file = "regex-2022.10.31.tar.gz", hash = "sha256:a3a98921da9a1bf8457aeee6a551948a83601689e5ecdd736894ea9bbec77e83"},
{file = "regex-2023.3.23-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:845a5e2d84389c4ddada1a9b95c055320070f18bb76512608374aca00d22eca8"},
{file = "regex-2023.3.23-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:87d9951f5a538dd1d016bdc0dcae59241d15fa94860964833a54d18197fcd134"},
{file = "regex-2023.3.23-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37ae17d3be44c0b3f782c28ae9edd8b47c1f1776d4cabe87edc0b98e1f12b021"},
{file = "regex-2023.3.23-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b8eb1e3bca6b48dc721818a60ae83b8264d4089a4a41d62be6d05316ec38e15"},
{file = "regex-2023.3.23-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df45fac182ebc3c494460c644e853515cc24f5ad9da05f8ffb91da891bfee879"},
{file = "regex-2023.3.23-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7006105b10b59971d3b248ad75acc3651c7e4cf54d81694df5a5130a3c3f7ea"},
{file = "regex-2023.3.23-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93f3f1aa608380fe294aa4cb82e2afda07a7598e828d0341e124b8fd9327c715"},
{file = "regex-2023.3.23-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:787954f541ab95d8195d97b0b8cf1dc304424adb1e07365967e656b92b38a699"},
{file = "regex-2023.3.23-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:20abe0bdf03630fe92ccafc45a599bca8b3501f48d1de4f7d121153350a2f77d"},
{file = "regex-2023.3.23-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11d00c31aeab9a6e0503bc77e73ed9f4527b3984279d997eb145d7c7be6268fd"},
{file = "regex-2023.3.23-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:d5bbe0e1511b844794a3be43d6c145001626ba9a6c1db8f84bdc724e91131d9d"},
{file = "regex-2023.3.23-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ea3c0cb56eadbf4ab2277e7a095676370b3e46dbfc74d5c383bd87b0d6317910"},
{file = "regex-2023.3.23-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d895b4c863059a4934d3e874b90998df774644a41b349ebb330f85f11b4ef2c0"},
{file = "regex-2023.3.23-cp310-cp310-win32.whl", hash = "sha256:9d764514d19b4edcc75fd8cb1423448ef393e8b6cbd94f38cab983ab1b75855d"},
{file = "regex-2023.3.23-cp310-cp310-win_amd64.whl", hash = "sha256:11d1f2b7a0696dc0310de0efb51b1f4d813ad4401fe368e83c0c62f344429f98"},
{file = "regex-2023.3.23-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8a9c63cde0eaa345795c0fdeb19dc62d22e378c50b0bc67bf4667cd5b482d98b"},
{file = "regex-2023.3.23-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dd7200b4c27b68cf9c9646da01647141c6db09f48cc5b51bc588deaf8e98a797"},
{file = "regex-2023.3.23-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22720024b90a6ba673a725dcc62e10fb1111b889305d7c6b887ac7466b74bedb"},
{file = "regex-2023.3.23-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b190a339090e6af25f4a5fd9e77591f6d911cc7b96ecbb2114890b061be0ac1"},
{file = "regex-2023.3.23-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e76b6fc0d8e9efa39100369a9b3379ce35e20f6c75365653cf58d282ad290f6f"},
{file = "regex-2023.3.23-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7868b8f218bf69a2a15402fde08b08712213a1f4b85a156d90473a6fb6b12b09"},
{file = "regex-2023.3.23-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2472428efc4127374f494e570e36b30bb5e6b37d9a754f7667f7073e43b0abdd"},
{file = "regex-2023.3.23-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c37df2a060cb476d94c047b18572ee2b37c31f831df126c0da3cd9227b39253d"},
{file = "regex-2023.3.23-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4479f9e2abc03362df4045b1332d4a2b7885b245a30d4f4b051c4083b97d95d8"},
{file = "regex-2023.3.23-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e2396e0678167f2d0c197da942b0b3fb48fee2f0b5915a0feb84d11b6686afe6"},
{file = "regex-2023.3.23-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:75f288c60232a5339e0ff2fa05779a5e9c74e9fc085c81e931d4a264501e745b"},
{file = "regex-2023.3.23-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c869260aa62cee21c5eb171a466c0572b5e809213612ef8d495268cd2e34f20d"},
{file = "regex-2023.3.23-cp311-cp311-win32.whl", hash = "sha256:25f0532fd0c53e96bad84664171969de9673b4131f2297f1db850d3918d58858"},
{file = "regex-2023.3.23-cp311-cp311-win_amd64.whl", hash = "sha256:5ccfafd98473e007cebf7da10c1411035b7844f0f204015efd050601906dbb53"},
{file = "regex-2023.3.23-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6572ff287176c0fb96568adb292674b421fa762153ed074d94b1d939ed92c253"},
{file = "regex-2023.3.23-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a610e0adfcb0fc84ea25f6ea685e39e74cbcd9245a72a9a7aab85ff755a5ed27"},
{file = "regex-2023.3.23-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086afe222d58b88b62847bdbd92079b4699350b4acab892f88a935db5707c790"},
{file = "regex-2023.3.23-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79e29fd62fa2f597a6754b247356bda14b866131a22444d67f907d6d341e10f3"},
{file = "regex-2023.3.23-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c07ce8e9eee878a48ebeb32ee661b49504b85e164b05bebf25420705709fdd31"},
{file = "regex-2023.3.23-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86b036f401895e854de9fefe061518e78d506d8a919cc250dc3416bca03f6f9a"},
{file = "regex-2023.3.23-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78ac8dd8e18800bb1f97aad0d73f68916592dddf233b99d2b5cabc562088503a"},
{file = "regex-2023.3.23-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:539dd010dc35af935b32f248099e38447bbffc10b59c2b542bceead2bed5c325"},
{file = "regex-2023.3.23-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9bf4a5626f2a0ea006bf81e8963f498a57a47d58907eaa58f4b3e13be68759d8"},
{file = "regex-2023.3.23-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf86b4328c204c3f315074a61bc1c06f8a75a8e102359f18ce99fbcbbf1951f0"},
{file = "regex-2023.3.23-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:2848bf76673c83314068241c8d5b7fa9ad9bed866c979875a0e84039349e8fa7"},
{file = "regex-2023.3.23-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c125a02d22c555e68f7433bac8449992fa1cead525399f14e47c2d98f2f0e467"},
{file = "regex-2023.3.23-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cd1671e9d5ac05ce6aa86874dd8dfa048824d1dbe73060851b310c6c1a201a96"},
{file = "regex-2023.3.23-cp38-cp38-win32.whl", hash = "sha256:fffe57312a358be6ec6baeb43d253c36e5790e436b7bf5b7a38df360363e88e9"},
{file = "regex-2023.3.23-cp38-cp38-win_amd64.whl", hash = "sha256:dbb3f87e15d3dd76996d604af8678316ad2d7d20faa394e92d9394dfd621fd0c"},
{file = "regex-2023.3.23-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c88e8c226473b5549fe9616980ea7ca09289246cfbdf469241edf4741a620004"},
{file = "regex-2023.3.23-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6560776ec19c83f3645bbc5db64a7a5816c9d8fb7ed7201c5bcd269323d88072"},
{file = "regex-2023.3.23-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b1fc2632c01f42e06173d8dd9bb2e74ab9b0afa1d698058c867288d2c7a31f3"},
{file = "regex-2023.3.23-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fdf7ad455f1916b8ea5cdbc482d379f6daf93f3867b4232d14699867a5a13af7"},
{file = "regex-2023.3.23-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5fc33b27b1d800fc5b78d7f7d0f287e35079ecabe68e83d46930cf45690e1c8c"},
{file = "regex-2023.3.23-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c49552dc938e3588f63f8a78c86f3c9c75301e813bca0bef13bdb4b87ccf364"},
{file = "regex-2023.3.23-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e152461e9a0aedec7d37fc66ec0fa635eca984777d3d3c3e36f53bf3d3ceb16e"},
{file = "regex-2023.3.23-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:db034255e72d2995cf581b14bb3fc9c00bdbe6822b49fcd4eef79e1d5f232618"},
{file = "regex-2023.3.23-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:55ae114da21b7a790b90255ea52d2aa3a0d121a646deb2d3c6a3194e722fc762"},
{file = "regex-2023.3.23-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ef3f528fe1cc3d139508fe1b22523745aa77b9d6cb5b0bf277f48788ee0b993f"},
{file = "regex-2023.3.23-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:a81c9ec59ca2303acd1ccd7b9ac409f1e478e40e96f8f79b943be476c5fdb8bb"},
{file = "regex-2023.3.23-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cde09c4fdd070772aa2596d97e942eb775a478b32459e042e1be71b739d08b77"},
{file = "regex-2023.3.23-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3cd9f5dd7b821f141d3a6ca0d5d9359b9221e4f051ca3139320adea9f1679691"},
{file = "regex-2023.3.23-cp39-cp39-win32.whl", hash = "sha256:7304863f3a652dab5e68e6fb1725d05ebab36ec0390676d1736e0571ebb713ef"},
{file = "regex-2023.3.23-cp39-cp39-win_amd64.whl", hash = "sha256:54c3fa855a3f7438149de3211738dd9b5f0c733f48b54ae05aa7fce83d48d858"},
{file = "regex-2023.3.23.tar.gz", hash = "sha256:dc80df325b43ffea5cdea2e3eaa97a44f3dd298262b1c7fe9dbb2a9522b956a7"},
]
[[package]]
@ -2475,7 +2421,7 @@ interactions = {git = "https://github.com/interactions-py/interactions.py", rev
type = "git"
url = "https://github.com/zevaryx/statipy"
reference = "main"
resolved_reference = "b73d7812e29e2dc8290b869bc94b029c7c1ec3e9"
resolved_reference = "9bc2f910dafd7702d275185a8b96187c6ab1f8fb"
[[package]]
name = "thefuzz"
@ -2594,14 +2540,14 @@ files = [
[[package]]
name = "tzlocal"
version = "4.2"
version = "4.3"
description = "tzinfo object for the local timezone"
category = "main"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
files = [
{file = "tzlocal-4.2-py3-none-any.whl", hash = "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745"},
{file = "tzlocal-4.2.tar.gz", hash = "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"},
{file = "tzlocal-4.3-py3-none-any.whl", hash = "sha256:b44c4388f3d34f25862cfbb387578a4d70fec417649da694a132f628a23367e2"},
{file = "tzlocal-4.3.tar.gz", hash = "sha256:3f21d09e1b2aa9f2dacca12da240ca37de3ba5237a93addfd6d593afe9073355"},
]
[package.dependencies]
@ -2609,8 +2555,7 @@ pytz-deprecation-shim = "*"
tzdata = {version = "*", markers = "platform_system == \"Windows\""}
[package.extras]
devenv = ["black", "pyroma", "pytest-cov", "zest.releaser"]
test = ["pytest (>=4.3)", "pytest-mock (>=3.3)"]
devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"]
[[package]]
name = "ulid-py"
@ -2705,40 +2650,39 @@ test = ["covdefaults (>=2.2.2)", "coverage (>=7.1)", "coverage-enable-subprocess
[[package]]
name = "watchdog"
version = "2.3.1"
version = "3.0.0"
description = "Filesystem events monitoring"
category = "main"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
files = [
{file = "watchdog-2.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1f1200d4ec53b88bf04ab636f9133cb703eb19768a39351cee649de21a33697"},
{file = "watchdog-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:564e7739abd4bd348aeafbf71cc006b6c0ccda3160c7053c4a53b67d14091d42"},
{file = "watchdog-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:95ad708a9454050a46f741ba5e2f3468655ea22da1114e4c40b8cbdaca572565"},
{file = "watchdog-2.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a073c91a6ef0dda488087669586768195c3080c66866144880f03445ca23ef16"},
{file = "watchdog-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa8b028750b43e80eea9946d01925168eeadb488dfdef1d82be4b1e28067f375"},
{file = "watchdog-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:964fd236cd443933268ae49b59706569c8b741073dbfd7ca705492bae9d39aab"},
{file = "watchdog-2.3.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:91fd146d723392b3e6eb1ac21f122fcce149a194a2ba0a82c5e4d0ee29cd954c"},
{file = "watchdog-2.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efe3252137392a471a2174d721e1037a0e6a5da7beb72a021e662b7000a9903f"},
{file = "watchdog-2.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:85bf2263290591b7c5fa01140601b64c831be88084de41efbcba6ea289874f44"},
{file = "watchdog-2.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f2df370cd8e4e18499dd0bfdef476431bcc396108b97195d9448d90924e3131"},
{file = "watchdog-2.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ea5d86d1bcf4a9d24610aa2f6f25492f441960cf04aed2bd9a97db439b643a7b"},
{file = "watchdog-2.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6f5d0f7eac86807275eba40b577c671b306f6f335ba63a5c5a348da151aba0fc"},
{file = "watchdog-2.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b848c71ef2b15d0ef02f69da8cc120d335cec0ed82a3fa7779e27a5a8527225"},
{file = "watchdog-2.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0d9878be36d2b9271e3abaa6f4f051b363ff54dbbe7e7df1af3c920e4311ee43"},
{file = "watchdog-2.3.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4cd61f98cb37143206818cb1786d2438626aa78d682a8f2ecee239055a9771d5"},
{file = "watchdog-2.3.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3d2dbcf1acd96e7a9c9aefed201c47c8e311075105d94ce5e899f118155709fd"},
{file = "watchdog-2.3.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:03f342a9432fe08107defbe8e405a2cb922c5d00c4c6c168c68b633c64ce6190"},
{file = "watchdog-2.3.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7a596f9415a378d0339681efc08d2249e48975daae391d58f2e22a3673b977cf"},
{file = "watchdog-2.3.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:0e1dd6d449267cc7d6935d7fe27ee0426af6ee16578eed93bacb1be9ff824d2d"},
{file = "watchdog-2.3.1-py3-none-manylinux2014_i686.whl", hash = "sha256:7a1876f660e32027a1a46f8a0fa5747ad4fcf86cb451860eae61a26e102c8c79"},
{file = "watchdog-2.3.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:2caf77ae137935c1466f8cefd4a3aec7017b6969f425d086e6a528241cba7256"},
{file = "watchdog-2.3.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:53f3e95081280898d9e4fc51c5c69017715929e4eea1ab45801d5e903dd518ad"},
{file = "watchdog-2.3.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:9da7acb9af7e4a272089bd2af0171d23e0d6271385c51d4d9bde91fe918c53ed"},
{file = "watchdog-2.3.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:8a4d484e846dcd75e96b96d80d80445302621be40e293bfdf34a631cab3b33dc"},
{file = "watchdog-2.3.1-py3-none-win32.whl", hash = "sha256:a74155398434937ac2780fd257c045954de5b11b5c52fc844e2199ce3eecf4cf"},
{file = "watchdog-2.3.1-py3-none-win_amd64.whl", hash = "sha256:5defe4f0918a2a1a4afbe4dbb967f743ac3a93d546ea4674567806375b024adb"},
{file = "watchdog-2.3.1-py3-none-win_ia64.whl", hash = "sha256:4109cccf214b7e3462e8403ab1e5b17b302ecce6c103eb2fc3afa534a7f27b96"},
{file = "watchdog-2.3.1.tar.gz", hash = "sha256:d9f9ed26ed22a9d331820a8432c3680707ea8b54121ddcc9dc7d9f2ceeb36906"},
{file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"},
{file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"},
{file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"},
{file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"},
{file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"},
{file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"},
{file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"},
{file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"},
{file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"},
{file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"},
{file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"},
{file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"},
{file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"},
{file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"},
{file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"},
{file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"},
{file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"},
{file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"},
{file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"},
{file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"},
{file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"},
{file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"},
{file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"},
{file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"},
{file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"},
{file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"},
{file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"},
]
[package.extras]
@ -2942,4 +2886,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more
[metadata]
lock-version = "2.0"
python-versions = ">=3.10,<4"
content-hash = "973d2a4a3018b5b46a43a44e3d7f3c05b80b5b03a67cc77ccb75bb10194ff646"
content-hash = "a557982b4ff57231c0e25cf53e760e49173fae268fb840e891ff4fe78436d3be"

View file

@ -31,6 +31,8 @@ redis = "^4.4.0"
interactions = {git = "https://github.com/interactions-py/interactions.py", rev = "5.x"}
statipy = {git = "https://github.com/zevaryx/statipy", rev = "main"}
beanie = "^1.17.0"
pydantic = "^1.10.7"
orjson = "^3.8.8"
[tool.poetry.dev-dependencies]
black = {version = "^22.3.0", allow-prereleases = true}
@ -38,6 +40,7 @@ black = {version = "^22.3.0", allow-prereleases = true}
[tool.poetry.group.dev.dependencies]
pre-commit = "^2.21.0"
pandas = "^1.5.3"
black = "^23.1.0"
[build-system]
requires = ["poetry-core>=1.0.0"]