Add calculator cog for math and conversions
This commit is contained in:
parent
e8a419b9e3
commit
97d15f2f6b
6 changed files with 784 additions and 99 deletions
|
@ -22,7 +22,7 @@ repos:
|
|||
rev: 22.3.0
|
||||
hooks:
|
||||
- id: black
|
||||
args: [--line-length=100, --target-version=py310]
|
||||
args: [--line-length=120, --target-version=py310]
|
||||
language_version: python3.10
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-isort
|
||||
|
|
417
jarvis/cogs/calc.py
Normal file
417
jarvis/cogs/calc.py
Normal file
|
@ -0,0 +1,417 @@
|
|||
"""JARVIS Calculator Cog."""
|
||||
import json
|
||||
|
||||
from aiohttp import ClientSession
|
||||
from calculator import calculate
|
||||
from naff import AutocompleteContext, Client, Extension, InteractionContext
|
||||
from naff.models.discord.components import Button
|
||||
from naff.models.discord.embed import Embed, EmbedField
|
||||
from naff.models.discord.enums import ButtonStyles
|
||||
from naff.models.naff.application_commands import (
|
||||
OptionTypes,
|
||||
SlashCommand,
|
||||
SlashCommandChoice,
|
||||
slash_option,
|
||||
)
|
||||
from thefuzz import process
|
||||
|
||||
from jarvis.data import units
|
||||
from jarvis.utils import build_embed
|
||||
|
||||
TEMP_CHOICES = (
|
||||
SlashCommandChoice(name="Fahrenheit", value=0),
|
||||
SlashCommandChoice(name="Celsius", value=1),
|
||||
SlashCommandChoice(name="Kelvin", value=2),
|
||||
)
|
||||
TEMP_LOOKUP = {0: "F", 1: "C", 2: "K"}
|
||||
CURRENCIES = (
|
||||
"AUD",
|
||||
"BGN",
|
||||
"BRL",
|
||||
"CAD",
|
||||
"CHF",
|
||||
"CNY",
|
||||
"CZK",
|
||||
"DKK",
|
||||
"GBP",
|
||||
"HKD",
|
||||
"HRK",
|
||||
"HUF",
|
||||
"IDR",
|
||||
"INR",
|
||||
"ISK",
|
||||
"JPY",
|
||||
"KRW",
|
||||
"MXN",
|
||||
"MYR",
|
||||
"NOK",
|
||||
"NZD",
|
||||
"PHP",
|
||||
"PLN",
|
||||
"RON",
|
||||
"SEK",
|
||||
"SGD",
|
||||
"THB",
|
||||
"TRY",
|
||||
"USD",
|
||||
"ZAR",
|
||||
)
|
||||
|
||||
|
||||
class CalcCog(Extension):
|
||||
"""Calculator functions for JARVIS"""
|
||||
|
||||
def __init__(self, bot: Client):
|
||||
self.bot = bot
|
||||
|
||||
async def _get_currency_conversion(self, from_: str, to: str) -> int:
|
||||
"""Get the conversion rate."""
|
||||
async with ClientSession() as session:
|
||||
async with session.get("https://theforexapi.com/api/latest", params={"base": from_, "symbols": to}) as resp:
|
||||
raw = await resp.content.read()
|
||||
data = json.loads(raw.decode("UTF8"))
|
||||
return data["rates"][to]
|
||||
|
||||
calc = SlashCommand(name="calc", description="Calculate some things")
|
||||
|
||||
@calc.subcommand(sub_cmd_name="math", sub_cmd_description="Do a basic math calculation")
|
||||
@slash_option(name="expression", description="Expression to calculate", required=True, opt_type=OptionTypes.STRING)
|
||||
async def _calc_math(self, ctx: InteractionContext, expression: str) -> None:
|
||||
if expression == "The answer to life, the universe, and everything":
|
||||
fields = (EmbedField(name="Expression", value=f"`{expression}`"), EmbedField(name="Result", value=str(42)))
|
||||
embed = build_embed(title="Calculator", description=None, fields=fields)
|
||||
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, components=components)
|
||||
return
|
||||
try:
|
||||
value = calculate(expression)
|
||||
except Exception as e:
|
||||
await ctx.send(f"Failed to calculate:\n{e}", ephemeral=True)
|
||||
return
|
||||
if not value:
|
||||
await ctx.send("No value? Try a valid expression", ephemeral=True)
|
||||
return
|
||||
|
||||
fields = (EmbedField(name="Expression", value=f"`{expression}`"), EmbedField(name="Result", value=str(value)))
|
||||
embed = build_embed(title="Calculator", description=None, fields=fields)
|
||||
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, components=components)
|
||||
|
||||
convert = calc.group(name="convert", description="Conversion helpers")
|
||||
|
||||
@convert.subcommand(sub_cmd_name="temperature", sub_cmd_description="Convert between temperatures")
|
||||
@slash_option(name="value", description="Value to convert", required=True, opt_type=OptionTypes.NUMBER)
|
||||
@slash_option(
|
||||
name="from_unit", description="From unit", required=True, opt_type=OptionTypes.INTEGER, choices=TEMP_CHOICES
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="To unit", required=True, opt_type=OptionTypes.INTEGER, choices=TEMP_CHOICES
|
||||
)
|
||||
async def _calc_convert_temperature(
|
||||
self, ctx: InteractionContext, value: int, from_unit: int, to_unit: int
|
||||
) -> None:
|
||||
if from_unit == to_unit:
|
||||
converted = value
|
||||
elif from_unit == 0:
|
||||
converted = (value - 32) * (5 / 9)
|
||||
if to_unit == 2:
|
||||
converted += 273.15
|
||||
elif from_unit == 1:
|
||||
if to_unit == 0:
|
||||
converted = (value * 9 / 5) + 32
|
||||
else:
|
||||
converted = value + 273.15
|
||||
else:
|
||||
converted = value + 273.15
|
||||
if to_unit == 0:
|
||||
converted = (value * 9 / 5) + 32
|
||||
|
||||
fields = (
|
||||
EmbedField(name=f"°{TEMP_LOOKUP.get(from_unit)}", value=f"{value:0.2f}"),
|
||||
EmbedField(name=f"°{TEMP_LOOKUP.get(to_unit)}", value=f"{converted:0.2f}"),
|
||||
)
|
||||
|
||||
embed = build_embed(
|
||||
title="Conversion",
|
||||
description=f"°{TEMP_LOOKUP.get(from_unit)} -> °{TEMP_LOOKUP.get(to_unit)}",
|
||||
fields=fields,
|
||||
)
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, components=components)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="currency", sub_cmd_description="Convert currency based on current rates")
|
||||
@slash_option(name="value", description="Value of starting currency", required=True, opt_type=OptionTypes.NUMBER)
|
||||
@slash_option(
|
||||
name="from_currency",
|
||||
description="Currency to convert from",
|
||||
required=True,
|
||||
opt_type=OptionTypes.STRING,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_currency",
|
||||
description="Currency to convert to",
|
||||
required=True,
|
||||
opt_type=OptionTypes.STRING,
|
||||
autocomplete=True,
|
||||
)
|
||||
async def _calc_convert_currency(
|
||||
self, ctx: InteractionContext, value: int, from_currency: str, to_currency: str
|
||||
) -> None:
|
||||
if from_currency == to_currency:
|
||||
conv = value
|
||||
else:
|
||||
rate = await self._get_currency_conversion(from_currency, to_currency)
|
||||
conv = value * rate
|
||||
|
||||
fields = (
|
||||
EmbedField(name=from_currency, value=f"{value:0.2f}"),
|
||||
EmbedField(name=to_currency, value=f"{conv:0.2f}"),
|
||||
)
|
||||
|
||||
embed = build_embed(title="Conversion", description=f"{from_currency} -> {to_currency}", fields=fields)
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, components=components)
|
||||
|
||||
async def _convert(self, ctx: InteractionContext, from_: str, to: str, value: int) -> Embed:
|
||||
*_, which = ctx.invoked_name.split(" ")
|
||||
which = getattr(units, which.capitalize(), None)
|
||||
ratio = which.get_rate(from_, to)
|
||||
converted = value / ratio
|
||||
fields = (EmbedField(name=from_, value=f"{value:0.2f}"), EmbedField(name=to, value=f"{converted:0.2f}"))
|
||||
embed = build_embed(title="Conversion", description=f"{from_} -> {to}", fields=fields)
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, components=components)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="angle", sub_cmd_description="Convert angles")
|
||||
@slash_option(name="value", description="Angle to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_angle(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="area", sub_cmd_description="Convert areas")
|
||||
@slash_option(name="value", description="Area to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_area(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="data", sub_cmd_description="Convert data sizes")
|
||||
@slash_option(name="value", description="Data size to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_data(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="energy", sub_cmd_description="Convert energy")
|
||||
@slash_option(name="value", description="Energy to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_energy(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="length", sub_cmd_description="Convert lengths")
|
||||
@slash_option(name="value", description="Length to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_length(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="power", sub_cmd_description="Convert powers")
|
||||
@slash_option(name="value", description="Power to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_power(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="pressure", sub_cmd_description="Convert pressures")
|
||||
@slash_option(name="value", description="Pressure to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_pressure(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="speed", sub_cmd_description="Convert speeds")
|
||||
@slash_option(name="value", description="Speed to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_speed(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="time", sub_cmd_description="Convert times")
|
||||
@slash_option(name="value", description="Time to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_time(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="volume", sub_cmd_description="Convert volumes")
|
||||
@slash_option(name="value", description="Volume to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_volume(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
@convert.subcommand(sub_cmd_name="weight", sub_cmd_description="Convert weights")
|
||||
@slash_option(name="value", description="Weight to convert", opt_type=OptionTypes.NUMBER, required=True)
|
||||
@slash_option(
|
||||
name="from_unit",
|
||||
description="Units to convert from",
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
autocomplete=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="to_unit", description="Units to convert to", opt_type=OptionTypes.STRING, required=True, autocomplete=True
|
||||
)
|
||||
async def _calc_convert_weight(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None:
|
||||
await self._convert(ctx, from_unit, to_unit, value)
|
||||
|
||||
def _unit_autocomplete(self, which: units.Converter, unit: str) -> list[dict[str, str]]:
|
||||
options = list(which.CONVERSIONS.keys())
|
||||
results = process.extract(unit, options, limit=25)
|
||||
if any([r[1] > 0 for r in results]):
|
||||
return [{"name": r[0], "value": r[0]} for r in results if r[1] > 50]
|
||||
return [{"name": r[0], "value": r[0]} for r in results]
|
||||
|
||||
@_calc_convert_angle.autocomplete("from_unit")
|
||||
@_calc_convert_area.autocomplete("from_unit")
|
||||
@_calc_convert_data.autocomplete("from_unit")
|
||||
@_calc_convert_energy.autocomplete("from_unit")
|
||||
@_calc_convert_length.autocomplete("from_unit")
|
||||
@_calc_convert_power.autocomplete("from_unit")
|
||||
@_calc_convert_pressure.autocomplete("from_unit")
|
||||
@_calc_convert_speed.autocomplete("from_unit")
|
||||
@_calc_convert_time.autocomplete("from_unit")
|
||||
@_calc_convert_volume.autocomplete("from_unit")
|
||||
@_calc_convert_weight.autocomplete("from_unit")
|
||||
async def _autocomplete_from_unit(
|
||||
self, ctx: AutocompleteContext, from_unit: str, to_unit: str = None, value: int = 0
|
||||
) -> None:
|
||||
*_, which = ctx.invoked_name.split(" ")
|
||||
which = getattr(units, which.capitalize(), None)
|
||||
await ctx.send(choices=self._unit_autocomplete(which, from_unit))
|
||||
|
||||
@_calc_convert_angle.autocomplete("to_unit")
|
||||
@_calc_convert_area.autocomplete("to_unit")
|
||||
@_calc_convert_data.autocomplete("to_unit")
|
||||
@_calc_convert_energy.autocomplete("to_unit")
|
||||
@_calc_convert_length.autocomplete("to_unit")
|
||||
@_calc_convert_power.autocomplete("to_unit")
|
||||
@_calc_convert_pressure.autocomplete("to_unit")
|
||||
@_calc_convert_speed.autocomplete("to_unit")
|
||||
@_calc_convert_time.autocomplete("to_unit")
|
||||
@_calc_convert_volume.autocomplete("to_unit")
|
||||
@_calc_convert_weight.autocomplete("to_unit")
|
||||
async def _autocomplete_to_unit(
|
||||
self, ctx: AutocompleteContext, from_unit: str, to_unit: str = None, value: int = 0
|
||||
) -> None:
|
||||
*_, which = ctx.invoked_name.split(" ")
|
||||
which = getattr(units, which.capitalize(), None)
|
||||
await ctx.send(choices=self._unit_autocomplete(which, to_unit))
|
||||
|
||||
def _currency_autocomplete(self, currency: str) -> list[dict[str, str]]:
|
||||
results = process.extract(currency, CURRENCIES, limit=25)
|
||||
if any([r[1] > 0 for r in results]):
|
||||
return [{"name": r[0], "value": r[0]} for r in results if r[1] > 50]
|
||||
return [{"name": r[0], "value": r[0]} for r in results]
|
||||
|
||||
@_calc_convert_currency.autocomplete("from_currency")
|
||||
async def _autocomplete_from_currency(
|
||||
self, ctx: AutocompleteContext, from_currency: str = None, to_currency: str = None, value: int = 0
|
||||
) -> None:
|
||||
await ctx.send(choices=self._currency_autocomplete(from_currency))
|
||||
|
||||
@_calc_convert_currency.autocomplete("to_currency")
|
||||
async def _autocomplete_to_currency(
|
||||
self, ctx: AutocompleteContext, from_currency: str = None, to_currency: str = None, value: int = 0
|
||||
) -> None:
|
||||
await ctx.send(choices=self._currency_autocomplete(to_currency))
|
||||
|
||||
|
||||
def setup(bot: Client) -> None:
|
||||
"""Add CalcCog to JARVIS"""
|
||||
CalcCog(bot)
|
|
@ -3,6 +3,7 @@ import logging
|
|||
import re
|
||||
import secrets
|
||||
import string
|
||||
import urllib.parse
|
||||
from datetime import datetime, timezone
|
||||
from io import BytesIO
|
||||
|
||||
|
@ -57,7 +58,9 @@ class UtilCog(Extension):
|
|||
if ctx.author.id == 264072583987593217:
|
||||
await ctx.send("Oh fuck no, go fuck yourself")
|
||||
elif ctx.author.id == 840031256201003008:
|
||||
await ctx.send("https://tenor.com/view/fluffy-gabriel-iglesias-you-need-jesus-thats-what-you-need-pointing-up-gif-16385108")
|
||||
await ctx.send(
|
||||
"https://tenor.com/view/fluffy-gabriel-iglesias-you-need-jesus-thats-what-you-need-pointing-up-gif-16385108"
|
||||
)
|
||||
elif ctx.author.id == 215564028615852033:
|
||||
await ctx.send("As flattered as I am, I'm not into bestiality")
|
||||
else:
|
||||
|
@ -83,26 +86,14 @@ class UtilCog(Extension):
|
|||
inline=True,
|
||||
)
|
||||
)
|
||||
fields.append(
|
||||
EmbedField(name="NAFF", value=f"[{const.__version__}](https://naff.info)", inline=True)
|
||||
)
|
||||
repo_url = (
|
||||
f"https://git.zevaryx.com/stark-industries/jarvis/jarvis-bot/-/tree/{get_repo_hash()}"
|
||||
)
|
||||
fields.append(
|
||||
EmbedField(name="Git Hash", value=f"[{get_repo_hash()[:7]}]({repo_url})", inline=True)
|
||||
)
|
||||
fields.append(EmbedField(name="NAFF", value=f"[{const.__version__}](https://naff.info)", inline=True))
|
||||
repo_url = f"https://git.zevaryx.com/stark-industries/jarvis/jarvis-bot/-/tree/{get_repo_hash()}"
|
||||
fields.append(EmbedField(name="Git Hash", value=f"[{get_repo_hash()[:7]}]({repo_url})", inline=True))
|
||||
fields.append(EmbedField(name="Online Since", value=f"<t:{uptime}:F>", inline=False))
|
||||
num_domains = len(self.bot.phishing_domains)
|
||||
fields.append(
|
||||
EmbedField(
|
||||
name="Phishing Protection", value=f"Detecting {num_domains} phishing domains"
|
||||
)
|
||||
)
|
||||
fields.append(EmbedField(name="Phishing Protection", value=f"Detecting {num_domains} phishing domains"))
|
||||
embed = build_embed(title=title, description=desc, fields=fields, color=color)
|
||||
components = Button(
|
||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
||||
)
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, components=components)
|
||||
|
||||
@bot.subcommand(
|
||||
|
@ -115,9 +106,7 @@ class UtilCog(Extension):
|
|||
JARVIS_LOGO.save(image_bytes, "PNG")
|
||||
image_bytes.seek(0)
|
||||
logo = File(image_bytes, file_name="logo.png")
|
||||
components = Button(
|
||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
||||
)
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(file=logo, components=components)
|
||||
|
||||
rc = SlashCommand(name="rc", description="Robot Camo emoji commands")
|
||||
|
@ -163,9 +152,7 @@ class UtilCog(Extension):
|
|||
embed = build_embed(title="Avatar", description="", fields=[], color="#00FFEE")
|
||||
embed.set_image(url=avatar)
|
||||
embed.set_author(name=f"{user.username}#{user.discriminator}", icon_url=avatar)
|
||||
components = Button(
|
||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
||||
)
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, components=components)
|
||||
|
||||
@slash_command(
|
||||
|
@ -213,9 +200,7 @@ class UtilCog(Extension):
|
|||
im.save(image_bytes, "PNG")
|
||||
image_bytes.seek(0)
|
||||
color_show = File(image_bytes, file_name="color_show.png")
|
||||
components = Button(
|
||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
||||
)
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, file=color_show, components=components)
|
||||
|
||||
@slash_command(name="avatar", description="Get a user avatar")
|
||||
|
@ -281,11 +266,15 @@ class UtilCog(Extension):
|
|||
)
|
||||
embed.set_thumbnail(url=user.display_avatar.url)
|
||||
embed.set_footer(text=f"ID: {user.id}")
|
||||
components = Button(
|
||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
||||
)
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, components=components)
|
||||
|
||||
@slash_command(name="lmgtfy", description="Let me Google that for you")
|
||||
@slash_option(name="search", description="What to search", opt_type=OptionTypes.STRING, required=True)
|
||||
async def _lmgtfy(self, ctx: InteractionContext, search: str) -> None:
|
||||
url = "https://letmegooglethat.com/?q=" + urllib.parse.quote_plus(search)
|
||||
await ctx.send(url)
|
||||
|
||||
@slash_command(
|
||||
name="userinfo",
|
||||
description="Get user info",
|
||||
|
@ -338,9 +327,7 @@ class UtilCog(Extension):
|
|||
embed.set_author(name=guild.name, icon_url=guild.icon.url)
|
||||
embed.set_thumbnail(url=guild.icon.url)
|
||||
embed.set_footer(text=f"ID: {guild.id} | Server Created")
|
||||
components = Button(
|
||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
||||
)
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, components=components)
|
||||
|
||||
@slash_command(
|
||||
|
@ -389,9 +376,7 @@ class UtilCog(Extension):
|
|||
)
|
||||
|
||||
@slash_command(name="pigpen", description="Encode a string into pigpen")
|
||||
@slash_option(
|
||||
name="text", description="Text to encode", opt_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
@slash_option(name="text", description="Text to encode", opt_type=OptionTypes.STRING, required=True)
|
||||
async def _pigpen(self, ctx: InteractionContext, text: str) -> None:
|
||||
outp = "`"
|
||||
for c in text:
|
||||
|
@ -406,15 +391,9 @@ class UtilCog(Extension):
|
|||
outp += "`"
|
||||
await ctx.send(outp[:2000])
|
||||
|
||||
@slash_command(
|
||||
name="timestamp", description="Convert a datetime or timestamp into it's counterpart"
|
||||
)
|
||||
@slash_option(
|
||||
name="string", description="String to convert", opt_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="private", description="Respond quietly?", opt_type=OptionTypes.BOOLEAN, required=False
|
||||
)
|
||||
@slash_command(name="timestamp", description="Convert a datetime or timestamp into it's counterpart")
|
||||
@slash_option(name="string", description="String to convert", opt_type=OptionTypes.STRING, required=True)
|
||||
@slash_option(name="private", description="Respond quietly?", opt_type=OptionTypes.BOOLEAN, required=False)
|
||||
async def _timestamp(self, ctx: InteractionContext, string: str, private: bool = False) -> None:
|
||||
timestamp = parse(string)
|
||||
if not timestamp:
|
||||
|
@ -436,9 +415,7 @@ class UtilCog(Extension):
|
|||
EmbedField(name="ISO8601", value=timestamp.isoformat()),
|
||||
]
|
||||
embed = build_embed(title="Converted Time", description=f"`{string}`", fields=fields)
|
||||
components = Button(
|
||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
||||
)
|
||||
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||
await ctx.send(embeds=embed, ephemeral=private, components=components)
|
||||
|
||||
@bot.subcommand(sub_cmd_name="support", sub_cmd_description="Got issues?")
|
||||
|
@ -453,9 +430,7 @@ We'll help as best we can with whatever issues you encounter.
|
|||
"""
|
||||
)
|
||||
|
||||
@bot.subcommand(
|
||||
sub_cmd_name="privacy_terms", sub_cmd_description="View Privacy and Terms of Use"
|
||||
)
|
||||
@bot.subcommand(sub_cmd_name="privacy_terms", sub_cmd_description="View Privacy and Terms of Use")
|
||||
async def _privacy_terms(self, ctx: InteractionContext) -> None:
|
||||
await ctx.send(
|
||||
"""
|
||||
|
|
241
jarvis/data/units.py
Normal file
241
jarvis/data/units.py
Normal file
|
@ -0,0 +1,241 @@
|
|||
"""
|
||||
Unit Converter utilities.
|
||||
|
||||
Rates based on https://github.com/microsoft/calculator
|
||||
"""
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
|
||||
@dataclass
|
||||
class Converter:
|
||||
BASE: str = "sample"
|
||||
CONVERSIONS: dict[str, int] = field(default_factory=dict)
|
||||
|
||||
@classmethod
|
||||
def get_rate(cls, from_: str, to: str) -> int:
|
||||
"""
|
||||
Get the conversion rate
|
||||
|
||||
Args:
|
||||
from_: Convert from this
|
||||
to: Convert to this
|
||||
"""
|
||||
if from_ == cls.BASE:
|
||||
return cls.CONVERSIONS.get(to, None)
|
||||
else:
|
||||
from_rate = cls.CONVERSIONS.get(from_)
|
||||
to_rate = cls.CONVERSIONS.get(to)
|
||||
return (1 / from_rate) * to_rate
|
||||
|
||||
|
||||
class Angle(Converter):
|
||||
BASE = "degree"
|
||||
CONVERSIONS = {"degree": 1, "radian": 57.29577951308233, "gradian": 0.9}
|
||||
|
||||
|
||||
class Area(Converter):
|
||||
BASE = "square meter"
|
||||
CONVERSIONS = {
|
||||
"acre": 4046.8564224,
|
||||
"square meter": 1,
|
||||
"square foot": 0.09290304,
|
||||
"square yard": 0.83612736,
|
||||
"square millimeter": 0.000001,
|
||||
"square centimeter": 0.00001,
|
||||
"square inch": 0.00064516,
|
||||
"square mile": 2589988.110336,
|
||||
"square kilometer": 1000000,
|
||||
"hectare": 10000,
|
||||
"hand": 0.01251604,
|
||||
"paper": 0.06032246,
|
||||
"soccer field": 10869.66,
|
||||
"castle": 100000,
|
||||
"pyeong": 400 / 121,
|
||||
}
|
||||
|
||||
|
||||
class Data(Converter):
|
||||
BASE = "megabyte"
|
||||
CONVERSIONS = {
|
||||
"bit": 0.000000125,
|
||||
"byte": 0.000001,
|
||||
"kilobyte": 0.001,
|
||||
"megabyte": 1,
|
||||
"gigabyte": 1000,
|
||||
"terabyte": 1000000,
|
||||
"petabyte": 1000000000,
|
||||
"exabyte": 1000000000000,
|
||||
"zetabyte": 1000000000000000,
|
||||
"yottabyte": 1000000000000000000,
|
||||
"kilobit": 0.000125,
|
||||
"megabit": 0.0125,
|
||||
"gigabit": 125,
|
||||
"terabit": 125000,
|
||||
"petabit": 125000000,
|
||||
"exabit": 125000000000,
|
||||
"zetabit": 125000000000000,
|
||||
"yottabit": 125000000000000000,
|
||||
"gibibit": 134.217728,
|
||||
"gibibyte": 1073.731824,
|
||||
"kibibit": 0.000128,
|
||||
"kibibyte": 0.001024,
|
||||
"mebibit": 0.131072,
|
||||
"mebibyte": 1.048576,
|
||||
"pebibit": 140737488.355328,
|
||||
"pebibyte": 1125899906.842624,
|
||||
"tebibit": 137438.953472,
|
||||
"tebibyte": 1099511.627776,
|
||||
"exbibit": 144115188075.855872,
|
||||
"exbibyte": 1152921504606.846976,
|
||||
"zebibit": 147573952589676.412928,
|
||||
"zebibyte": 1180591620717411.303424,
|
||||
"yobibit": 151115727451828646.838272,
|
||||
"yobibyte": 1208925819614629174.706176,
|
||||
"floppy disk": 1.474560,
|
||||
"cd": 734.003200,
|
||||
"dvd": 5046.586573,
|
||||
}
|
||||
|
||||
|
||||
class Energy(Converter):
|
||||
BASE = "joule"
|
||||
CONVERSIONS = {
|
||||
"calorie": 4.184,
|
||||
"kilocalorie": 4184,
|
||||
"british thermal unit": 1055.056,
|
||||
"kilojoule": 1000,
|
||||
"electron volt": 0.0000000000000000001602176565,
|
||||
"joule": 1,
|
||||
"foot pound": 1.3558179483314,
|
||||
"battery": 9000,
|
||||
"banana": 439614,
|
||||
"slice of cake": 1046700,
|
||||
}
|
||||
|
||||
|
||||
class Length(Converter):
|
||||
BASE = "meter"
|
||||
CONVERSIONS = {
|
||||
"inch": 0.0254,
|
||||
"foot": 0.3048,
|
||||
"yard": 0.9144,
|
||||
"mile": 1609.344,
|
||||
"micron": 0.000001,
|
||||
"millimeter": 0.001,
|
||||
"nanometer": 0.000000001,
|
||||
"centimeter": 0.01,
|
||||
"meter": 1,
|
||||
"kilometer": 1000,
|
||||
"nautical mile": 1852,
|
||||
"paperclip": 0.035052,
|
||||
"hand": 0.18669,
|
||||
"jumbo jet": 76,
|
||||
}
|
||||
|
||||
|
||||
class Power(Converter):
|
||||
BASE = "watt"
|
||||
CONVERSIONS = {
|
||||
"british thermal unit per minute": 17.58426666666667,
|
||||
"foot pound per minute": 0.0225969658055233,
|
||||
"watt": 1,
|
||||
"kilowatt": 1000,
|
||||
"horsepower": 745.69987158227022,
|
||||
"lightbulb": 60,
|
||||
"horse": 745.7,
|
||||
"train engine": 2982799.486329081,
|
||||
}
|
||||
|
||||
|
||||
class Pressure(Converter):
|
||||
BASE = "atmosphere"
|
||||
CONVERSIONS = {
|
||||
"atmosphere": 1,
|
||||
"bar": 0.9869232667160128,
|
||||
"kilopascal": 0.0098692326671601,
|
||||
"millimeter of mercury": 0.0013155687145324,
|
||||
"pascal": 9.869232667160128e-6,
|
||||
"psi": 0.068045961016531,
|
||||
}
|
||||
|
||||
|
||||
class Speed(Converter):
|
||||
BASE = "centimeters per second"
|
||||
CONVERSIONS = {
|
||||
"centimeters per second": 1,
|
||||
"feet per second": 30.48,
|
||||
"kilometers per hour": 27.777777777777777777778,
|
||||
"knot": 51.44,
|
||||
"mach": 34040,
|
||||
"meters per second": 100,
|
||||
"miles per hour": 44.7,
|
||||
"turtle": 8.94,
|
||||
"horse": 2011.5,
|
||||
"jet": 24585,
|
||||
}
|
||||
|
||||
|
||||
class Time(Converter):
|
||||
BASE = "second"
|
||||
CONVERSIONS = {
|
||||
"day": 86400,
|
||||
"second": 1,
|
||||
"week": 604800,
|
||||
"millisecond": 0.001,
|
||||
"microsecond": 0.000001,
|
||||
"minute": 60,
|
||||
"hour": 3600,
|
||||
}
|
||||
|
||||
|
||||
class Volume(Converter):
|
||||
BASE = "millileter"
|
||||
CONVERSIONS = {
|
||||
"cup (US)": 236.588237,
|
||||
"pint (US)": 473.176473,
|
||||
"pint (UK)": 568.26125,
|
||||
"quart (US)": 946.352946,
|
||||
"quart (UK)": 1136.5225,
|
||||
"gallon (US)": 3785.411784,
|
||||
"gallon (UK)": 4546.09,
|
||||
"liter": 1000,
|
||||
"teaspoon (US)": 4.92892159375,
|
||||
"tablespoon (US)": 14.78676478125,
|
||||
"cubic centimeter": 1,
|
||||
"cubic yard": 764554.857984,
|
||||
"cubic meter": 1000000,
|
||||
"millimeter": 1,
|
||||
"cubic inch": 16.387064,
|
||||
"cubic foot": 28316.846592,
|
||||
"fluid ounce (US)": 29.5735295625,
|
||||
"fluid ounce (UK)": 28.4130625,
|
||||
"teaspoon (UK)": 5.91938802083333333333,
|
||||
"tablespoon (UK)": 17.7581640625,
|
||||
"coffee cup": 236.588237,
|
||||
"bathtub": 378541.2,
|
||||
"swimming pool": 3750000000,
|
||||
}
|
||||
|
||||
|
||||
class Weight(Converter):
|
||||
BASE = "kilogram"
|
||||
CONVERSIONS = {
|
||||
"kilogram": 1,
|
||||
"hectogram": 0.1,
|
||||
"decagram": 0.01,
|
||||
"gram": 0.001,
|
||||
"pound": 0.45359237,
|
||||
"ounce": 0.028349523125,
|
||||
"milligram": 0.000001,
|
||||
"centigram": 0.00001,
|
||||
"decigram": 0.0001,
|
||||
"long ton": 1016.0469088,
|
||||
"tonne": 1000,
|
||||
"stone": 6.35029318,
|
||||
"carat": 0.0002,
|
||||
"short ton": 907.18474,
|
||||
"snowflake": 0.000002,
|
||||
"soccer ball": 0.4325,
|
||||
"elephant": 4000,
|
||||
"whale": 90000,
|
||||
}
|
145
poetry.lock
generated
145
poetry.lock
generated
|
@ -38,7 +38,7 @@ multidict = ">=4.5,<7.0"
|
|||
yarl = ">=1.0,<2.0"
|
||||
|
||||
[package.extras]
|
||||
speedups = ["aiodns", "brotli", "cchardet"]
|
||||
speedups = ["Brotli", "aiodns", "cchardet"]
|
||||
|
||||
[[package]]
|
||||
name = "aioredis"
|
||||
|
@ -154,7 +154,7 @@ update-checker = ">=0.18"
|
|||
|
||||
[package.extras]
|
||||
ci = ["coveralls"]
|
||||
dev = ["packaging", "pre-commit", "sphinx", "sphinx-rtd-theme", "sphinxcontrib-trio", "asynctest (>=0.13.0)", "mock (>=0.8)", "pytest (>=2.7.3)", "pytest-asyncio", "pytest-vcr", "testfixtures (>4.13.2,<7)", "vcrpy (==4.1.1)"]
|
||||
dev = ["asynctest (>=0.13.0)", "mock (>=0.8)", "packaging", "pre-commit", "pytest (>=2.7.3)", "pytest-asyncio", "pytest-vcr", "sphinx", "sphinx-rtd-theme", "sphinxcontrib-trio", "testfixtures (>4.13.2,<7)", "vcrpy (==4.1.1)"]
|
||||
lint = ["pre-commit", "sphinx", "sphinx-rtd-theme", "sphinxcontrib-trio"]
|
||||
readthedocs = ["sphinx", "sphinx-rtd-theme", "sphinxcontrib-trio"]
|
||||
test = ["asynctest (>=0.13.0)", "mock (>=0.8)", "pytest (>=2.7.3)", "pytest-asyncio", "pytest-vcr", "testfixtures (>4.13.2,<7)", "vcrpy (==4.1.1)"]
|
||||
|
@ -172,10 +172,10 @@ aiohttp = "*"
|
|||
yarl = "*"
|
||||
|
||||
[package.extras]
|
||||
test = ["vcrpy (==4.0.2)", "testfixtures (>4.13.2,<7)", "pytest-vcr", "pytest", "mock (>=0.8)", "asynctest (>=0.13.0)"]
|
||||
lint = ["pydocstyle", "pre-commit", "flynt", "flake8", "black"]
|
||||
dev = ["vcrpy (==4.0.2)", "testfixtures (>4.13.2,<7)", "pytest-vcr", "pytest", "mock (>=0.8)", "asynctest (>=0.13.0)", "pydocstyle", "pre-commit", "flynt", "flake8", "black"]
|
||||
ci = ["coveralls"]
|
||||
dev = ["asynctest (>=0.13.0)", "black", "flake8", "flynt", "mock (>=0.8)", "pre-commit", "pydocstyle", "pytest", "pytest-vcr", "testfixtures (>4.13.2,<7)", "vcrpy (==4.0.2)"]
|
||||
lint = ["black", "flake8", "flynt", "pre-commit", "pydocstyle"]
|
||||
test = ["asynctest (>=0.13.0)", "mock (>=0.8)", "pytest", "pytest-vcr", "testfixtures (>4.13.2,<7)", "vcrpy (==4.0.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
|
@ -186,10 +186,10 @@ optional = false
|
|||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||
|
||||
[package.extras]
|
||||
dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"]
|
||||
docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
|
||||
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
|
||||
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
|
||||
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"]
|
||||
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
|
||||
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"]
|
||||
tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"]
|
||||
|
||||
[[package]]
|
||||
name = "beautifulsoup4"
|
||||
|
@ -251,6 +251,21 @@ python-versions = ">=3.5.*, <4"
|
|||
[package.extras]
|
||||
develop = ["aiomisc", "pytest", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
name = "calculator"
|
||||
version = "1.0.0"
|
||||
description = "A simple calculator"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
develop = false
|
||||
|
||||
[package.source]
|
||||
type = "git"
|
||||
url = "https://git.zevaryx.com/zevaryx/calculator.git"
|
||||
reference = "HEAD"
|
||||
resolved_reference = "b317d35788c6a06f2b496844d5fdf4e3414453e6"
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2021.10.8"
|
||||
|
@ -268,7 +283,7 @@ optional = false
|
|||
python-versions = ">=3.5.0"
|
||||
|
||||
[package.extras]
|
||||
unicode_backport = ["unicodedata2"]
|
||||
unicode-backport = ["unicodedata2"]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
|
@ -306,7 +321,7 @@ optional = false
|
|||
python-versions = "*"
|
||||
|
||||
[package.extras]
|
||||
test = ["hypothesis (==3.55.3)", "flake8 (==3.7.8)"]
|
||||
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "dateparser"
|
||||
|
@ -323,9 +338,9 @@ regex = "<2019.02.19 || >2019.02.19,<2021.8.27 || >2021.8.27,<2022.3.15"
|
|||
tzlocal = "*"
|
||||
|
||||
[package.extras]
|
||||
langdetect = ["langdetect"]
|
||||
calendars = ["convertdate", "convertdate", "hijri-converter"]
|
||||
fasttext = ["fasttext"]
|
||||
calendars = ["convertdate", "hijri-converter", "convertdate"]
|
||||
langdetect = ["langdetect"]
|
||||
|
||||
[[package]]
|
||||
name = "discord-typings"
|
||||
|
@ -412,13 +427,13 @@ python-versions = ">=3.7"
|
|||
zipp = ">=0.5"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
|
||||
docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"]
|
||||
perf = ["ipython"]
|
||||
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"]
|
||||
testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "jarvis-core"
|
||||
version = "0.13.1"
|
||||
version = "0.16.0"
|
||||
description = "JARVIS core"
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -430,6 +445,7 @@ aiohttp = "^3.8.1"
|
|||
motor = "^2.5.1"
|
||||
nanoid = "^2.0.0"
|
||||
orjson = "^3.6.6"
|
||||
python-dotenv = "^0.21.0"
|
||||
pytz = "^2022.1"
|
||||
PyYAML = "^6.0"
|
||||
rich = "^12.3.0"
|
||||
|
@ -439,7 +455,7 @@ umongo = "^3.1.0"
|
|||
type = "git"
|
||||
url = "https://git.zevaryx.com/stark-industries/jarvis/jarvis-core.git"
|
||||
reference = "main"
|
||||
resolved_reference = "739d07885e161d66adbf946805e70b88360ddce3"
|
||||
resolved_reference = "1eb9455d800bc33fd45142d8ffeea56a99dad813"
|
||||
|
||||
[[package]]
|
||||
name = "jinxed"
|
||||
|
@ -467,7 +483,7 @@ ovld = ">=0.3.1,<0.4.0"
|
|||
watchdog = ">=1.0.2"
|
||||
|
||||
[package.extras]
|
||||
develoop = ["hrepr (>=0.4.0,<0.5.0)", "rich (>=10.13.0,<11.0.0)", "giving (>=0.3.6,<0.4.0)"]
|
||||
develoop = ["giving (>=0.3.6,<0.4.0)", "hrepr (>=0.4.0,<0.5.0)", "rich (>=10.13.0,<11.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "marshmallow"
|
||||
|
@ -481,9 +497,9 @@ python-versions = ">=3.7"
|
|||
packaging = ">=17.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["pytest", "pytz", "simplejson", "mypy (==0.960)", "flake8 (==4.0.1)", "flake8-bugbear (==22.4.25)", "pre-commit (>=2.4,<3.0)", "tox"]
|
||||
docs = ["sphinx (==4.5.0)", "sphinx-issues (==3.0.1)", "alabaster (==0.7.12)", "sphinx-version-warning (==1.1.2)", "autodocsumm (==0.2.8)"]
|
||||
lint = ["mypy (==0.960)", "flake8 (==4.0.1)", "flake8-bugbear (==22.4.25)", "pre-commit (>=2.4,<3.0)"]
|
||||
dev = ["flake8 (==4.0.1)", "flake8-bugbear (==22.4.25)", "mypy (==0.960)", "pre-commit (>=2.4,<3.0)", "pytest", "pytz", "simplejson", "tox"]
|
||||
docs = ["alabaster (==0.7.12)", "autodocsumm (==0.2.8)", "sphinx (==4.5.0)", "sphinx-issues (==3.0.1)", "sphinx-version-warning (==1.1.2)"]
|
||||
lint = ["flake8 (==4.0.1)", "flake8-bugbear (==22.4.25)", "mypy (==0.960)", "pre-commit (>=2.4,<3.0)"]
|
||||
tests = ["pytest", "pytz", "simplejson"]
|
||||
|
||||
[[package]]
|
||||
|
@ -529,7 +545,7 @@ python-versions = "*"
|
|||
|
||||
[[package]]
|
||||
name = "naff"
|
||||
version = "1.11.1"
|
||||
version = "1.12.0"
|
||||
description = "Not another freaking fork"
|
||||
category = "main"
|
||||
optional = false
|
||||
|
@ -542,11 +558,11 @@ discord-typings = ">=0.5.1"
|
|||
tomli = "*"
|
||||
|
||||
[package.extras]
|
||||
all = ["PyNaCl (>=1.5.0,<1.6)", "aiodns", "orjson", "brotli", "sentry-sdk"]
|
||||
docs = ["PyNaCl (>=1.5.0,<1.6)", "aiodns", "orjson", "brotli", "sentry-sdk", "mkdocs-autorefs", "mkdocs-awesome-pages-plugin", "mkdocs-material", "mkdocstrings-python", "mkdocs-minify-plugin", "mkdocs-git-committers-plugin-2", "mkdocs-git-revision-date-localized-plugin"]
|
||||
all = ["Brotli", "PyNaCl (>=1.5.0,<1.6)", "aiodns", "orjson", "sentry-sdk"]
|
||||
docs = ["Brotli", "PyNaCl (>=1.5.0,<1.6)", "aiodns", "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"]
|
||||
sentry = ["sentry-sdk"]
|
||||
speedup = ["aiodns", "orjson", "brotli"]
|
||||
tests = ["pytest", "pytest-recording", "pytest-asyncio", "pytest-cov", "typeguard"]
|
||||
speedup = ["Brotli", "aiodns", "orjson"]
|
||||
tests = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-recording", "python-dotenv", "typeguard"]
|
||||
voice = ["PyNaCl (>=1.5.0,<1.6)"]
|
||||
|
||||
[[package]]
|
||||
|
@ -567,7 +583,7 @@ uvicorn = "^0.18.2"
|
|||
type = "git"
|
||||
url = "https://github.com/artem30801/nafftrack.git"
|
||||
reference = "master"
|
||||
resolved_reference = "eae6ffd93a1a7854347eb0e147b894bf307c0003"
|
||||
resolved_reference = "ac5ece577f67faad01602d1b945e08c72f43d093"
|
||||
|
||||
[[package]]
|
||||
name = "nanoid"
|
||||
|
@ -661,11 +677,11 @@ python-versions = ">=3.10"
|
|||
aiohttp = {version = "3.8.1", markers = "python_version >= \"3.6\""}
|
||||
aiosignal = {version = "1.2.0", markers = "python_version >= \"3.6\""}
|
||||
async-timeout = {version = "4.0.2", markers = "python_version >= \"3.6\""}
|
||||
attrs = {version = "21.4.0", markers = "python_version >= \"3.6\" and python_full_version < \"3.0.0\" or python_full_version >= \"3.5.0\" and python_version >= \"3.6\""}
|
||||
attrs = {version = "21.4.0", markers = "python_version >= \"3.6\""}
|
||||
certifi = {version = "2021.10.8", markers = "python_version >= \"2.7\" and python_full_version < \"3.0.0\" or python_full_version >= \"3.6.0\""}
|
||||
charset-normalizer = {version = "2.0.12", markers = "python_full_version >= \"3.6.0\" and python_version >= \"3.6\""}
|
||||
charset-normalizer = {version = "2.0.12", markers = "python_version >= \"3.6\""}
|
||||
frozenlist = {version = "1.3.0", markers = "python_version >= \"3.7\""}
|
||||
idna = {version = "3.3", markers = "python_version >= \"3.6\" and python_full_version < \"3.0.0\" or python_full_version >= \"3.6.0\" and python_version >= \"3.6\""}
|
||||
idna = {version = "3.3", markers = "python_version >= \"3.6\""}
|
||||
multidict = {version = "6.0.2", markers = "python_version >= \"3.7\""}
|
||||
pycryptodome = {version = "3.14.1", markers = "python_version >= \"2.7\" and python_full_version < \"3.0.0\" or python_full_version >= \"3.5.0\""}
|
||||
requests = {version = "2.27.1", markers = "python_version >= \"2.7\" and python_full_version < \"3.0.0\" or python_full_version >= \"3.6.0\""}
|
||||
|
@ -701,8 +717,8 @@ optional = false
|
|||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"]
|
||||
test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"]
|
||||
docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"]
|
||||
test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
|
||||
|
||||
[[package]]
|
||||
name = "prometheus-client"
|
||||
|
@ -732,7 +748,7 @@ optional = false
|
|||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
|
||||
[package.extras]
|
||||
test = ["ipaddress", "mock", "enum34", "pywin32", "wmi"]
|
||||
test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"]
|
||||
|
||||
[[package]]
|
||||
name = "pycryptodome"
|
||||
|
@ -770,7 +786,7 @@ python-versions = "*"
|
|||
aws = ["pymongo-auth-aws (<2.0.0)"]
|
||||
encryption = ["pymongocrypt (>=1.1.0,<2.0.0)"]
|
||||
gssapi = ["pykerberos"]
|
||||
ocsp = ["pyopenssl (>=17.2.0)", "requests (<3.0.0)", "service-identity (>=18.1.0)", "certifi"]
|
||||
ocsp = ["certifi", "pyopenssl (>=17.2.0)", "requests (<3.0.0)", "service-identity (>=18.1.0)"]
|
||||
snappy = ["python-snappy"]
|
||||
srv = ["dnspython (>=1.16.0,<1.17.0)"]
|
||||
tls = ["ipaddress"]
|
||||
|
@ -815,6 +831,17 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
|||
[package.dependencies]
|
||||
six = ">=1.5"
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "0.21.0"
|
||||
description = "Read key-value pairs from a .env file and set them as environment variables"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
cli = ["click (>=5.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "python-gitlab"
|
||||
version = "3.5.0"
|
||||
|
@ -839,6 +866,9 @@ category = "main"
|
|||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
setuptools = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2022.1"
|
||||
|
@ -890,7 +920,7 @@ urllib3 = ">=1.21.1,<1.27"
|
|||
|
||||
[package.extras]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
|
||||
use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"]
|
||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<5)"]
|
||||
|
||||
[[package]]
|
||||
name = "requests-oauthlib"
|
||||
|
@ -951,7 +981,20 @@ six = ">=1.13"
|
|||
websocket-client = ">=0.56,<0.58 || >0.58,<0.59 || >0.59,<1.0 || >1.0,<1.1 || >1.1"
|
||||
|
||||
[package.extras]
|
||||
ssl_backport = ["backports.ssl", "backports.ssl-match-hostname", "pyopenssl"]
|
||||
ssl-backport = ["PyOpenSSL", "backports.ssl", "backports.ssl-match-hostname"]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "65.6.3"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
||||
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
||||
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
|
@ -1065,7 +1108,7 @@ tzdata = {version = "*", markers = "platform_system == \"Windows\""}
|
|||
|
||||
[package.extras]
|
||||
devenv = ["black", "pyroma", "pytest-cov", "zest.releaser"]
|
||||
test = ["pytest-mock (>=3.3)", "pytest (>=4.3)"]
|
||||
test = ["pytest (>=4.3)", "pytest-mock (>=3.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "ulid-py"
|
||||
|
@ -1118,7 +1161,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
|
|||
|
||||
[package.extras]
|
||||
brotli = ["brotlipy (>=0.6.0)"]
|
||||
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
|
||||
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)"]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
|
||||
[[package]]
|
||||
|
@ -1134,7 +1177,7 @@ click = ">=7.0"
|
|||
h11 = ">=0.8"
|
||||
|
||||
[package.extras]
|
||||
standard = ["websockets (>=10.0)", "httptools (>=0.4.0)", "watchfiles (>=0.13)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"]
|
||||
standard = ["PyYAML (>=5.1)", "colorama (>=0.4)", "httptools (>=0.4.0)", "python-dotenv (>=0.13)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "watchdog"
|
||||
|
@ -1164,9 +1207,9 @@ optional = false
|
|||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"]
|
||||
optional = ["python-socks", "wsaccel"]
|
||||
test = ["websockets"]
|
||||
optional = ["wsaccel", "python-socks"]
|
||||
docs = ["sphinx-rtd-theme (>=0.5)", "Sphinx (>=3.4)"]
|
||||
|
||||
[[package]]
|
||||
name = "websockets"
|
||||
|
@ -1197,13 +1240,13 @@ optional = false
|
|||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
|
||||
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
|
||||
docs = ["jaraco.packaging (>=9)", "rst.linker (>=1.9)", "sphinx"]
|
||||
testing = ["func-timeout", "jaraco.itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "e95b3b3bed46990e5d3bd4f8662fd888dbf35a9272f09a18192c78d6c60b6f83"
|
||||
content-hash = "57bd23e6265cf41781732790f7aea43c6985f3711ecd9977f8058b81b2689460"
|
||||
|
||||
[metadata.files]
|
||||
aiofile = [
|
||||
|
@ -1386,6 +1429,7 @@ caio = [
|
|||
{file = "caio-0.9.5-py3-none-any.whl", hash = "sha256:3c74d84dff2bec5f93685cf2f32eb22e4cc5663434a9be5f4a759247229b69b3"},
|
||||
{file = "caio-0.9.5.tar.gz", hash = "sha256:167d9342a807bae441b2e88f9ecb62da2f236b319939a8679f68f510a0194c40"},
|
||||
]
|
||||
calculator = []
|
||||
certifi = [
|
||||
{file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"},
|
||||
{file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"},
|
||||
|
@ -1594,8 +1638,8 @@ mypy-extensions = [
|
|||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
]
|
||||
naff = [
|
||||
{file = "naff-1.11.1-py3-none-any.whl", hash = "sha256:ea9192556ad162e9990f41b1d4c315255e4354580614bdedc6ac4228c3339004"},
|
||||
{file = "naff-1.11.1.tar.gz", hash = "sha256:f1933c218b3a3ac93866245f8d2b034cc8d2b4b4ff48b76cacd37a0c2507abe2"},
|
||||
{file = "naff-1.12.0-py3-none-any.whl", hash = "sha256:37b595f0c9fed1672b5fe6f511374da4a33e818ae8451c710d745231d7cbd941"},
|
||||
{file = "naff-1.12.0.tar.gz", hash = "sha256:21d1ce708e1a7cfe08ae59e7d79576cff103a027424b032c9ac8c33dbe2d0a5d"},
|
||||
]
|
||||
nafftrack = []
|
||||
nanoid = [
|
||||
|
@ -1949,7 +1993,6 @@ pymongo = [
|
|||
{file = "pymongo-3.12.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0be605bfb8461384a4cb81e80f51eb5ca1b89851f2d0e69a75458c788a7263a4"},
|
||||
{file = "pymongo-3.12.3-cp39-cp39-win32.whl", hash = "sha256:2157d68f85c28688e8b723bbe70c8013e0aba5570e08c48b3562f74d33fc05c4"},
|
||||
{file = "pymongo-3.12.3-cp39-cp39-win_amd64.whl", hash = "sha256:dfa217bf8cf3ff6b30c8e6a89014e0c0e7b50941af787b970060ae5ba04a4ce5"},
|
||||
{file = "pymongo-3.12.3-py2.7-macosx-10.14-intel.egg", hash = "sha256:d81299f63dc33cc172c26faf59cc54dd795fc6dd5821a7676cca112a5ee8bbd6"},
|
||||
{file = "pymongo-3.12.3.tar.gz", hash = "sha256:0a89cadc0062a5e53664dde043f6c097172b8c1c5f0094490095282ff9995a5f"},
|
||||
]
|
||||
pyparsing = [
|
||||
|
@ -1964,6 +2007,10 @@ python-dateutil = [
|
|||
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
|
||||
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
|
||||
]
|
||||
python-dotenv = [
|
||||
{file = "python-dotenv-0.21.0.tar.gz", hash = "sha256:b77d08274639e3d34145dfa6c7008e66df0f04b7be7a75fd0d5292c191d79045"},
|
||||
{file = "python_dotenv-0.21.0-py3-none-any.whl", hash = "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5"},
|
||||
]
|
||||
python-gitlab = [
|
||||
{file = "python-gitlab-3.5.0.tar.gz", hash = "sha256:29ae7fb9b8c9aeb2e6e19bd2fd04867e93ecd7af719978ce68fac0cf116ab30d"},
|
||||
{file = "python_gitlab-3.5.0-py3-none-any.whl", hash = "sha256:73b5aa6502efa557ee1a51227cceb0243fac5529627da34f08c5f265bf50417c"},
|
||||
|
@ -2135,6 +2182,10 @@ rook = [
|
|||
{file = "rook-0.1.175-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eb2783d654093f9e8fa2508dd5ee29c9fff90ccb075ac06359b103dc849a18db"},
|
||||
{file = "rook-0.1.175.tar.gz", hash = "sha256:b6d92298bfd170c8ff0e4b13ba870079f44644386e12c08244e182421b471004"},
|
||||
]
|
||||
setuptools = [
|
||||
{file = "setuptools-65.6.3-py3-none-any.whl", hash = "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54"},
|
||||
{file = "setuptools-65.6.3.tar.gz", hash = "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"},
|
||||
]
|
||||
six = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
|
|
|
@ -31,6 +31,7 @@ ansitoimg = "^2022.1"
|
|||
nest-asyncio = "^1.5.5"
|
||||
thefuzz = {extras = ["speedup"], version = "^0.19.0"}
|
||||
beautifulsoup4 = "^4.11.1"
|
||||
calculator = {git = "https://git.zevaryx.com/zevaryx/calculator.git"}
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
black = {version = "^22.3.0", allow-prereleases = true}
|
||||
|
|
Loading…
Add table
Reference in a new issue