update(core): change to >=3.8
This commit is contained in:
parent
b75e5b8a8e
commit
ba53228d44
24 changed files with 274 additions and 53 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -33,6 +33,9 @@ __pycache__/
|
||||||
__pypackages__/
|
__pypackages__/
|
||||||
|
|
||||||
venv
|
venv
|
||||||
|
venv3.8
|
||||||
|
venv3.9
|
||||||
|
venv3.11
|
||||||
dist
|
dist
|
||||||
build
|
build
|
||||||
*.egg
|
*.egg
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/data" />
|
<excludeFolder url="file://$MODULE_DIR$/data" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.mypy_cache" />
|
<excludeFolder url="file://$MODULE_DIR$/.mypy_cache" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/venv3.8" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/venv3.9" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/venv3.11" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.10 (tuxbot_bot)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.10 (tuxbot_bot)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -35,7 +35,7 @@ update-all:
|
||||||
|
|
||||||
.PHONY: dev
|
.PHONY: dev
|
||||||
dev: style update
|
dev: style update
|
||||||
tuxbot
|
$(VIRTUAL_ENV)/bin/tuxbot
|
||||||
|
|
||||||
# Docker
|
# Docker
|
||||||
.PHONY: docker
|
.PHONY: docker
|
||||||
|
|
|
@ -14,7 +14,7 @@ Installing the pre-requirements
|
||||||
|
|
||||||
- The pre-requirements are:
|
- The pre-requirements are:
|
||||||
|
|
||||||
- Python 3.10 or greater
|
- Python 3.8 or greater
|
||||||
- Pip
|
- Pip
|
||||||
- Git
|
- Git
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ To update the whole bot after a :bash:`git pull`, just execute
|
||||||
|
|
||||||
$ make update
|
$ make update
|
||||||
|
|
||||||
.. |image0| image:: https://img.shields.io/badge/python-3.10-%23007ec6
|
.. |image0| image:: https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10-%23007ec6
|
||||||
.. |image1| image:: https://img.shields.io/github/issues/Rom1-J/tuxbot-bot
|
.. |image1| image:: https://img.shields.io/github/issues/Rom1-J/tuxbot-bot
|
||||||
.. |image2| image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
.. |image2| image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||||
.. |image3| image:: https://wakatime.com/badge/github/Rom1-J/tuxbot-bot.svg
|
.. |image3| image:: https://wakatime.com/badge/github/Rom1-J/tuxbot-bot.svg
|
||||||
|
|
|
@ -13,7 +13,7 @@ platforms = linux
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
packages = find_namespace:
|
packages = find_namespace:
|
||||||
python_requires = >=3.10
|
python_requires = >=3.9
|
||||||
install_requires =
|
install_requires =
|
||||||
aiocache>=0.11.1
|
aiocache>=0.11.1
|
||||||
asyncpg>=0.21.0
|
asyncpg>=0.21.0
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -1,5 +1,5 @@
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
python_requires=">=3.10",
|
python_requires=">=3.8",
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
|
from typing import List
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
@ -76,7 +77,7 @@ class Custom(commands.Cog):
|
||||||
|
|
||||||
@_custom.command(name="alias", aliases=["aliases"])
|
@_custom.command(name="alias", aliases=["aliases"])
|
||||||
async def _custom_alias(self, ctx: ContextPlus, *, alias: AliasConvertor):
|
async def _custom_alias(self, ctx: ContextPlus, *, alias: AliasConvertor):
|
||||||
args: list[str] = str(alias).split(" | ")
|
args: List[str] = str(alias).split(" | ")
|
||||||
|
|
||||||
command = args[0]
|
command = args[0]
|
||||||
custom = args[1]
|
custom = args[1]
|
||||||
|
|
|
@ -2,7 +2,7 @@ from collections import Counter
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
|
|
||||||
def sort_by(_events: Counter) -> dict[str, dict]:
|
def sort_by(_events: Counter) -> Dict[str, dict]:
|
||||||
majors = (
|
majors = (
|
||||||
"guild",
|
"guild",
|
||||||
"channel",
|
"channel",
|
||||||
|
|
|
@ -6,7 +6,7 @@ import textwrap
|
||||||
import traceback
|
import traceback
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from logging import LogRecord
|
from logging import LogRecord
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict, List, DefaultDict
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
import humanize
|
import humanize
|
||||||
|
@ -53,7 +53,7 @@ class Logs(commands.Cog):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.process = psutil.Process()
|
self.process = psutil.Process()
|
||||||
self._batch_lock = asyncio.Lock()
|
self._batch_lock = asyncio.Lock()
|
||||||
self._data_batch: list[Dict[str, Any]] = []
|
self._data_batch: List[Dict[str, Any]] = []
|
||||||
self._gateway_queue: asyncio.Queue = asyncio.Queue()
|
self._gateway_queue: asyncio.Queue = asyncio.Queue()
|
||||||
self.gateway_worker.start() # pylint: disable=no-member
|
self.gateway_worker.start() # pylint: disable=no-member
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@ class Logs(commands.Cog):
|
||||||
LogsConfig,
|
LogsConfig,
|
||||||
).config
|
).config
|
||||||
|
|
||||||
self._resumes: list[datetime.datetime] = []
|
self._resumes: List[datetime.datetime] = []
|
||||||
self._identifies: defaultdict[Any, list] = defaultdict(list)
|
self._identifies: DefaultDict[Any, list] = defaultdict(list)
|
||||||
|
|
||||||
self.old_on_error = bot.on_error
|
self.old_on_error = bot.on_error
|
||||||
bot.on_error = self.on_error
|
bot.on_error = self.on_error
|
||||||
|
|
|
@ -6,6 +6,7 @@ from tuxbot.cogs.Mod.functions.exceptions import (
|
||||||
UnknownRuleException,
|
UnknownRuleException,
|
||||||
NonMessageException,
|
NonMessageException,
|
||||||
NonBotMessageException,
|
NonBotMessageException,
|
||||||
|
ReasonTooLongException,
|
||||||
)
|
)
|
||||||
from tuxbot.cogs.Mod.models import Rule
|
from tuxbot.cogs.Mod.models import Rule
|
||||||
|
|
||||||
|
@ -52,3 +53,13 @@ class BotMessageConverter(commands.Converter):
|
||||||
raise NonMessageException(
|
raise NonMessageException(
|
||||||
_("Please provide a message in this guild")
|
_("Please provide a message in this guild")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ReasonConverter(commands.Converter):
|
||||||
|
async def convert(self, ctx: Context, argument: str): # skipcq: PYL-W0613
|
||||||
|
if len(argument) > 300:
|
||||||
|
raise ReasonTooLongException(
|
||||||
|
_("Reason length must be 300 characters or lower.")
|
||||||
|
)
|
||||||
|
|
||||||
|
return argument
|
||||||
|
|
|
@ -19,3 +19,7 @@ class NonMessageException(ModException):
|
||||||
|
|
||||||
class NonBotMessageException(ModException):
|
class NonBotMessageException(ModException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ReasonTooLongException(ModException):
|
||||||
|
pass
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
from tuxbot.cogs.Mod.models import MuteRole
|
||||||
from tuxbot.cogs.Mod.models.rules import Rule
|
from tuxbot.cogs.Mod.models.rules import Rule
|
||||||
from tuxbot.core.config import set_for_key
|
from tuxbot.core.config import set_for_key
|
||||||
from tuxbot.core.config import Config
|
from tuxbot.core.config import Config
|
||||||
|
@ -10,15 +13,15 @@ async def save_lang(bot: Tux, ctx: ContextPlus, lang: str) -> None:
|
||||||
set_for_key(bot.config.Servers, ctx.guild.id, Config.Server, locale=lang)
|
set_for_key(bot.config.Servers, ctx.guild.id, Config.Server, locale=lang)
|
||||||
|
|
||||||
|
|
||||||
async def get_server_rules(guild_id: int) -> list[Rule]:
|
async def get_server_rules(guild_id: int) -> List[Rule]:
|
||||||
return await Rule.filter(server_id=guild_id).all().order_by("rule_id")
|
return await Rule.filter(server_id=guild_id).all().order_by("rule_id")
|
||||||
|
|
||||||
|
|
||||||
def get_most_recent_server_rules(rules: list[Rule]) -> Rule:
|
def get_most_recent_server_rules(rules: List[Rule]) -> Rule:
|
||||||
return sorted(rules, key=lambda r: r.updated_at, reverse=True)[0]
|
return sorted(rules, key=lambda r: r.updated_at, reverse=True)[0]
|
||||||
|
|
||||||
|
|
||||||
def paginate_server_rules(rules: list[Rule]) -> list[str]:
|
def paginate_server_rules(rules: List[Rule]) -> List[str]:
|
||||||
body = [""]
|
body = [""]
|
||||||
|
|
||||||
for rule in rules:
|
for rule in rules:
|
||||||
|
@ -32,3 +35,18 @@ def paginate_server_rules(rules: list[Rule]) -> list[str]:
|
||||||
|
|
||||||
def format_rule(rule: Rule) -> str:
|
def format_rule(rule: Rule) -> str:
|
||||||
return f"**{rule.rule_id}** - {rule.content}"
|
return f"**{rule.rule_id}** - {rule.content}"
|
||||||
|
|
||||||
|
|
||||||
|
async def get_mute_role(guild_id: int) -> Optional[MuteRole]:
|
||||||
|
return await MuteRole.get_or_none(server_id=guild_id)
|
||||||
|
|
||||||
|
|
||||||
|
async def create_mute_role(guild_id: int, role_id: int) -> MuteRole:
|
||||||
|
role_row = await MuteRole()
|
||||||
|
|
||||||
|
role_row.server_id = guild_id # type: ignore
|
||||||
|
role_row.role_id = role_id # type: ignore
|
||||||
|
|
||||||
|
await role_row.save()
|
||||||
|
|
||||||
|
return role_row
|
||||||
|
|
|
@ -8,12 +8,14 @@ from tuxbot.cogs.Mod.functions.converters import (
|
||||||
RuleConverter,
|
RuleConverter,
|
||||||
RuleIDConverter,
|
RuleIDConverter,
|
||||||
BotMessageConverter,
|
BotMessageConverter,
|
||||||
|
ReasonConverter,
|
||||||
)
|
)
|
||||||
from tuxbot.cogs.Mod.functions.exceptions import (
|
from tuxbot.cogs.Mod.functions.exceptions import (
|
||||||
RuleTooLongException,
|
RuleTooLongException,
|
||||||
UnknownRuleException,
|
UnknownRuleException,
|
||||||
NonMessageException,
|
NonMessageException,
|
||||||
NonBotMessageException,
|
NonBotMessageException,
|
||||||
|
ReasonTooLongException,
|
||||||
)
|
)
|
||||||
from tuxbot.cogs.Mod.functions.utils import (
|
from tuxbot.cogs.Mod.functions.utils import (
|
||||||
save_lang,
|
save_lang,
|
||||||
|
@ -21,6 +23,8 @@ from tuxbot.cogs.Mod.functions.utils import (
|
||||||
format_rule,
|
format_rule,
|
||||||
get_most_recent_server_rules,
|
get_most_recent_server_rules,
|
||||||
paginate_server_rules,
|
paginate_server_rules,
|
||||||
|
get_mute_role,
|
||||||
|
create_mute_role,
|
||||||
)
|
)
|
||||||
from tuxbot.cogs.Mod.models.rules import Rule
|
from tuxbot.cogs.Mod.models.rules import Rule
|
||||||
from tuxbot.core.utils import checks
|
from tuxbot.core.utils import checks
|
||||||
|
@ -35,6 +39,7 @@ from tuxbot.core.i18n import (
|
||||||
from tuxbot.core.utils.functions.extra import (
|
from tuxbot.core.utils.functions.extra import (
|
||||||
group_extra,
|
group_extra,
|
||||||
ContextPlus,
|
ContextPlus,
|
||||||
|
command_extra,
|
||||||
)
|
)
|
||||||
|
|
||||||
log = logging.getLogger("tuxbot.cogs.Mod")
|
log = logging.getLogger("tuxbot.cogs.Mod")
|
||||||
|
@ -53,9 +58,10 @@ class Mod(commands.Cog):
|
||||||
UnknownRuleException,
|
UnknownRuleException,
|
||||||
NonMessageException,
|
NonMessageException,
|
||||||
NonBotMessageException,
|
NonBotMessageException,
|
||||||
|
ReasonTooLongException,
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
await ctx.send(_(str(error), ctx, self.bot.config))
|
return await ctx.send(_(str(error), ctx, self.bot.config))
|
||||||
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
|
@ -163,7 +169,9 @@ class Mod(commands.Cog):
|
||||||
rule_row.server_id = ctx.guild.id
|
rule_row.server_id = ctx.guild.id
|
||||||
rule_row.author_id = ctx.message.author.id
|
rule_row.author_id = ctx.message.author.id
|
||||||
|
|
||||||
rule_row.rule_id = len(await get_server_rules(ctx.guild.id)) + 1 # type: ignore
|
rule_row.rule_id = (
|
||||||
|
len(await get_server_rules(ctx.guild.id)) + 1 # type: ignore
|
||||||
|
)
|
||||||
rule_row.content = str(rule) # type: ignore
|
rule_row.content = str(rule) # type: ignore
|
||||||
|
|
||||||
await rule_row.save()
|
await rule_row.save()
|
||||||
|
@ -243,10 +251,13 @@ class Mod(commands.Cog):
|
||||||
|
|
||||||
pages = paginate_server_rules(rules)
|
pages = paginate_server_rules(rules)
|
||||||
|
|
||||||
|
# noinspection PyTypeChecker
|
||||||
|
to_edit: discord.Message = message
|
||||||
|
|
||||||
if len(pages) == 1:
|
if len(pages) == 1:
|
||||||
embed.description = pages[0]
|
embed.description = pages[0]
|
||||||
|
|
||||||
await message.edit(content="", embed=embed)
|
await to_edit.edit(content="", embed=embed)
|
||||||
else:
|
else:
|
||||||
for i, page in enumerate(pages):
|
for i, page in enumerate(pages):
|
||||||
embed.title = _(
|
embed.title = _(
|
||||||
|
@ -254,4 +265,117 @@ class Mod(commands.Cog):
|
||||||
).format(ctx.guild.name, str(i + 1), str(len(pages)))
|
).format(ctx.guild.name, str(i + 1), str(len(pages)))
|
||||||
embed.description = page
|
embed.description = page
|
||||||
|
|
||||||
await message.edit(content="", embed=embed)
|
await to_edit.edit(content="", embed=embed)
|
||||||
|
|
||||||
|
# =========================================================================
|
||||||
|
|
||||||
|
@group_extra(
|
||||||
|
name="mute",
|
||||||
|
deletable=True,
|
||||||
|
invoke_without_command=True,
|
||||||
|
)
|
||||||
|
@commands.guild_only()
|
||||||
|
@checks.is_admin()
|
||||||
|
async def _mute(
|
||||||
|
self,
|
||||||
|
ctx: ContextPlus,
|
||||||
|
members: commands.Greedy[discord.Member],
|
||||||
|
*,
|
||||||
|
reason: ReasonConverter,
|
||||||
|
):
|
||||||
|
if not members:
|
||||||
|
return await ctx.send(_("Missing members", ctx, self.bot.config))
|
||||||
|
|
||||||
|
role_row = await get_mute_role(ctx.guild.id)
|
||||||
|
|
||||||
|
if role_row is None:
|
||||||
|
return await ctx.send(
|
||||||
|
_(
|
||||||
|
"No mute role has been specified for this guild",
|
||||||
|
ctx,
|
||||||
|
self.bot.config,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for member in members:
|
||||||
|
await member.add_roles(
|
||||||
|
discord.Object(id=int(role_row.role_id)), reason=reason
|
||||||
|
)
|
||||||
|
|
||||||
|
await ctx.send("\N{THUMBS UP SIGN}")
|
||||||
|
|
||||||
|
@_mute.command(name="show", aliases=["role"])
|
||||||
|
async def _mute_show(
|
||||||
|
self,
|
||||||
|
ctx: ContextPlus,
|
||||||
|
):
|
||||||
|
role_row = await get_mute_role(ctx.guild.id)
|
||||||
|
|
||||||
|
if (
|
||||||
|
role_row is None
|
||||||
|
or (role := ctx.guild.get_role(int(role_row.role_id))) is None
|
||||||
|
):
|
||||||
|
return await ctx.send(
|
||||||
|
_(
|
||||||
|
"No mute role has been specified for this guild",
|
||||||
|
ctx,
|
||||||
|
self.bot.config,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
muted_members = [m for m in ctx.guild.members if role in m.roles]
|
||||||
|
|
||||||
|
e = discord.Embed(
|
||||||
|
title=f"Role: {role.name} (ID: {role.id})", color=role.color
|
||||||
|
)
|
||||||
|
e.add_field(name="Total mute:", value=len(muted_members))
|
||||||
|
|
||||||
|
await ctx.send(embed=e)
|
||||||
|
|
||||||
|
@_mute.command(name="set", aliases=["define"])
|
||||||
|
async def _mute_set(self, ctx: ContextPlus, role: discord.Role):
|
||||||
|
role_row = await get_mute_role(ctx.guild.id)
|
||||||
|
|
||||||
|
if role_row is None:
|
||||||
|
await create_mute_role(ctx.guild.id, role.id)
|
||||||
|
else:
|
||||||
|
role_row.role_id = role.id # type: ignore
|
||||||
|
await role_row.save()
|
||||||
|
|
||||||
|
await ctx.send(
|
||||||
|
_("Mute role successfully defined", ctx, self.bot.config)
|
||||||
|
)
|
||||||
|
|
||||||
|
@command_extra(
|
||||||
|
name="unmute",
|
||||||
|
deletable=True,
|
||||||
|
)
|
||||||
|
@commands.guild_only()
|
||||||
|
@checks.is_admin()
|
||||||
|
async def _unmute(
|
||||||
|
self,
|
||||||
|
ctx: ContextPlus,
|
||||||
|
members: commands.Greedy[discord.Member],
|
||||||
|
*,
|
||||||
|
reason: ReasonConverter,
|
||||||
|
):
|
||||||
|
if not members:
|
||||||
|
return await ctx.send(_("Missing members", ctx, self.bot.config))
|
||||||
|
|
||||||
|
role_row = await get_mute_role(ctx.guild.id)
|
||||||
|
|
||||||
|
if role_row is None:
|
||||||
|
return await ctx.send(
|
||||||
|
_(
|
||||||
|
"No mute role has been specified for this guild",
|
||||||
|
ctx,
|
||||||
|
self.bot.config,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for member in members:
|
||||||
|
await member.remove_roles(
|
||||||
|
discord.Object(id=int(role_row.role_id)), reason=reason
|
||||||
|
)
|
||||||
|
|
||||||
|
await ctx.send("\N{THUMBS UP SIGN}")
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
from .rules import *
|
from .rules import *
|
||||||
from .warns import *
|
from .warns import *
|
||||||
|
from .mutes import *
|
||||||
|
|
46
tuxbot/cogs/Mod/models/mutes.py
Normal file
46
tuxbot/cogs/Mod/models/mutes.py
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import tortoise
|
||||||
|
from tortoise import fields
|
||||||
|
|
||||||
|
|
||||||
|
class MuteRole(tortoise.Model):
|
||||||
|
id = fields.BigIntField(pk=True)
|
||||||
|
server_id = fields.BigIntField()
|
||||||
|
role_id = fields.BigIntField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
table = "mute_role"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
f"<MuteRole id={self.id} "
|
||||||
|
f"server_id={self.server_id} "
|
||||||
|
f"role_id={self.role_id}>"
|
||||||
|
)
|
||||||
|
|
||||||
|
__repr__ = __str__
|
||||||
|
|
||||||
|
|
||||||
|
class Mute(tortoise.Model):
|
||||||
|
id = fields.BigIntField(pk=True)
|
||||||
|
server_id = fields.BigIntField()
|
||||||
|
author_id = fields.BigIntField()
|
||||||
|
reason = fields.TextField(max_length=300)
|
||||||
|
member_id = fields.BigIntField()
|
||||||
|
created_at = fields.DatetimeField(auto_now_add=True)
|
||||||
|
expire_at = fields.DatetimeField(null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
table = "mutes"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
f"<Mute id={self.id} "
|
||||||
|
f"server_id={self.server_id} "
|
||||||
|
f"author_id={self.author_id} "
|
||||||
|
f"reason='{self.reason}' "
|
||||||
|
f"member_id={self.member_id} "
|
||||||
|
f"created_at={self.created_at} "
|
||||||
|
f"expire_at={self.expire_at}>"
|
||||||
|
)
|
||||||
|
|
||||||
|
__repr__ = __str__
|
|
@ -1,6 +1,6 @@
|
||||||
import io
|
import io
|
||||||
import socket
|
import socket
|
||||||
from typing import NoReturn, Optional
|
from typing import NoReturn, Optional, Union
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import re
|
import re
|
||||||
|
@ -37,7 +37,7 @@ def _(x):
|
||||||
namespace="network",
|
namespace="network",
|
||||||
)
|
)
|
||||||
async def get_ip(loop, ip: str, inet: Optional[dict]) -> str:
|
async def get_ip(loop, ip: str, inet: Optional[dict]) -> str:
|
||||||
_inet: socket.AddressFamily | int = 0 # pylint: disable=no-member
|
_inet: Union[socket.AddressFamily, int] = 0 # pylint: disable=no-member
|
||||||
|
|
||||||
if inet:
|
if inet:
|
||||||
if inet["inet"] == "6":
|
if inet["inet"] == "6":
|
||||||
|
@ -89,8 +89,8 @@ async def get_hostname(loop, ip: str) -> str:
|
||||||
cache=Cache.MEMORY,
|
cache=Cache.MEMORY,
|
||||||
namespace="network",
|
namespace="network",
|
||||||
)
|
)
|
||||||
async def get_ipwhois_result(loop, ip: str) -> NoReturn | dict:
|
async def get_ipwhois_result(loop, ip: str) -> Union[NoReturn, dict]:
|
||||||
def _get_ipwhois_result(_ip: str) -> NoReturn | dict:
|
def _get_ipwhois_result(_ip: str) -> Union[NoReturn, dict]:
|
||||||
try:
|
try:
|
||||||
net = Net(ip)
|
net = Net(ip)
|
||||||
obj = IPASN(net)
|
obj = IPASN(net)
|
||||||
|
@ -121,7 +121,7 @@ async def get_ipwhois_result(loop, ip: str) -> NoReturn | dict:
|
||||||
namespace="network",
|
namespace="network",
|
||||||
)
|
)
|
||||||
async def get_ipinfo_result(loop, apikey: str, ip: str) -> dict:
|
async def get_ipinfo_result(loop, apikey: str, ip: str) -> dict:
|
||||||
def _get_ipinfo_result(_ip: str) -> NoReturn | dict:
|
def _get_ipinfo_result(_ip: str) -> Union[NoReturn, dict]:
|
||||||
"""
|
"""
|
||||||
Q. Why no getHandlerAsync ?
|
Q. Why no getHandlerAsync ?
|
||||||
A. Use of this return "Unclosed client session" and "Unclosed connector"
|
A. Use of this return "Unclosed client session" and "Unclosed connector"
|
||||||
|
@ -251,11 +251,11 @@ async def get_map_bytes(apikey: str, latlon: str) -> Optional[io.BytesIO]:
|
||||||
namespace="network",
|
namespace="network",
|
||||||
)
|
)
|
||||||
async def get_pydig_result(
|
async def get_pydig_result(
|
||||||
loop, domain: str, query_type: str, dnssec: str | bool
|
loop, domain: str, query_type: str, dnssec: Union[str, bool]
|
||||||
) -> list:
|
) -> list:
|
||||||
additional_args = [] if dnssec is False else ["+dnssec"]
|
additional_args = [] if dnssec is False else ["+dnssec"]
|
||||||
|
|
||||||
def _get_pydig_result(_domain: str) -> NoReturn | dict:
|
def _get_pydig_result(_domain: str) -> Union[NoReturn, dict]:
|
||||||
resolver = pydig.Resolver(
|
resolver = pydig.Resolver(
|
||||||
nameservers=[
|
nameservers=[
|
||||||
"80.67.169.40",
|
"80.67.169.40",
|
||||||
|
@ -275,14 +275,16 @@ async def get_pydig_result(
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def check_ip_version_or_raise(version: Optional[dict]) -> bool | NoReturn:
|
def check_ip_version_or_raise(
|
||||||
|
version: Optional[dict],
|
||||||
|
) -> Union[bool, NoReturn]:
|
||||||
if version is None or version["inet"] in ("4", "6", ""):
|
if version is None or version["inet"] in ("4", "6", ""):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
raise InvalidIp(_("Invalid ip version"))
|
raise InvalidIp(_("Invalid ip version"))
|
||||||
|
|
||||||
|
|
||||||
def check_query_type_or_raise(query_type: str) -> bool | NoReturn:
|
def check_query_type_or_raise(query_type: str) -> Union[bool, NoReturn]:
|
||||||
query_types = (
|
query_types = (
|
||||||
"a",
|
"a",
|
||||||
"aaaa",
|
"aaaa",
|
||||||
|
@ -306,7 +308,7 @@ def check_query_type_or_raise(query_type: str) -> bool | NoReturn:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def check_asn_or_raise(asn: str) -> bool | NoReturn:
|
def check_asn_or_raise(asn: str) -> Union[bool, NoReturn]:
|
||||||
if asn.isdigit() and int(asn) < 4_294_967_295:
|
if asn.isdigit() and int(asn) < 4_294_967_295:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import asyncio
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Optional
|
from typing import Optional, Union
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import discord
|
import discord
|
||||||
|
@ -272,7 +272,7 @@ class Network(commands.Cog):
|
||||||
ctx: ContextPlus,
|
ctx: ContextPlus,
|
||||||
domain: IPConverter,
|
domain: IPConverter,
|
||||||
query_type: QueryTypeConverter,
|
query_type: QueryTypeConverter,
|
||||||
dnssec: str | bool = False,
|
dnssec: Union[str, bool] = False,
|
||||||
):
|
):
|
||||||
check_query_type_or_raise(str(query_type))
|
check_query_type_or_raise(str(query_type))
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict
|
from typing import Dict, Union, List
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
@ -45,7 +45,7 @@ class Polls(commands.Cog):
|
||||||
self,
|
self,
|
||||||
ctx: ContextPlus,
|
ctx: ContextPlus,
|
||||||
question: str,
|
question: str,
|
||||||
answers: list[str],
|
answers: List[str],
|
||||||
anonymous=False,
|
anonymous=False,
|
||||||
):
|
):
|
||||||
emotes = utils_emotes.get(len(answers))
|
emotes = utils_emotes.get(len(answers))
|
||||||
|
@ -90,7 +90,7 @@ class Polls(commands.Cog):
|
||||||
|
|
||||||
async def get_poll(
|
async def get_poll(
|
||||||
self, pld: discord.RawReactionActionEvent
|
self, pld: discord.RawReactionActionEvent
|
||||||
) -> bool | Poll:
|
) -> Union[bool, Poll]:
|
||||||
if pld.user_id != self.bot.user.id:
|
if pld.user_id != self.bot.user.id:
|
||||||
poll = await Poll.get_or_none(message_id=pld.message_id)
|
poll = await Poll.get_or_none(message_id=pld.message_id)
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ class Polls(commands.Cog):
|
||||||
|
|
||||||
async def get_suggest(
|
async def get_suggest(
|
||||||
self, pld: discord.RawReactionActionEvent
|
self, pld: discord.RawReactionActionEvent
|
||||||
) -> bool | Suggest:
|
) -> Union[bool, Suggest]:
|
||||||
if pld.user_id != self.bot.user.id:
|
if pld.user_id != self.bot.user.id:
|
||||||
suggest = await Suggest.get_or_none(message_id=pld.message_id)
|
suggest = await Suggest.get_or_none(message_id=pld.message_id)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Optional
|
from typing import Optional, List
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ async def get_tag(guild_id: int, name: str) -> Tag:
|
||||||
|
|
||||||
async def get_all_tags(
|
async def get_all_tags(
|
||||||
guild_id: int, author: Optional[discord.Member] = None
|
guild_id: int, author: Optional[discord.Member] = None
|
||||||
) -> list[Tag]:
|
) -> List[Tag]:
|
||||||
if author is not None:
|
if author is not None:
|
||||||
return (
|
return (
|
||||||
await Tag.filter(server_id=guild_id, author_id=author.id)
|
await Tag.filter(server_id=guild_id, author_id=author.id)
|
||||||
|
@ -23,7 +23,7 @@ async def get_all_tags(
|
||||||
return await Tag.filter(server_id=guild_id).all().order_by("-uses")
|
return await Tag.filter(server_id=guild_id).all().order_by("-uses")
|
||||||
|
|
||||||
|
|
||||||
async def search_tags(guild_id: int, q: str) -> list[Tag]:
|
async def search_tags(guild_id: int, q: str) -> List[Tag]:
|
||||||
return (
|
return (
|
||||||
await Tag.filter(server_id=guild_id, name__icontains=q)
|
await Tag.filter(server_id=guild_id, name__icontains=q)
|
||||||
.all()
|
.all()
|
||||||
|
|
|
@ -2,8 +2,9 @@ import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
import importlib
|
import importlib
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple, Union
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import discord
|
import discord
|
||||||
|
@ -177,6 +178,7 @@ class Tux(commands.AutoShardedBot):
|
||||||
table.add_row(f"Language: {self.config.Core.locale}")
|
table.add_row(f"Language: {self.config.Core.locale}")
|
||||||
table.add_row(f"Tuxbot Version: {__version__}")
|
table.add_row(f"Tuxbot Version: {__version__}")
|
||||||
table.add_row(f"Discord.py Version: {discord.__version__}")
|
table.add_row(f"Discord.py Version: {discord.__version__}")
|
||||||
|
table.add_row(f"Python Version: {sys.version.split(' ')[0]}")
|
||||||
table.add_row(f"Instance name: {self.instance_name}")
|
table.add_row(f"Instance name: {self.instance_name}")
|
||||||
table.add_row(f"Shards: {self.shard_count}")
|
table.add_row(f"Shards: {self.shard_count}")
|
||||||
table.add_row(f"Servers: {len(self.guilds)}")
|
table.add_row(f"Servers: {len(self.guilds)}")
|
||||||
|
@ -200,13 +202,13 @@ class Tux(commands.AutoShardedBot):
|
||||||
self.console.print()
|
self.console.print()
|
||||||
|
|
||||||
async def is_owner(
|
async def is_owner(
|
||||||
self, user: discord.User | discord.Member | discord.Object
|
self, user: Union[discord.User, discord.Member, discord.Object]
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Determines if the user is a bot owner.
|
"""Determines if the user is a bot owner.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
user: discord.User | discord.Member
|
user: Union[discord.User, discord.Member]
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, NoReturn, Any, Tuple
|
from typing import Dict, NoReturn, Any, Tuple, Union
|
||||||
|
|
||||||
from babel.messages.pofile import read_po
|
from babel.messages.pofile import read_po
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ available_locales: Dict[str, Tuple] = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def find_locale(locale: str) -> str | NoReturn:
|
def find_locale(locale: str) -> Union[str, NoReturn]:
|
||||||
"""We suppose `locale` is in `_available_locales.values()`"""
|
"""We suppose `locale` is in `_available_locales.values()`"""
|
||||||
|
|
||||||
for key, val in available_locales.items():
|
for key, val in available_locales.items():
|
||||||
|
@ -46,7 +46,9 @@ def get_locale_name(locale: str) -> str:
|
||||||
class Translator:
|
class Translator:
|
||||||
"""Class to load texts at init."""
|
"""Class to load texts at init."""
|
||||||
|
|
||||||
def __init__(self, name: str, file_location: Path | os.PathLike | str):
|
def __init__(
|
||||||
|
self, name: str, file_location: Union[Path, os.PathLike, str]
|
||||||
|
):
|
||||||
"""Initializes the Translator object.
|
"""Initializes the Translator object.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import functools
|
import functools
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Optional, Tuple
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
@ -29,7 +29,7 @@ def typing(func):
|
||||||
|
|
||||||
async def shorten(
|
async def shorten(
|
||||||
text: str, length: int, fail: bool = False
|
text: str, length: int, fail: bool = False
|
||||||
) -> tuple[bool, dict]:
|
) -> Tuple[bool, dict]:
|
||||||
output: Dict[str, str] = {"text": text[:length], "link": ""}
|
output: Dict[str, str] = {"text": text[:length], "link": ""}
|
||||||
|
|
||||||
if len(text) > length:
|
if len(text) > length:
|
||||||
|
|
|
@ -7,7 +7,7 @@ import sys
|
||||||
import json
|
import json
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List, Union
|
||||||
from urllib import request
|
from urllib import request
|
||||||
|
|
||||||
from rich.prompt import Prompt, IntPrompt
|
from rich.prompt import Prompt, IntPrompt
|
||||||
|
@ -121,7 +121,7 @@ def get_ip() -> str:
|
||||||
|
|
||||||
def get_multiple(
|
def get_multiple(
|
||||||
question: str, confirmation: str, value_type: type
|
question: str, confirmation: str, value_type: type
|
||||||
) -> List[str | int]:
|
) -> List[Union[str, int]]:
|
||||||
"""Give possibility to user to fill multiple value.
|
"""Give possibility to user to fill multiple value.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
@ -135,10 +135,12 @@ def get_multiple(
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
List[str | int]
|
List[Union[str, int]]
|
||||||
List containing user filled values.
|
List containing user filled values.
|
||||||
"""
|
"""
|
||||||
prompt: IntPrompt | Prompt = IntPrompt() if value_type is int else Prompt()
|
prompt: Union[IntPrompt, Prompt] = (
|
||||||
|
IntPrompt() if value_type is int else Prompt()
|
||||||
|
)
|
||||||
|
|
||||||
user_input = prompt.ask(question, console=console)
|
user_input = prompt.ask(question, console=console)
|
||||||
|
|
||||||
|
@ -166,12 +168,14 @@ def get_multiple(
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
||||||
def get_extra(question: str, value_type: type) -> str | int:
|
def get_extra(question: str, value_type: type) -> Union[str, int]:
|
||||||
prompt: IntPrompt | Prompt = IntPrompt() if value_type is int else Prompt()
|
prompt: Union[IntPrompt, Prompt] = (
|
||||||
|
IntPrompt() if value_type is int else Prompt()
|
||||||
|
)
|
||||||
return prompt.ask(question, console=console)
|
return prompt.ask(question, console=console)
|
||||||
|
|
||||||
|
|
||||||
def additional_config(cogs: str | list = "**"):
|
def additional_config(cogs: Union[str, list] = "**"):
|
||||||
"""Asking for additional configs in cogs.
|
"""Asking for additional configs in cogs.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
|
|
Loading…
Reference in a new issue