Pass all flake8 checks
This commit is contained in:
parent
a87783db16
commit
93759287ca
50 changed files with 625 additions and 380 deletions
|
@ -35,9 +35,3 @@ repos:
|
|||
- flake8-bandit~=2.1
|
||||
- flake8-docstrings~=1.5
|
||||
args: [--max-line-length=120, --ignore=ANN101 D107 ANN102 ANN206 D105 ANN204]
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.910
|
||||
hooks:
|
||||
- id: mypy
|
||||
args: [--install-types, --non-interactive]
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
"""Main J.A.R.V.I.S. package."""
|
||||
import asyncio
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
from typing import Optional
|
||||
|
||||
from discord import Intents
|
||||
from discord.ext import commands
|
||||
|
@ -10,7 +11,7 @@ from discord_slash import SlashCommand
|
|||
from mongoengine import connect
|
||||
from psutil import Process
|
||||
|
||||
from jarvis import logo
|
||||
from jarvis import logo # noqa: F401
|
||||
from jarvis import tasks
|
||||
from jarvis import utils
|
||||
from jarvis.config import get_config
|
||||
|
@ -18,6 +19,14 @@ from jarvis.events import guild
|
|||
from jarvis.events import member
|
||||
from jarvis.events import message
|
||||
|
||||
jconfig = get_config()
|
||||
|
||||
logger = logging.getLogger("discord")
|
||||
logger.setLevel(logging.getLevelName(jconfig.log_level))
|
||||
file_handler = logging.FileHandler(filename="jarvis.log", encoding="UTF-8", mode="w")
|
||||
file_handler.setFormatter(logging.Formatter("[%(asctime)s][%(levelname)s][%(name)s] %(message)s"))
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
if asyncio.get_event_loop().is_closed():
|
||||
asyncio.set_event_loop(asyncio.new_event_loop())
|
||||
|
||||
|
@ -25,7 +34,6 @@ intents = Intents.default()
|
|||
intents.members = True
|
||||
restart_ctx = None
|
||||
|
||||
jconfig = get_config()
|
||||
|
||||
jarvis = commands.Bot(
|
||||
command_prefix=utils.get_prefix,
|
||||
|
@ -40,7 +48,8 @@ __version__ = "1.10.3"
|
|||
|
||||
|
||||
@jarvis.event
|
||||
async def on_ready():
|
||||
async def on_ready() -> None:
|
||||
"""d.py on_ready override."""
|
||||
global restart_ctx
|
||||
print(" Logged in as {0.user}".format(jarvis))
|
||||
print(" Connected to {} guild(s)".format(len(jarvis.guilds)))
|
||||
|
@ -60,7 +69,8 @@ async def on_ready():
|
|||
restart_ctx = None
|
||||
|
||||
|
||||
def run(ctx=None):
|
||||
def run(ctx: dict = None) -> Optional[dict]:
|
||||
"""Run J.A.R.V.I.S."""
|
||||
global restart_ctx
|
||||
if ctx:
|
||||
restart_ctx = ctx
|
||||
|
@ -81,7 +91,7 @@ def run(ctx=None):
|
|||
jarvis.load_extension(extension)
|
||||
print(
|
||||
" https://discord.com/api/oauth2/authorize?client_id="
|
||||
+ "{}&permissions=8&scope=bot%20applications.commands".format(jconfig.client_id)
|
||||
+ "{}&permissions=8&scope=bot%20applications.commands".format(jconfig.client_id) # noqa: W503
|
||||
)
|
||||
|
||||
jarvis.max_messages = jconfig.max_messages
|
||||
|
@ -89,7 +99,7 @@ def run(ctx=None):
|
|||
|
||||
# Add event listeners
|
||||
if jconfig.events:
|
||||
listeners = [
|
||||
_ = [
|
||||
guild.GuildEventHandler(jarvis),
|
||||
member.MemberEventHandler(jarvis),
|
||||
message.MessageEventHandler(jarvis),
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
"""J.A.R.V.I.S. Admin Cogs."""
|
||||
from discord.ext.commands import Bot
|
||||
|
||||
from jarvis.cogs.admin import ban
|
||||
from jarvis.cogs.admin import kick
|
||||
from jarvis.cogs.admin import lock
|
||||
|
@ -8,7 +11,8 @@ from jarvis.cogs.admin import roleping
|
|||
from jarvis.cogs.admin import warning
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: Bot) -> None:
|
||||
"""Add admin cogs to J.A.R.V.I.S."""
|
||||
bot.add_cog(ban.BanCog(bot))
|
||||
bot.add_cog(kick.KickCog(bot))
|
||||
bot.add_cog(lock.LockCog(bot))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. BanCog."""
|
||||
import re
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
@ -21,6 +22,8 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class BanCog(CacheCog):
|
||||
"""J.A.R.V.I.S. BanCog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
super().__init__(bot)
|
||||
|
||||
|
@ -32,7 +35,8 @@ class BanCog(CacheCog):
|
|||
duration: int,
|
||||
active: bool,
|
||||
fields: list,
|
||||
):
|
||||
) -> None:
|
||||
"""Apply a Discord ban."""
|
||||
await ctx.guild.ban(user, reason=reason)
|
||||
_ = Ban(
|
||||
user=user.id,
|
||||
|
@ -61,7 +65,8 @@ class BanCog(CacheCog):
|
|||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
async def discord_apply_unban(self, ctx: SlashContext, user: User, reason: str):
|
||||
async def discord_apply_unban(self, ctx: SlashContext, user: User, reason: str) -> None:
|
||||
"""Apply a Discord unban."""
|
||||
await ctx.guild.unban(user, reason=reason)
|
||||
_ = Unban(
|
||||
user=user.id,
|
||||
|
@ -128,7 +133,7 @@ class BanCog(CacheCog):
|
|||
reason: str = None,
|
||||
type: str = "perm",
|
||||
duration: int = 4,
|
||||
):
|
||||
) -> None:
|
||||
if not user or user == ctx.author:
|
||||
await ctx.send("You cannot ban yourself.", hidden=True)
|
||||
return
|
||||
|
@ -221,7 +226,7 @@ class BanCog(CacheCog):
|
|||
ctx: SlashContext,
|
||||
user: str,
|
||||
reason: str,
|
||||
):
|
||||
) -> None:
|
||||
if len(reason) > 100:
|
||||
await ctx.send("Reason must be < 100 characters", hidden=True)
|
||||
return
|
||||
|
@ -252,12 +257,8 @@ class BanCog(CacheCog):
|
|||
active_bans = []
|
||||
for ban in bans:
|
||||
active_bans.append("{0} ({1}): {2}".format(ban.user.name, ban.user.id, ban.reason))
|
||||
message = (
|
||||
"More than one result. "
|
||||
+ "Please use one of the following IDs:\n```"
|
||||
+ "\n".join(active_bans)
|
||||
+ "\n```"
|
||||
)
|
||||
ab_message = "\n".join(active_bans)
|
||||
message = f"More than one result. Please use one of the following IDs:\n```{ab_message}\n```"
|
||||
await ctx.send(message)
|
||||
return
|
||||
else:
|
||||
|
@ -331,13 +332,13 @@ class BanCog(CacheCog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(ban_members=True)
|
||||
async def _bans_list(self, ctx: SlashContext, type: int = 0, active: int = 1):
|
||||
async def _bans_list(self, ctx: SlashContext, type: int = 0, active: int = 1) -> None:
|
||||
active = bool(active)
|
||||
exists = self.check_cache(ctx, type=type, active=active)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.send(
|
||||
"Please use existing interaction: " + f"{exists['paginator']._message.jump_url}",
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -357,10 +358,12 @@ class BanCog(CacheCog):
|
|||
fields.append(
|
||||
Field(
|
||||
name=f"Username: {ban.username}#{ban.discrim}",
|
||||
value=f"Date: {ban.created_at.strftime('%d-%m-%Y')}\n"
|
||||
+ f"User ID: {ban.user}\n"
|
||||
+ f"Reason: {ban.reason}\n"
|
||||
+ f"Type: {ban.type}\n\u200b",
|
||||
value=(
|
||||
f"Date: {ban.created_at.strftime('%d-%m-%Y')}\n"
|
||||
f"User ID: {ban.user}\n"
|
||||
f"Reason: {ban.reason}\n"
|
||||
f"Type: {ban.type}\n\u200b"
|
||||
),
|
||||
inline=False,
|
||||
)
|
||||
)
|
||||
|
@ -372,10 +375,12 @@ class BanCog(CacheCog):
|
|||
fields.append(
|
||||
Field(
|
||||
name=f"Username: {ban.user.name}#" + f"{ban.user.discriminator}",
|
||||
value="Date: [unknown]\n"
|
||||
+ f"User ID: {ban.user.id}\n"
|
||||
+ f"Reason: {ban.reason}\n"
|
||||
+ "Type: manual\n\u200b",
|
||||
value=(
|
||||
f"Date: [unknown]\n"
|
||||
f"User ID: {ban.user.id}\n"
|
||||
f"Reason: {ban.reason}\n"
|
||||
"Type: manual\n\u200b"
|
||||
),
|
||||
inline=False,
|
||||
)
|
||||
)
|
||||
|
@ -397,7 +402,7 @@ class BanCog(CacheCog):
|
|||
pages.append(embed)
|
||||
else:
|
||||
for i in range(0, len(bans), 5):
|
||||
embed = build_embed(title=title, description="", fields=fields[i : i + 5])
|
||||
embed = build_embed(title=title, description="", fields=fields[i : i + 5]) # noqa: E203
|
||||
embed.set_thumbnail(url=ctx.guild.icon_url)
|
||||
pages.append(embed)
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
"""J.A.R.V.I.S. KickCog."""
|
||||
from discord import User
|
||||
from discord.ext.commands import Bot
|
||||
from discord_slash import cog_ext
|
||||
from discord_slash import SlashContext
|
||||
from discord_slash.utils.manage_commands import create_option
|
||||
|
@ -11,7 +13,9 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class KickCog(CacheCog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. KickCog."""
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
|
||||
@cog_ext.cog_slash(
|
||||
|
@ -33,7 +37,7 @@ class KickCog(CacheCog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(kick_members=True)
|
||||
async def _kick(self, ctx: SlashContext, user: User, reason=None):
|
||||
async def _kick(self, ctx: SlashContext, user: User, reason: str = None) -> None:
|
||||
if not user or user == ctx.author:
|
||||
await ctx.send("You cannot kick yourself.", hidden=True)
|
||||
return
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
"""J.A.R.V.I.S. LockCog."""
|
||||
from contextlib import suppress
|
||||
from typing import Union
|
||||
|
||||
from discord import Role
|
||||
from discord import TextChannel
|
||||
from discord import User
|
||||
from discord import VoiceChannel
|
||||
from discord.ext import commands
|
||||
from discord.ext.commands import Bot
|
||||
from discord_slash import cog_ext
|
||||
from discord_slash import SlashContext
|
||||
from discord_slash.utils.manage_commands import create_option
|
||||
|
@ -15,7 +17,9 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class LockCog(CacheCog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
"""J.A.R.V.I.S. LockCog."""
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
|
||||
async def _lock_channel(
|
||||
|
@ -24,8 +28,8 @@ class LockCog(CacheCog):
|
|||
role: Role,
|
||||
admin: User,
|
||||
reason: str,
|
||||
allow_send=False,
|
||||
):
|
||||
allow_send: bool = False,
|
||||
) -> None:
|
||||
overrides = channel.overwrites_for(role)
|
||||
if isinstance(channel, TextChannel):
|
||||
overrides.send_messages = allow_send
|
||||
|
@ -38,7 +42,7 @@ class LockCog(CacheCog):
|
|||
channel: Union[TextChannel, VoiceChannel],
|
||||
role: Role,
|
||||
admin: User,
|
||||
):
|
||||
) -> None:
|
||||
overrides = channel.overwrites_for(role)
|
||||
if isinstance(channel, TextChannel):
|
||||
overrides.send_messages = None
|
||||
|
@ -77,7 +81,7 @@ class LockCog(CacheCog):
|
|||
reason: str,
|
||||
duration: int = 10,
|
||||
channel: Union[TextChannel, VoiceChannel] = None,
|
||||
):
|
||||
) -> None:
|
||||
await ctx.defer(hidden=True)
|
||||
if duration <= 0:
|
||||
await ctx.send("Duration must be > 0", hidden=True)
|
||||
|
@ -91,10 +95,8 @@ class LockCog(CacheCog):
|
|||
if not channel:
|
||||
channel = ctx.channel
|
||||
for role in ctx.guild.roles:
|
||||
try:
|
||||
with suppress(Exception):
|
||||
await self._lock_channel(channel, role, ctx.author, reason)
|
||||
except Exception:
|
||||
continue # Just continue on error
|
||||
_ = Lock(
|
||||
channel=channel.id,
|
||||
guild=ctx.guild.id,
|
||||
|
@ -121,7 +123,7 @@ class LockCog(CacheCog):
|
|||
self,
|
||||
ctx: SlashContext,
|
||||
channel: Union[TextChannel, VoiceChannel] = None,
|
||||
):
|
||||
) -> None:
|
||||
if not channel:
|
||||
channel = ctx.channel
|
||||
lock = Lock.objects(guild=ctx.guild.id, channel=channel.id, active=True).first()
|
||||
|
@ -129,10 +131,8 @@ class LockCog(CacheCog):
|
|||
await ctx.send(f"{channel.mention} not locked.", hidden=True)
|
||||
return
|
||||
for role in ctx.guild.roles:
|
||||
try:
|
||||
with suppress(Exception):
|
||||
await self._unlock_channel(channel, role, ctx.author)
|
||||
except Exception:
|
||||
continue # Just continue on error
|
||||
lock.active = False
|
||||
lock.save()
|
||||
await ctx.send(f"{channel.mention} unlocked")
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"""J.A.R.V.I.S. LockdownCog."""
|
||||
from contextlib import suppress
|
||||
from datetime import datetime
|
||||
|
||||
from discord.ext import commands
|
||||
|
@ -11,6 +13,8 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class LockdownCog(CacheCog):
|
||||
"""J.A.R.V.I.S. LockdownCog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
super().__init__(bot)
|
||||
|
||||
|
@ -39,7 +43,7 @@ class LockdownCog(CacheCog):
|
|||
ctx: SlashContext,
|
||||
reason: str,
|
||||
duration: int = 10,
|
||||
):
|
||||
) -> None:
|
||||
await ctx.defer(hidden=True)
|
||||
if duration <= 0:
|
||||
await ctx.send("Duration must be > 0", hidden=True)
|
||||
|
@ -52,10 +56,8 @@ class LockdownCog(CacheCog):
|
|||
updates = []
|
||||
for channel in channels:
|
||||
for role in roles:
|
||||
try:
|
||||
with suppress(Exception):
|
||||
await self._lock_channel(channel, role, ctx.author, reason)
|
||||
except Exception:
|
||||
continue # Just continue on error
|
||||
updates.append(
|
||||
Lock(
|
||||
channel=channel.id,
|
||||
|
@ -80,7 +82,7 @@ class LockdownCog(CacheCog):
|
|||
async def _lockdown_end(
|
||||
self,
|
||||
ctx: SlashContext,
|
||||
):
|
||||
) -> None:
|
||||
channels = ctx.guild.channels
|
||||
roles = ctx.guild.roles
|
||||
update = False
|
||||
|
@ -91,10 +93,8 @@ class LockdownCog(CacheCog):
|
|||
await ctx.defer()
|
||||
for channel in channels:
|
||||
for role in roles:
|
||||
try:
|
||||
with suppress(Exception):
|
||||
await self._unlock_channel(channel, role, ctx.author)
|
||||
except Exception:
|
||||
continue # Just continue on error
|
||||
update = True
|
||||
if update:
|
||||
Lock.objects(guild=ctx.guild.id, active=True).update(set__active=False)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. MuteCog."""
|
||||
from discord import Member
|
||||
from discord.ext import commands
|
||||
from discord.utils import get
|
||||
|
@ -13,7 +14,9 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class MuteCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. MuteCog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@cog_ext.cog_slash(
|
||||
|
@ -41,7 +44,7 @@ class MuteCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(mute_members=True)
|
||||
async def _mute(self, ctx: SlashContext, user: Member, reason: str, duration: int = 30):
|
||||
async def _mute(self, ctx: SlashContext, user: Member, reason: str, duration: int = 30) -> None:
|
||||
if user == ctx.author:
|
||||
await ctx.send("You cannot mute yourself.", hidden=True)
|
||||
return
|
||||
|
@ -54,7 +57,7 @@ class MuteCog(commands.Cog):
|
|||
mute_setting = Setting.objects(guild=ctx.guild.id, setting="mute").first()
|
||||
if not mute_setting:
|
||||
await ctx.send(
|
||||
"Please configure a mute role " + "with /settings mute <role> first",
|
||||
"Please configure a mute role with /settings mute <role> first",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -100,11 +103,11 @@ class MuteCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(mute_members=True)
|
||||
async def _unmute(self, ctx: SlashContext, user: Member):
|
||||
async def _unmute(self, ctx: SlashContext, user: Member) -> None:
|
||||
mute_setting = Setting.objects(guild=ctx.guild.id, setting="mute").first()
|
||||
if not mute_setting:
|
||||
await ctx.send(
|
||||
"Please configure a mute role with " + "/settings mute <role> first.",
|
||||
"Please configure a mute role with /settings mute <role> first.",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. PurgeCog."""
|
||||
from discord import TextChannel
|
||||
from discord.ext import commands
|
||||
from discord_slash import cog_ext
|
||||
|
@ -10,7 +11,9 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class PurgeCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. PurgeCog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@cog_ext.cog_slash(
|
||||
|
@ -26,7 +29,7 @@ class PurgeCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_messages=True)
|
||||
async def _purge(self, ctx: SlashContext, amount: int = 10):
|
||||
async def _purge(self, ctx: SlashContext, amount: int = 10) -> None:
|
||||
if amount < 1:
|
||||
await ctx.send("Amount must be >= 1", hidden=True)
|
||||
return
|
||||
|
@ -63,7 +66,7 @@ class PurgeCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_messages=True)
|
||||
async def _autopurge_add(self, ctx: SlashContext, channel: TextChannel, delay: int = 30):
|
||||
async def _autopurge_add(self, ctx: SlashContext, channel: TextChannel, delay: int = 30) -> None:
|
||||
if not isinstance(channel, TextChannel):
|
||||
await ctx.send("Channel must be a TextChannel", hidden=True)
|
||||
return
|
||||
|
@ -83,7 +86,7 @@ class PurgeCog(commands.Cog):
|
|||
admin=ctx.author.id,
|
||||
delay=delay,
|
||||
).save()
|
||||
await ctx.send(f"Autopurge set up on {channel.mention}, " + f"delay is {delay} seconds")
|
||||
await ctx.send(f"Autopurge set up on {channel.mention}, delay is {delay} seconds")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
base="autopurge",
|
||||
|
@ -99,7 +102,7 @@ class PurgeCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_messages=True)
|
||||
async def _autopurge_remove(self, ctx: SlashContext, channel: TextChannel):
|
||||
async def _autopurge_remove(self, ctx: SlashContext, channel: TextChannel) -> None:
|
||||
autopurge = Autopurge.objects(guild=ctx.guild.id, channel=channel.id)
|
||||
if not autopurge:
|
||||
await ctx.send("Autopurge does not exist.", hidden=True)
|
||||
|
@ -127,7 +130,7 @@ class PurgeCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_messages=True)
|
||||
async def _autopurge_update(self, ctx: SlashContext, channel: TextChannel, delay: int):
|
||||
async def _autopurge_update(self, ctx: SlashContext, channel: TextChannel, delay: int) -> None:
|
||||
autopurge = Autopurge.objects(guild=ctx.guild.id, channel=channel.id)
|
||||
if not autopurge:
|
||||
await ctx.send("Autopurge does not exist.", hidden=True)
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
"""J.A.R.V.I.S. RolepingCog."""
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
from ButtonPaginator import Paginator
|
||||
from discord import Member
|
||||
from discord import Role
|
||||
from discord.ext.commands import Bot
|
||||
from discord_slash import cog_ext
|
||||
from discord_slash import SlashContext
|
||||
from discord_slash.model import ButtonStyle
|
||||
|
@ -17,7 +19,9 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class RolepingCog(CacheCog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. RolepingCog."""
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -34,7 +38,7 @@ class RolepingCog(CacheCog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _roleping_add(self, ctx: SlashContext, role: Role):
|
||||
async def _roleping_add(self, ctx: SlashContext, role: Role) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=role.id).first()
|
||||
if roleping:
|
||||
await ctx.send(f"Role `{role.name}` already in roleping.", hidden=True)
|
||||
|
@ -62,7 +66,7 @@ class RolepingCog(CacheCog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _roleping_remove(self, ctx: SlashContext, role: Role):
|
||||
async def _roleping_remove(self, ctx: SlashContext, role: Role) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=role.id)
|
||||
if not roleping:
|
||||
await ctx.send("Roleping does not exist", hidden=True)
|
||||
|
@ -76,12 +80,12 @@ class RolepingCog(CacheCog):
|
|||
name="list",
|
||||
description="List all blocklisted roles",
|
||||
)
|
||||
async def _roleping_list(self, ctx: SlashContext):
|
||||
async def _roleping_list(self, ctx: SlashContext) -> None:
|
||||
exists = self.check_cache(ctx)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.send(
|
||||
"Please use existing interaction: " + f"{exists['paginator']._message.jump_url}",
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -176,7 +180,7 @@ class RolepingCog(CacheCog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _roleping_bypass_user(self, ctx: SlashContext, user: Member, rping: Role):
|
||||
async def _roleping_bypass_user(self, ctx: SlashContext, user: Member, rping: Role) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||
if not roleping:
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", hidden=True)
|
||||
|
@ -188,7 +192,7 @@ class RolepingCog(CacheCog):
|
|||
|
||||
if len(roleping.bypass["users"]) == 10:
|
||||
await ctx.send(
|
||||
"Already have 10 users in bypass. " "Please consider using roles for roleping bypass",
|
||||
"Already have 10 users in bypass. Please consider using roles for roleping bypass",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -197,7 +201,7 @@ class RolepingCog(CacheCog):
|
|||
|
||||
if matching_role:
|
||||
await ctx.send(
|
||||
f"{user.mention} already has bypass " f"via {matching_role[0].mention}",
|
||||
f"{user.mention} already has bypass via {matching_role[0].mention}",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -229,7 +233,7 @@ class RolepingCog(CacheCog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _roleping_bypass_role(self, ctx: SlashContext, role: Role, rping: Role):
|
||||
async def _roleping_bypass_role(self, ctx: SlashContext, role: Role, rping: Role) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||
if not roleping:
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", hidden=True)
|
||||
|
@ -241,7 +245,7 @@ class RolepingCog(CacheCog):
|
|||
|
||||
if len(roleping.bypass["roles"]) == 10:
|
||||
await ctx.send(
|
||||
"Already have 10 roles in bypass. " "Please consider consolidating roles for roleping bypass",
|
||||
"Already have 10 roles in bypass. Please consider consolidating roles for roleping bypass",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -273,7 +277,7 @@ class RolepingCog(CacheCog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _roleping_restore_user(self, ctx: SlashContext, user: Member, rping: Role):
|
||||
async def _roleping_restore_user(self, ctx: SlashContext, user: Member, rping: Role) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||
if not roleping:
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", hidden=True)
|
||||
|
@ -310,7 +314,7 @@ class RolepingCog(CacheCog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _roleping_restore_role(self, ctx: SlashContext, role: Role, rping: Role):
|
||||
async def _roleping_restore_role(self, ctx: SlashContext, role: Role, rping: Role) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||
if not roleping:
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", hidden=True)
|
||||
|
@ -322,7 +326,7 @@ class RolepingCog(CacheCog):
|
|||
|
||||
if len(roleping.bypass["roles"]) == 10:
|
||||
await ctx.send(
|
||||
"Already have 10 roles in bypass. " "Please consider consolidating roles for roleping bypass",
|
||||
"Already have 10 roles in bypass. Please consider consolidating roles for roleping bypass",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
"""J.A.R.V.I.S. WarningCog."""
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
from ButtonPaginator import Paginator
|
||||
from discord import User
|
||||
from discord.ext.commands import Bot
|
||||
from discord_slash import cog_ext
|
||||
from discord_slash import SlashContext
|
||||
from discord_slash.model import ButtonStyle
|
||||
|
@ -17,7 +19,9 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class WarningCog(CacheCog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. WarningCog."""
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
|
||||
@cog_ext.cog_slash(
|
||||
|
@ -45,7 +49,7 @@ class WarningCog(CacheCog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _warn(self, ctx: SlashContext, user: User, reason: str, duration: int = 24):
|
||||
async def _warn(self, ctx: SlashContext, user: User, reason: str, duration: int = 24) -> None:
|
||||
if len(reason) > 100:
|
||||
await ctx.send("Reason must be < 100 characters", hidden=True)
|
||||
return
|
||||
|
@ -101,13 +105,13 @@ class WarningCog(CacheCog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _warnings(self, ctx: SlashContext, user: User, active: bool = 1):
|
||||
async def _warnings(self, ctx: SlashContext, user: User, active: bool = 1) -> None:
|
||||
active = bool(active)
|
||||
exists = self.check_cache(ctx, user_id=user.id, active=active)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.send(
|
||||
"Please use existing interaction: " + f"{exists['paginator']._message.jump_url}",
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -138,15 +142,15 @@ class WarningCog(CacheCog):
|
|||
fields.append(
|
||||
Field(
|
||||
name=warn.created_at.strftime("%Y-%m-%d %H:%M:%S UTC"),
|
||||
value=f"{warn.reason}\n" + f"Admin: {admin_name}\n" + "\u200b",
|
||||
value=f"{warn.reason}\nAdmin: {admin_name}\n\u200b",
|
||||
inline=False,
|
||||
)
|
||||
)
|
||||
for i in range(0, len(fields), 5):
|
||||
embed = build_embed(
|
||||
title="Warnings",
|
||||
description=f"{warnings.count()} total | " + f"{active_warns.count()} currently active",
|
||||
fields=fields[i : i + 5],
|
||||
description=f"{warnings.count()} total | {active_warns.count()} currently active",
|
||||
fields=fields[i : i + 5], # noqa: E203
|
||||
)
|
||||
embed.set_author(
|
||||
name=user.name + "#" + user.discriminator,
|
||||
|
@ -170,8 +174,8 @@ class WarningCog(CacheCog):
|
|||
for i in range(0, len(fields), 5):
|
||||
embed = build_embed(
|
||||
title="Warnings",
|
||||
description=f"{warnings.count()} total | " + f"{active_warns.count()} currently active",
|
||||
fields=fields[i : i + 5],
|
||||
description=f"{warnings.count()} total | {active_warns.count()} currently active",
|
||||
fields=fields[i : i + 5], # noqa: E203
|
||||
)
|
||||
embed.set_author(
|
||||
name=user.name + "#" + user.discriminator,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. Autoreact Cog."""
|
||||
import re
|
||||
|
||||
from discord import TextChannel
|
||||
|
@ -13,7 +14,9 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class AutoReactCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. Autoreact Cog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.custom_emote = re.compile(r"^<:\w+:(\d+)>$")
|
||||
|
||||
|
@ -31,7 +34,7 @@ class AutoReactCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _autoreact_create(self, ctx: SlashContext, channel: TextChannel):
|
||||
async def _autoreact_create(self, ctx: SlashContext, channel: TextChannel) -> None:
|
||||
if not isinstance(channel, TextChannel):
|
||||
await ctx.send("Channel must be a text channel", hidden=True)
|
||||
return
|
||||
|
@ -62,7 +65,7 @@ class AutoReactCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _autoreact_delete(self, ctx, channel: TextChannel):
|
||||
async def _autoreact_delete(self, ctx: SlashContext, channel: TextChannel) -> None:
|
||||
exists = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).delete()
|
||||
if exists:
|
||||
await ctx.send(f"Autoreact removed from {channel.mention}")
|
||||
|
@ -89,13 +92,13 @@ class AutoReactCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _autoreact_add(self, ctx, channel: TextChannel, emote: str):
|
||||
async def _autoreact_add(self, ctx: SlashContext, channel: TextChannel, emote: str) -> None:
|
||||
await ctx.defer()
|
||||
custom_emoji = self.custom_emote.match(emote)
|
||||
standard_emoji = emote in emoji_list
|
||||
if not custom_emoji and not standard_emoji:
|
||||
await ctx.send(
|
||||
"Please use either an emote from this server" + " or a unicode emoji.",
|
||||
"Please use either an emote from this server or a unicode emoji.",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -106,7 +109,7 @@ class AutoReactCog(commands.Cog):
|
|||
return
|
||||
exists = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
|
||||
if not exists:
|
||||
await ctx.send("Please create autoreact first with " + f"/autoreact create {channel.mention}")
|
||||
await ctx.send(f"Please create autoreact first with /autoreact create {channel.mention}")
|
||||
return
|
||||
if emote in exists.reactions:
|
||||
await ctx.send(
|
||||
|
@ -116,7 +119,7 @@ class AutoReactCog(commands.Cog):
|
|||
return
|
||||
if len(exists.reactions) >= 5:
|
||||
await ctx.send(
|
||||
"Max number of reactions hit. " + "Remove a different one to add this one",
|
||||
"Max number of reactions hit. Remove a different one to add this one",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -144,11 +147,11 @@ class AutoReactCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _autoreact_remove(self, ctx, channel: TextChannel, emote: str):
|
||||
async def _autoreact_remove(self, ctx: SlashContext, channel: TextChannel, emote: str) -> None:
|
||||
exists = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
|
||||
if not exists:
|
||||
await ctx.send(
|
||||
"Please create autoreact first with " + f"/autoreact create {channel.mention}",
|
||||
f"Please create autoreact first with /autoreact create {channel.mention}",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -176,11 +179,11 @@ class AutoReactCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _autoreact_list(self, ctx, channel: TextChannel):
|
||||
async def _autoreact_list(self, ctx: SlashContext, channel: TextChannel) -> None:
|
||||
exists = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
|
||||
if not exists:
|
||||
await ctx.send(
|
||||
"Please create autoreact first with " + f"/autoreact create {channel.mention}",
|
||||
f"Please create autoreact first with /autoreact create {channel.mention}",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -192,5 +195,6 @@ class AutoReactCog(commands.Cog):
|
|||
await ctx.send(message)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add AutoReactCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(AutoReactCog(bot))
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
"""J.A.R.V.I.S. Complete the Code 2 Cog."""
|
||||
import re
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
import aiohttp
|
||||
import pymongo
|
||||
from ButtonPaginator import Paginator
|
||||
from discord import Member
|
||||
from discord import User
|
||||
from discord.commands.ext import Bot
|
||||
from discord.ext import commands
|
||||
from discord.ext.tasks import loop
|
||||
from discord.utils import find
|
||||
from discord_slash import cog_ext
|
||||
from discord_slash import SlashContext
|
||||
from discord_slash.model import ButtonStyle
|
||||
|
@ -29,11 +28,16 @@ invites = re.compile(
|
|||
|
||||
|
||||
class CTCCog(CacheCog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. Complete the Code 2 Cog."""
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
self._session = aiohttp.ClientSession()
|
||||
self.url = "https://completethecodetwo.cards/pw"
|
||||
|
||||
def __del__(self):
|
||||
self._session.close()
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
base="ctc2",
|
||||
name="about",
|
||||
|
@ -41,7 +45,7 @@ class CTCCog(CacheCog):
|
|||
guild_ids=guild_ids,
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _about(self, ctx):
|
||||
async def _about(self, ctx: SlashContext) -> None:
|
||||
await ctx.send("See https://completethecode.com for more information")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -51,22 +55,22 @@ class CTCCog(CacheCog):
|
|||
guild_ids=guild_ids,
|
||||
)
|
||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||
async def _pw(self, ctx: SlashContext, guess: str):
|
||||
async def _pw(self, ctx: SlashContext, guess: str) -> None:
|
||||
if len(guess) > 800:
|
||||
await ctx.send(
|
||||
"Listen here, dipshit. Don't be like " + "<@256110768724901889>. Make your guesses < 800 characters.",
|
||||
"Listen here, dipshit. Don't be like <@256110768724901889>. Make your guesses < 800 characters.",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
elif not valid.fullmatch(guess):
|
||||
await ctx.send(
|
||||
"Listen here, dipshit. Don't be like " + "<@256110768724901889>. Make your guesses *readable*.",
|
||||
"Listen here, dipshit. Don't be like <@256110768724901889>. Make your guesses *readable*.",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
elif invites.search(guess):
|
||||
await ctx.send(
|
||||
"Listen here, dipshit. " + "No using this to bypass sending invite links.",
|
||||
"Listen here, dipshit. No using this to bypass sending invite links.",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -90,12 +94,12 @@ class CTCCog(CacheCog):
|
|||
guild_ids=guild_ids,
|
||||
)
|
||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||
async def _guesses(self, ctx: SlashContext):
|
||||
async def _guesses(self, ctx: SlashContext) -> None:
|
||||
exists = self.check_cache(ctx)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.send(
|
||||
"Please use existing interaction: " + f"{exists['paginator']._message.jump_url}",
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -124,7 +128,7 @@ class CTCCog(CacheCog):
|
|||
embed = build_embed(
|
||||
title="completethecodetwo.cards guesses",
|
||||
description=f"{len(fields)} guesses so far",
|
||||
fields=fields[i : i + 5],
|
||||
fields=fields[i : i + 5], # noqa: E203
|
||||
url="https://completethecodetwo.cards",
|
||||
)
|
||||
embed.set_thumbnail(url="https://dev.zevaryx.com/db_logo.png")
|
||||
|
@ -158,5 +162,6 @@ class CTCCog(CacheCog):
|
|||
await paginator.start()
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: Bot) -> None:
|
||||
"""Add CTCCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(CTCCog(bot))
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
"""J.A.R.V.I.S. dbrand cog."""
|
||||
import re
|
||||
|
||||
import aiohttp
|
||||
from discord.ext import commands
|
||||
from discord_slash import cog_ext
|
||||
from discord_slash import SlashContext
|
||||
from discord_slash.utils.manage_commands import create_option
|
||||
|
||||
from jarvis.config import get_config
|
||||
|
@ -20,7 +22,7 @@ class DbrandCog(commands.Cog):
|
|||
Mostly support functions. Credit @cpixl for the shipping API
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.base_url = "https://dbrand.com/"
|
||||
self._session = aiohttp.ClientSession()
|
||||
|
@ -28,6 +30,9 @@ class DbrandCog(commands.Cog):
|
|||
self.api_url = get_config().urls["dbrand_shipping"]
|
||||
self.cache = {}
|
||||
|
||||
def __del__(self):
|
||||
self._session.close()
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
base="db",
|
||||
name="skin",
|
||||
|
@ -35,7 +40,7 @@ class DbrandCog(commands.Cog):
|
|||
description="See what skins are available",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _skin(self, ctx):
|
||||
async def _skin(self, ctx: SlashContext) -> None:
|
||||
await ctx.send(self.base_url + "shop/skins")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -45,7 +50,7 @@ class DbrandCog(commands.Cog):
|
|||
description="Get some robot camo. Make Tony Stark proud",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _camo(self, ctx):
|
||||
async def _camo(self, ctx: SlashContext) -> None:
|
||||
await ctx.send(self.base_url + "shop/special-edition/robot-camo")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -55,7 +60,7 @@ class DbrandCog(commands.Cog):
|
|||
description="See devices with Grip support",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _grip(self, ctx):
|
||||
async def _grip(self, ctx: SlashContext) -> None:
|
||||
await ctx.send(self.base_url + "shop/grip/#grip-devices")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -65,7 +70,7 @@ class DbrandCog(commands.Cog):
|
|||
description="Contact support",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _contact(self, ctx):
|
||||
async def _contact(self, ctx: SlashContext) -> None:
|
||||
await ctx.send("Contact dbrand support here: " + self.base_url + "contact")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -75,7 +80,7 @@ class DbrandCog(commands.Cog):
|
|||
description="Contact support",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _support(self, ctx):
|
||||
async def _support(self, ctx: SlashContext) -> None:
|
||||
await ctx.send("Contact dbrand support here: " + self.base_url + "contact")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -85,7 +90,7 @@ class DbrandCog(commands.Cog):
|
|||
description="Get your order status",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _orderstat(self, ctx):
|
||||
async def _orderstat(self, ctx: SlashContext) -> None:
|
||||
await ctx.send(self.base_url + "order-status")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -95,7 +100,7 @@ class DbrandCog(commands.Cog):
|
|||
description="Get your order status",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _orders(self, ctx):
|
||||
async def _orders(self, ctx: SlashContext) -> None:
|
||||
await ctx.send(self.base_url + "order-status")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -105,7 +110,7 @@ class DbrandCog(commands.Cog):
|
|||
description="dbrand status",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _status(self, ctx):
|
||||
async def _status(self, ctx: SlashContext) -> None:
|
||||
await ctx.send(self.base_url + "status")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -115,7 +120,7 @@ class DbrandCog(commands.Cog):
|
|||
description="Give us your money!",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _buy(self, ctx):
|
||||
async def _buy(self, ctx: SlashContext) -> None:
|
||||
await ctx.send("Give us your money! " + self.base_url + "shop")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -125,7 +130,7 @@ class DbrandCog(commands.Cog):
|
|||
description="(not) extortion",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _extort(self, ctx):
|
||||
async def _extort(self, ctx: SlashContext) -> None:
|
||||
await ctx.send("Be (not) extorted here: " + self.base_url + "not-extortion")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -135,7 +140,7 @@ class DbrandCog(commands.Cog):
|
|||
guild_ids=guild_ids,
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _wallpapers(self, ctx):
|
||||
async def _wallpapers(self, ctx: SlashContext) -> None:
|
||||
await ctx.send("Get robot camo wallpapers here: https://db.io/wallpapers")
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -147,7 +152,7 @@ class DbrandCog(commands.Cog):
|
|||
(
|
||||
create_option(
|
||||
name="search",
|
||||
description="Country search query (2 character code, " + "country name, emoji)",
|
||||
description="Country search query (2 character code, country name, emoji)",
|
||||
option_type=3,
|
||||
required=True,
|
||||
)
|
||||
|
@ -155,7 +160,7 @@ class DbrandCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||
async def _shipping(self, ctx, *, search: str):
|
||||
async def _shipping(self, ctx: SlashContext, search: str) -> None:
|
||||
await ctx.defer()
|
||||
if not re.match(r"^[A-Z- ]+$", search, re.IGNORECASE):
|
||||
if re.match(
|
||||
|
@ -203,10 +208,12 @@ class DbrandCog(commands.Cog):
|
|||
)
|
||||
country = "-".join(x for x in data["country"].split(" ") if x != "the")
|
||||
country_urlsafe = country.replace("-", "%20")
|
||||
description = "Click the link above to " + "see shipping time to {data['country']}."
|
||||
description += "\n[View all shipping destinations]" + "(https://dbrand.com/shipping)"
|
||||
description += " | [Check shipping status]"
|
||||
description += "(https://dbrand.com/status" + f"#main-content:~:text={country_urlsafe})"
|
||||
description = (
|
||||
f"Click the link above to see shipping time to {data['country']}."
|
||||
"\n[View all shipping destinations](https://dbrand.com/shipping)"
|
||||
" | [Check shipping status]"
|
||||
f"(https://dbrand.com/status#main-content:~:text={country_urlsafe})"
|
||||
)
|
||||
embed = build_embed(
|
||||
title="Shipping to {}".format(data["country"]),
|
||||
description=description,
|
||||
|
@ -223,8 +230,9 @@ class DbrandCog(commands.Cog):
|
|||
elif not data["is_valid"]:
|
||||
embed = build_embed(
|
||||
title="Check Shipping Times",
|
||||
description="Country not found.\nYou can [view all shipping "
|
||||
+ "destinations here](https://dbrand.com/shipping)",
|
||||
description=(
|
||||
"Country not found.\nYou can [view all shipping " "destinations here](https://dbrand.com/shipping)"
|
||||
),
|
||||
fields=[],
|
||||
url="https://dbrand.com/shipping",
|
||||
color="#FFBB00",
|
||||
|
@ -238,9 +246,11 @@ class DbrandCog(commands.Cog):
|
|||
elif not data["shipping_available"]:
|
||||
embed = build_embed(
|
||||
title="Shipping to {}".format(data["country"]),
|
||||
description="No shipping available.\nTime to move to a country"
|
||||
+ " that has shipping available.\nYou can [find a new country "
|
||||
+ "to live in here](https://dbrand.com/shipping)",
|
||||
description=(
|
||||
"No shipping available.\nTime to move to a country"
|
||||
" that has shipping available.\nYou can [find a new country "
|
||||
"to live in here](https://dbrand.com/shipping)"
|
||||
),
|
||||
fields=[],
|
||||
url="https://dbrand.com/shipping",
|
||||
color="#FFBB00",
|
||||
|
@ -253,5 +263,6 @@ class DbrandCog(commands.Cog):
|
|||
await ctx.send(embed=embed)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add dbrandcog to J.A.R.V.I.S."""
|
||||
bot.add_cog(DbrandCog(bot))
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
"""J.A.R.V.I.S. Developer Cog."""
|
||||
import base64
|
||||
import hashlib
|
||||
import re
|
||||
import subprocess
|
||||
import subprocess # noqa: S404
|
||||
import uuid as uuidpy
|
||||
from typing import Any
|
||||
from typing import Union
|
||||
|
||||
import ulid as ulidpy
|
||||
from bson import ObjectId
|
||||
from discord.ext import commands
|
||||
from discord_slash import cog_ext
|
||||
from discord_slash import SlashContext
|
||||
from discord_slash.utils.manage_commands import create_choice
|
||||
from discord_slash.utils.manage_commands import create_option
|
||||
|
||||
|
@ -18,13 +22,13 @@ from jarvis.utils.field import Field
|
|||
supported_hashes = {x for x in hashlib.algorithms_guaranteed if "shake" not in x}
|
||||
|
||||
OID_VERIFY = re.compile(r"^([1-9][0-9]{0,3}|0)(\.([1-9][0-9]{0,3}|0)){5,13}$")
|
||||
URL_VERIFY = re.compile(r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]" + r"|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+")
|
||||
URL_VERIFY = re.compile(r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+")
|
||||
DN_VERIFY = re.compile(
|
||||
r"^(?:(?P<cn>CN=(?P<name>[^,]*)),)" + r"?(?:(?P<path>(?:(?:CN|OU)=[^,]+,?)+),)" + r"?(?P<domain>(?:DC=[^,]+,?)+)$"
|
||||
r"^(?:(?P<cn>CN=(?P<name>[^,]*)),)?(?:(?P<path>(?:(?:CN|OU)=[^,]+,?)+),)?(?P<domain>(?:DC=[^,]+,?)+)$"
|
||||
)
|
||||
ULID_VERIFY = re.compile(r"^[0-9a-z]{26}$", re.IGNORECASE)
|
||||
UUID_VERIFY = re.compile(
|
||||
("[a-f0-9]{8}-" + "[a-f0-9]{4}-" + "[1-5]" + "[a-f0-9]{3}-" + "[89ab][a-f0-9]{3}-" + "[a-f0-9]{12}$"),
|
||||
r"[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
@ -36,9 +40,8 @@ invites = re.compile(
|
|||
UUID_GET = {3: uuidpy.uuid3, 5: uuidpy.uuid5}
|
||||
|
||||
|
||||
def hash_obj(hash, data, text: bool = True) -> str:
|
||||
"""
|
||||
Hash data with hash object
|
||||
def hash_obj(hash: Any, data: Union[str, bytes], text: bool = True) -> str:
|
||||
"""Hash data with hash object.
|
||||
|
||||
Data can be text or binary
|
||||
"""
|
||||
|
@ -48,14 +51,16 @@ def hash_obj(hash, data, text: bool = True) -> str:
|
|||
BSIZE = 65536
|
||||
block_idx = 0
|
||||
while block_idx * BSIZE < len(data):
|
||||
block = data[BSIZE * block_idx : BSIZE * (block_idx + 1)]
|
||||
block = data[BSIZE * block_idx : BSIZE * (block_idx + 1)] # noqa: E203
|
||||
hash.update(block)
|
||||
block_idx += 1
|
||||
return hash.hexdigest()
|
||||
|
||||
|
||||
class DevCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. Developer Cog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@cog_ext.cog_slash(
|
||||
|
@ -78,7 +83,7 @@ class DevCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||
async def _hash(self, ctx, method: str, data: str):
|
||||
async def _hash(self, ctx: SlashContext, method: str, data: str) -> None:
|
||||
if not data:
|
||||
await ctx.send(
|
||||
"No data to hash",
|
||||
|
@ -119,7 +124,7 @@ class DevCog(commands.Cog):
|
|||
),
|
||||
],
|
||||
)
|
||||
async def _uuid(self, ctx, version: str, data: str = None):
|
||||
async def _uuid(self, ctx: SlashContext, version: str, data: str = None) -> None:
|
||||
version = int(version)
|
||||
if version in [3, 5] and not data:
|
||||
await ctx.send(f"UUID{version} requires data.", hidden=True)
|
||||
|
@ -143,8 +148,7 @@ class DevCog(commands.Cog):
|
|||
description="Generate an ObjectID",
|
||||
)
|
||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||
async def _objectid(self, ctx):
|
||||
"""Generates new bson.ObjectId"""
|
||||
async def _objectid(self, ctx: SlashContext) -> None:
|
||||
await ctx.send(f"ObjectId: `{str(ObjectId())}`")
|
||||
|
||||
@cog_ext.cog_slash(
|
||||
|
@ -152,8 +156,7 @@ class DevCog(commands.Cog):
|
|||
description="Generate a ULID",
|
||||
)
|
||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||
async def _ulid(self, ctx):
|
||||
"""Generates a new ULID"""
|
||||
async def _ulid(self, ctx: SlashContext) -> None:
|
||||
await ctx.send(f"ULID: `{ulidpy.new().str}`")
|
||||
|
||||
@cog_ext.cog_slash(
|
||||
|
@ -161,8 +164,7 @@ class DevCog(commands.Cog):
|
|||
description="Convert a UUID to a ULID",
|
||||
)
|
||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||
async def _uuid2ulid(self, ctx: commands.Context, uuid):
|
||||
"""Converts a UUID to a ULID"""
|
||||
async def _uuid2ulid(self, ctx: SlashContext, uuid: str) -> None:
|
||||
if UUID_VERIFY.match(uuid):
|
||||
u = ulidpy.parse(uuid)
|
||||
await ctx.send(f"ULID: `{u.str}`")
|
||||
|
@ -174,8 +176,7 @@ class DevCog(commands.Cog):
|
|||
description="Convert a ULID to a UUID",
|
||||
)
|
||||
@commands.cooldown(1, 2, commands.BucketType.user)
|
||||
async def _ulid2uuid(self, ctx: commands.Context, ulid):
|
||||
"""Converts a ULID to a UUID"""
|
||||
async def _ulid2uuid(self, ctx: SlashContext, ulid: str) -> None:
|
||||
if ULID_VERIFY.match(ulid):
|
||||
ulid = ulidpy.parse(ulid)
|
||||
await ctx.send(f"UUID: `{ulid.uuid}`")
|
||||
|
@ -203,8 +204,7 @@ class DevCog(commands.Cog):
|
|||
),
|
||||
],
|
||||
)
|
||||
async def _encode(self, ctx, method: str, data: str):
|
||||
"""Encodes text with specified encoding method"""
|
||||
async def _encode(self, ctx: SlashContext, method: str, data: str) -> None:
|
||||
method = getattr(base64, method + "encode")
|
||||
await ctx.send(f"`{method(data.encode('UTF-8')).decode('UTF-8')}`")
|
||||
|
||||
|
@ -227,8 +227,7 @@ class DevCog(commands.Cog):
|
|||
),
|
||||
],
|
||||
)
|
||||
async def _decode(self, ctx, method: str, data: str):
|
||||
"""Decodes text with specified encoding method"""
|
||||
async def _decode(self, ctx: SlashContext, method: str, data: str) -> None:
|
||||
method = getattr(base64, method + "decode")
|
||||
decoded = method(data.encode("UTF-8")).decode("UTF-8")
|
||||
if invites.search(decoded):
|
||||
|
@ -244,10 +243,11 @@ class DevCog(commands.Cog):
|
|||
description="Get J.A.R.V.I.S. lines of code",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _cloc(self, ctx):
|
||||
output = subprocess.check_output(["tokei", "-C", "--sort", "code"]).decode("UTF-8")
|
||||
async def _cloc(self, ctx: SlashContext) -> None:
|
||||
output = subprocess.check_output(["tokei", "-C", "--sort", "code"]).decode("UTF-8") # noqa: S603, S607
|
||||
await ctx.send(f"```\n{output}\n```")
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add DevCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(DevCog(bot))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. error handling cog."""
|
||||
from discord.ext import commands
|
||||
from discord_slash import SlashContext
|
||||
|
||||
|
@ -5,11 +6,14 @@ from jarvis import slash
|
|||
|
||||
|
||||
class ErrorHandlerCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. error handling cog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_command_error(self, ctx: commands.Context, error):
|
||||
async def on_command_error(self, ctx: commands.Context, error: Exception) -> None:
|
||||
"""d.py on_command_error override."""
|
||||
if isinstance(error, commands.errors.MissingPermissions):
|
||||
await ctx.send("I'm afraid I can't let you do that.")
|
||||
elif isinstance(error, commands.errors.CommandNotFound):
|
||||
|
@ -23,7 +27,8 @@ class ErrorHandlerCog(commands.Cog):
|
|||
ctx.command.reset_cooldown(ctx)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_slash_command_error(self, ctx: SlashContext, error):
|
||||
async def on_slash_command_error(self, ctx: SlashContext, error: Exception) -> None:
|
||||
"""discord_slash on_slash_command_error override."""
|
||||
if isinstance(error, commands.errors.MissingPermissions) or isinstance(error, commands.errors.CheckFailure):
|
||||
await ctx.send("I'm afraid I can't let you do that.", hidden=True)
|
||||
elif isinstance(error, commands.errors.CommandNotFound):
|
||||
|
@ -41,5 +46,6 @@ class ErrorHandlerCog(commands.Cog):
|
|||
slash.commands[ctx.command].reset_cooldown(ctx)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add ErrorHandlerCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(ErrorHandlerCog(bot))
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
"""J.A.R.V.I.S. GitLab Cog."""
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
import gitlab
|
||||
from ButtonPaginator import Paginator
|
||||
from discord import Embed
|
||||
from discord.ext import commands
|
||||
from discord.ext.tasks import loop
|
||||
from discord.utils import find
|
||||
from discord_slash import cog_ext
|
||||
from discord_slash import SlashContext
|
||||
from discord_slash.model import ButtonStyle
|
||||
|
@ -21,7 +21,9 @@ guild_ids = [862402786116763668]
|
|||
|
||||
|
||||
class GitlabCog(CacheCog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. GitLab Cog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
super().__init__(bot)
|
||||
config = get_config()
|
||||
self._gitlab = gitlab.Gitlab("https://git.zevaryx.com", private_token=config.gitlab_token)
|
||||
|
@ -35,7 +37,7 @@ class GitlabCog(CacheCog):
|
|||
guild_ids=guild_ids,
|
||||
options=[create_option(name="id", description="Issue ID", option_type=4, required=True)],
|
||||
)
|
||||
async def _issue(self, ctx: SlashContext, id: int):
|
||||
async def _issue(self, ctx: SlashContext, id: int) -> None:
|
||||
try:
|
||||
issue = self.project.issues.get(int(id))
|
||||
except gitlab.exceptions.GitlabGetError:
|
||||
|
@ -69,7 +71,7 @@ class GitlabCog(CacheCog):
|
|||
fields.append(
|
||||
Field(
|
||||
name="Milestone",
|
||||
value=f"[{issue.milestone['title']}]" + f"({issue.milestone['web_url']})",
|
||||
value=f"[{issue.milestone['title']}]({issue.milestone['web_url']})",
|
||||
inline=False,
|
||||
)
|
||||
)
|
||||
|
@ -87,7 +89,7 @@ class GitlabCog(CacheCog):
|
|||
icon_url=issue.author["avatar_url"],
|
||||
url=issue.author["web_url"],
|
||||
)
|
||||
embed.set_thumbnail(url="https://about.gitlab.com/images" + "/press/logo/png/gitlab-icon-rgb.png")
|
||||
embed.set_thumbnail(url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png")
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -104,7 +106,7 @@ class GitlabCog(CacheCog):
|
|||
)
|
||||
],
|
||||
)
|
||||
async def _milestone(self, ctx: SlashContext, id: int):
|
||||
async def _milestone(self, ctx: SlashContext, id: int) -> None:
|
||||
try:
|
||||
milestone = self.project.milestones.get(int(id))
|
||||
except gitlab.exceptions.GitlabGetError:
|
||||
|
@ -142,9 +144,9 @@ class GitlabCog(CacheCog):
|
|||
embed.set_author(
|
||||
name="J.A.R.V.I.S.",
|
||||
url="https://git.zevaryx.com/jarvis",
|
||||
icon_url="https://git.zevaryx.com/uploads/-" + "/system/user/avatar/11/avatar.png",
|
||||
icon_url="https://git.zevaryx.com/uploads/-/system/user/avatar/11/avatar.png",
|
||||
)
|
||||
embed.set_thumbnail(url="https://about.gitlab.com/images" + "/press/logo/png/gitlab-icon-rgb.png")
|
||||
embed.set_thumbnail(url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png")
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -161,7 +163,7 @@ class GitlabCog(CacheCog):
|
|||
)
|
||||
],
|
||||
)
|
||||
async def _mergerequest(self, ctx: SlashContext, id: int):
|
||||
async def _mergerequest(self, ctx: SlashContext, id: int) -> None:
|
||||
try:
|
||||
mr = self.project.mergerequests.get(int(id))
|
||||
except gitlab.exceptions.GitlabGetError:
|
||||
|
@ -201,7 +203,7 @@ class GitlabCog(CacheCog):
|
|||
fields.append(
|
||||
Field(
|
||||
name="Milestone",
|
||||
value=f"[{mr.milestone['title']}]" + f"({mr.milestone['web_url']})",
|
||||
value=f"[{mr.milestone['title']}]({mr.milestone['web_url']})",
|
||||
inline=False,
|
||||
)
|
||||
)
|
||||
|
@ -219,10 +221,11 @@ class GitlabCog(CacheCog):
|
|||
icon_url=mr.author["avatar_url"],
|
||||
url=mr.author["web_url"],
|
||||
)
|
||||
embed.set_thumbnail(url="https://about.gitlab.com/images" + "/press/logo/png/gitlab-icon-rgb.png")
|
||||
embed.set_thumbnail(url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png")
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
def build_embed_page(self, api_list: list, t_state: str, name: str):
|
||||
def build_embed_page(self, api_list: list, t_state: str, name: str) -> Embed:
|
||||
"""Build an embed page for the paginator."""
|
||||
title = ""
|
||||
if t_state:
|
||||
title = f"{t_state} "
|
||||
|
@ -241,14 +244,14 @@ class GitlabCog(CacheCog):
|
|||
title=title,
|
||||
description="",
|
||||
fields=fields,
|
||||
url="https://git.zevaryx.com/stark-industries/j.a.r.v.i.s./" + f"{name.replace(' ', '_')}s",
|
||||
url=f"https://git.zevaryx.com/stark-industries/j.a.r.v.i.s./{name.replace(' ', '_')}s",
|
||||
)
|
||||
embed.set_author(
|
||||
name="J.A.R.V.I.S.",
|
||||
url="https://git.zevaryx.com/jarvis",
|
||||
icon_url="https://git.zevaryx.com/uploads/-" + "/system/user/avatar/11/avatar.png",
|
||||
icon_url="https://git.zevaryx.com/uploads/-/system/user/avatar/11/avatar.png",
|
||||
)
|
||||
embed.set_thumbnail(url="https://about.gitlab.com/images" + "/press/logo/png/gitlab-icon-rgb.png")
|
||||
embed.set_thumbnail(url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png")
|
||||
return embed
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -270,7 +273,7 @@ class GitlabCog(CacheCog):
|
|||
)
|
||||
],
|
||||
)
|
||||
async def _issues(self, ctx: SlashContext, state: str = "opened"):
|
||||
async def _issues(self, ctx: SlashContext, state: str = "opened") -> None:
|
||||
exists = self.check_cache(ctx, state=state)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
|
@ -311,7 +314,7 @@ class GitlabCog(CacheCog):
|
|||
pages = []
|
||||
t_state = t_state[0].upper() + t_state[1:]
|
||||
for i in range(0, len(issues), 5):
|
||||
pages.append(self.build_embed_page(issues[i : i + 5], t_state=t_state, name="issue"))
|
||||
pages.append(self.build_embed_page(issues[i : i + 5], t_state=t_state, name="issue")) # noqa: E203
|
||||
|
||||
paginator = Paginator(
|
||||
bot=self.bot,
|
||||
|
@ -357,7 +360,7 @@ class GitlabCog(CacheCog):
|
|||
)
|
||||
],
|
||||
)
|
||||
async def _mergerequests(self, ctx: SlashContext, state: str = "opened"):
|
||||
async def _mergerequests(self, ctx: SlashContext, state: str = "opened") -> None:
|
||||
exists = self.check_cache(ctx, state=state)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
|
@ -398,7 +401,7 @@ class GitlabCog(CacheCog):
|
|||
pages = []
|
||||
t_state = t_state[0].upper() + t_state[1:]
|
||||
for i in range(0, len(merges), 5):
|
||||
pages.append(self.build_embed_page(merges[i : i + 5], t_state=t_state, name="merge request"))
|
||||
pages.append(self.build_embed_page(merges[i : i + 5], t_state=t_state, name="merge request")) # noqa: E203
|
||||
|
||||
paginator = Paginator(
|
||||
bot=self.bot,
|
||||
|
@ -430,12 +433,12 @@ class GitlabCog(CacheCog):
|
|||
description="Get open issues from GitLab",
|
||||
guild_ids=guild_ids,
|
||||
)
|
||||
async def _milestones(self, ctx: SlashContext):
|
||||
async def _milestones(self, ctx: SlashContext) -> None:
|
||||
exists = self.check_cache(ctx)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.send(
|
||||
"Please use existing interaction: " + f"{exists['paginator']._message.jump_url}",
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -463,7 +466,7 @@ class GitlabCog(CacheCog):
|
|||
|
||||
pages = []
|
||||
for i in range(0, len(milestones), 5):
|
||||
pages.append(self.build_embed_page(milestones[i : i + 5], t_state=None, name="milestone"))
|
||||
pages.append(self.build_embed_page(milestones[i : i + 5], t_state=None, name="milestone")) # noqa: E203
|
||||
|
||||
paginator = Paginator(
|
||||
bot=self.bot,
|
||||
|
@ -489,6 +492,7 @@ class GitlabCog(CacheCog):
|
|||
await paginator.start()
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add GitlabCog to J.A.R.V.I.S. if Gitlab token exists."""
|
||||
if get_config().gitlab_token:
|
||||
bot.add_cog(GitlabCog(bot))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. image processing cog."""
|
||||
import re
|
||||
from io import BytesIO
|
||||
|
||||
|
@ -20,19 +21,22 @@ class ImageCog(commands.Cog):
|
|||
May be categorized under util later
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self._session = aiohttp.ClientSession()
|
||||
self.tgt_match = re.compile(r"([0-9]*\.?[0-9]*?) ?([KMGTP]?B)", re.IGNORECASE)
|
||||
|
||||
async def _resize(self, ctx, target: str, url: str = None):
|
||||
def __del__(self):
|
||||
self._session.close()
|
||||
|
||||
async def _resize(self, ctx: commands.Context, target: str, url: str = None) -> None:
|
||||
if not target:
|
||||
await ctx.send("Missing target size, i.e. 200KB.")
|
||||
return
|
||||
|
||||
tgt = self.tgt_match.match(target)
|
||||
if not tgt:
|
||||
await ctx.send("Invalid target format ({}).".format(target) + " Expected format like 200KB")
|
||||
await ctx.send(f"Invalid target format ({target}). Expected format like 200KB")
|
||||
return
|
||||
|
||||
tgt_size = unconvert_bytesize(float(tgt.groups()[0]), tgt.groups()[1])
|
||||
|
@ -95,9 +99,10 @@ class ImageCog(commands.Cog):
|
|||
|
||||
@commands.command(name="resize", help="Resize an image")
|
||||
@commands.cooldown(1, 60, commands.BucketType.user)
|
||||
async def _resize_pref(self, ctx, target: str, url: str = None):
|
||||
async def _resize_pref(self, ctx: commands.Context, target: str, url: str = None) -> None:
|
||||
await self._resize(ctx, target, url)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add ImageCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(ImageCog(bot))
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
"""J.A.R.V.I.S. Jokes module."""
|
||||
import html
|
||||
import re
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
from random import randint
|
||||
from secrets import randint
|
||||
|
||||
from discord.ext import commands
|
||||
from discord_slash import cog_ext
|
||||
|
@ -20,7 +21,7 @@ class JokeCog(commands.Cog):
|
|||
May adapt over time to create jokes using machine learning
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
# TODO: Make this a command group with subcommands
|
||||
|
@ -29,8 +30,8 @@ class JokeCog(commands.Cog):
|
|||
description="Hear a joke",
|
||||
)
|
||||
@commands.cooldown(1, 10, commands.BucketType.channel)
|
||||
async def _joke(self, ctx: SlashContext, id: str = None):
|
||||
"""Get a joke from the database"""
|
||||
async def _joke(self, ctx: SlashContext, id: str = None) -> None:
|
||||
"""Get a joke from the database."""
|
||||
try:
|
||||
if randint(1, 100_000) == 5779 and id is None:
|
||||
await ctx.send(f"<@{ctx.message.author.id}>")
|
||||
|
@ -109,5 +110,6 @@ class JokeCog(commands.Cog):
|
|||
# await ctx.send(f"**{result['title']}**\n\n{result['body']}")
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add JokeCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(JokeCog(bot))
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
"""J.A.R.V.I.S. Modlog Cogs."""
|
||||
from discord.ext.commands import Bot
|
||||
|
||||
from jarvis.cogs.modlog import command
|
||||
from jarvis.cogs.modlog import member
|
||||
from jarvis.cogs.modlog import message
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: Bot) -> None:
|
||||
"""Add modlog cogs to J.A.R.V.I.S."""
|
||||
bot.add_cog(command.ModlogCommandCog(bot))
|
||||
bot.add_cog(member.ModlogMemberCog(bot))
|
||||
bot.add_cog(message.ModlogMessageCog(bot))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. ModlogCommandCog."""
|
||||
from discord import DMChannel
|
||||
from discord.ext import commands
|
||||
from discord_slash import SlashContext
|
||||
|
@ -8,11 +9,14 @@ from jarvis.utils.field import Field
|
|||
|
||||
|
||||
class ModlogCommandCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. ModlogCommandCog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_slash_command(self, ctx: SlashContext):
|
||||
async def on_slash_command(self, ctx: SlashContext) -> None:
|
||||
"""Process on_slash_command events."""
|
||||
if not isinstance(ctx.channel, DMChannel) and ctx.name not in ["pw"]:
|
||||
modlog = Setting.objects(guild=ctx.guild.id, setting="modlog").first()
|
||||
if modlog:
|
||||
|
@ -41,5 +45,5 @@ class ModlogCommandCog(commands.Cog):
|
|||
name=ctx.author.name,
|
||||
icon_url=ctx.author.avatar_url,
|
||||
)
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator}" + f" | {ctx.author.id}")
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} | {ctx.author.id}")
|
||||
await channel.send(embed=embed)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. ModlogMemberCog."""
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
@ -19,12 +20,15 @@ from jarvis.utils.field import Field
|
|||
|
||||
|
||||
class ModlogMemberCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. ModlogMemberCog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.cache = []
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_member_ban(self, guild: discord.Guild, user: discord.User):
|
||||
async def on_member_ban(self, guild: discord.Guild, user: discord.User) -> None:
|
||||
"""Process on_member_ban events."""
|
||||
modlog = Setting.objects(guild=guild.id, setting="modlog").first()
|
||||
if modlog:
|
||||
channel = guild.get_channel(modlog.value)
|
||||
|
@ -61,7 +65,8 @@ class ModlogMemberCog(commands.Cog):
|
|||
await channel.send(embed=embed)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_member_unban(self, guild: discord.Guild, user: discord.User):
|
||||
async def on_member_unban(self, guild: discord.Guild, user: discord.User) -> None:
|
||||
"""Process on_member_unban events."""
|
||||
modlog = Setting.objects(guild=guild.id, setting="modlog").first()
|
||||
if modlog:
|
||||
channel = guild.get_channel(modlog.value)
|
||||
|
@ -96,7 +101,8 @@ class ModlogMemberCog(commands.Cog):
|
|||
await channel.send(embed=embed)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_member_remove(self, user: discord.Member):
|
||||
async def on_member_remove(self, user: discord.Member) -> None:
|
||||
"""Process on_member_remove events."""
|
||||
modlog = Setting.objects(guild=user.guild.id, setting="modlog").first()
|
||||
if modlog:
|
||||
channel = user.guild.get_channel(modlog.value)
|
||||
|
@ -140,7 +146,8 @@ class ModlogMemberCog(commands.Cog):
|
|||
|
||||
await channel.send(embed=embed)
|
||||
|
||||
async def process_mute(self, before, after) -> discord.Embed:
|
||||
async def process_mute(self, before: discord.Member, after: discord.Member) -> discord.Embed:
|
||||
"""Process mute event."""
|
||||
await asyncio.sleep(0.5) # Need to wait for audit log
|
||||
auditlog = await before.guild.audit_logs(
|
||||
limit=50,
|
||||
|
@ -171,7 +178,8 @@ class ModlogMemberCog(commands.Cog):
|
|||
desc=f"{before.mention} was muted",
|
||||
)
|
||||
|
||||
async def process_unmute(self, before, after) -> discord.Embed:
|
||||
async def process_unmute(self, before: discord.Member, after: discord.Member) -> discord.Embed:
|
||||
"""Process unmute event."""
|
||||
await asyncio.sleep(0.5) # Need to wait for audit log
|
||||
auditlog = await before.guild.audit_logs(
|
||||
limit=50,
|
||||
|
@ -202,7 +210,8 @@ class ModlogMemberCog(commands.Cog):
|
|||
desc=f"{before.mention} was muted",
|
||||
)
|
||||
|
||||
async def process_verify(self, before, after) -> discord.Embed:
|
||||
async def process_verify(self, before: discord.Member, after: discord.Member) -> discord.Embed:
|
||||
"""Process verification event."""
|
||||
await asyncio.sleep(0.5) # Need to wait for audit log
|
||||
auditlog = await before.guild.audit_logs(
|
||||
limit=50,
|
||||
|
@ -220,7 +229,8 @@ class ModlogMemberCog(commands.Cog):
|
|||
desc=f"{before.mention} was verified",
|
||||
)
|
||||
|
||||
async def process_rolechange(self, before, after) -> discord.Embed:
|
||||
async def process_rolechange(self, before: discord.Member, after: discord.Member) -> discord.Embed:
|
||||
"""Process rolechange event."""
|
||||
await asyncio.sleep(0.5) # Need to wait for audit log
|
||||
auditlog = await before.guild.audit_logs(
|
||||
limit=50,
|
||||
|
@ -249,7 +259,11 @@ class ModlogMemberCog(commands.Cog):
|
|||
)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_member_update(self, before: discord.Member, after: discord.Member):
|
||||
async def on_member_update(self, before: discord.Member, after: discord.Member) -> None:
|
||||
"""Process on_member_update events.
|
||||
|
||||
Caches events due to double-send bug
|
||||
"""
|
||||
h = hash(hash(before) * hash(after))
|
||||
if h not in self.cache:
|
||||
self.cache.append(h)
|
||||
|
@ -287,18 +301,18 @@ class ModlogMemberCog(commands.Cog):
|
|||
fields = [
|
||||
Field(
|
||||
name="Before",
|
||||
value=f"{bname} ({before.name}" + f"#{before.discriminator})",
|
||||
value=f"{bname} ({before.name}#{before.discriminator})",
|
||||
),
|
||||
Field(
|
||||
name="After",
|
||||
value=f"{aname} ({after.name}" + f"#{after.discriminator})",
|
||||
value=f"{aname} ({after.name}#{after.discriminator})",
|
||||
),
|
||||
]
|
||||
if log.user.id != before.id:
|
||||
fields.append(
|
||||
Field(
|
||||
name="Moderator",
|
||||
value=f"{log.user.mention} ({log.user.name}" + f"#{log.user.discriminator})",
|
||||
value=f"{log.user.mention} ({log.user.name}#{log.user.discriminator})",
|
||||
)
|
||||
)
|
||||
if log.reason:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. ModlogMessageCog."""
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
|
@ -7,11 +8,14 @@ from jarvis.utils.field import Field
|
|||
|
||||
|
||||
class ModlogMessageCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. ModlogMessageCog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message_edit(self, before: discord.Message, after: discord.Message):
|
||||
async def on_message_edit(self, before: discord.Message, after: discord.Message) -> None:
|
||||
"""Process on_message_edit events."""
|
||||
if not before.author.bot:
|
||||
modlog = Setting.objects(guild=after.guild.id, setting="modlog").first()
|
||||
if modlog:
|
||||
|
@ -43,11 +47,12 @@ class ModlogMessageCog(commands.Cog):
|
|||
icon_url=before.author.avatar_url,
|
||||
url=after.jump_url,
|
||||
)
|
||||
embed.set_footer(text=f"{before.author.name}#{before.author.discriminator}" + f" | {before.author.id}")
|
||||
embed.set_footer(text=f"{before.author.name}#{before.author.discriminator} | {before.author.id}")
|
||||
await channel.send(embed=embed)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message_delete(self, message: discord.Message):
|
||||
async def on_message_delete(self, message: discord.Message) -> None:
|
||||
"""Process on_message_delete events."""
|
||||
modlog = Setting.objects(guild=message.guild.id, setting="modlog").first()
|
||||
if modlog:
|
||||
fields = [Field("Original Message", message.content or "N/A", False)]
|
||||
|
@ -95,5 +100,5 @@ class ModlogMessageCog(commands.Cog):
|
|||
icon_url=message.author.avatar_url,
|
||||
url=message.jump_url,
|
||||
)
|
||||
embed.set_footer(text=f"{message.author.name}#{message.author.discriminator}" + f" | {message.author.id}")
|
||||
embed.set_footer(text=f"{message.author.name}#{message.author.discriminator} | {message.author.id}")
|
||||
await channel.send(embed=embed)
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
"""J.A.R.V.I.S. Modlog Cog Utilities."""
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from typing import List
|
||||
|
||||
import discord
|
||||
from discord import AuditLogEntry
|
||||
from discord import Member
|
||||
from discord.utils import find
|
||||
|
||||
from jarvis.utils import build_embed
|
||||
|
@ -15,10 +19,11 @@ def modlog_embed(
|
|||
title: str,
|
||||
desc: str,
|
||||
) -> discord.Embed:
|
||||
"""Get modlog embed."""
|
||||
fields = [
|
||||
Field(
|
||||
name="Moderator",
|
||||
value=f"{admin.mention} ({admin.name}" + f"#{admin.discriminator})",
|
||||
value=f"{admin.mention} ({admin.name}#{admin.discriminator})",
|
||||
),
|
||||
]
|
||||
if log.reason:
|
||||
|
@ -38,7 +43,8 @@ def modlog_embed(
|
|||
return embed
|
||||
|
||||
|
||||
def get_latest_log(auditlog, target):
|
||||
def get_latest_log(auditlog: List[AuditLogEntry], target: Member) -> AuditLogEntry:
|
||||
"""Filter AuditLog to get latest entry."""
|
||||
before = datetime.utcnow() - timedelta(seconds=10)
|
||||
return find(
|
||||
lambda x: x.target.id == target.id and x.created_at > before,
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
"""J.A.R.V.I.S. Owner Cog."""
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
from inspect import getsource
|
||||
from time import time
|
||||
from typing import Any
|
||||
|
||||
import discord
|
||||
from discord import DMChannel
|
||||
|
@ -18,18 +20,18 @@ from jarvis.utils.permissions import user_is_bot_admin
|
|||
|
||||
class OwnerCog(commands.Cog):
|
||||
"""
|
||||
J.A.R.V.I.S. management cog
|
||||
J.A.R.V.I.S. management cog.
|
||||
|
||||
Used by admins to control core J.A.R.V.I.S. systems
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
def __init__(self, bot: commands.Cog):
|
||||
self.bot = bot
|
||||
self.admins = Config.objects(key="admins").first()
|
||||
|
||||
@commands.command(name="load", hidden=True)
|
||||
@user_is_bot_admin()
|
||||
async def _load_cog(self, ctx, *, cog: str):
|
||||
async def _load_cog(self, ctx: commands.Context, *, cog: str) -> None:
|
||||
info = await self.bot.application_info()
|
||||
if ctx.message.author == info.owner or ctx.message.author.id in self.admins.value:
|
||||
try:
|
||||
|
@ -47,7 +49,7 @@ class OwnerCog(commands.Cog):
|
|||
|
||||
@commands.command(name="unload", hidden=True)
|
||||
@user_is_bot_admin()
|
||||
async def _unload_cog(self, ctx, *, cog: str):
|
||||
async def _unload_cog(self, ctx: commands.Context, *, cog: str) -> None:
|
||||
if cog in ["jarvis.cogs.owner", "owner"]:
|
||||
await ctx.send("Cannot unload `owner` cog")
|
||||
return
|
||||
|
@ -68,7 +70,7 @@ class OwnerCog(commands.Cog):
|
|||
|
||||
@commands.command(name="reload", hidden=True)
|
||||
@user_is_bot_admin()
|
||||
async def _cog_reload(self, ctx, *, cog: str):
|
||||
async def _cog_reload(self, ctx: commands.Context, *, cog: str) -> None:
|
||||
if cog in ["jarvis.cogs.owner", "owner"]:
|
||||
await ctx.send("Cannot reload `owner` cog")
|
||||
return
|
||||
|
@ -91,13 +93,13 @@ class OwnerCog(commands.Cog):
|
|||
|
||||
@commands.group(name="system", hidden=True, pass_context=True)
|
||||
@user_is_bot_admin()
|
||||
async def _system(self, ctx):
|
||||
async def _system(self, ctx: commands.Context) -> None:
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send("Usage: `system <subcommand>`\n" + "Subcommands: `restart`, `update`")
|
||||
|
||||
@_system.command(name="restart", hidden=True)
|
||||
@user_is_bot_admin()
|
||||
async def _restart(self, ctx):
|
||||
async def _restart(self, ctx: commands.Context) -> None:
|
||||
info = await self.bot.application_info()
|
||||
if ctx.message.author == info.owner or ctx.message.author.id in self.admins.value:
|
||||
await ctx.send("Restarting core systems...")
|
||||
|
@ -117,7 +119,7 @@ class OwnerCog(commands.Cog):
|
|||
|
||||
@_system.command(name="update", hidden=True)
|
||||
@user_is_bot_admin()
|
||||
async def _update(self, ctx):
|
||||
async def _update(self, ctx: commands.Context) -> None:
|
||||
info = await self.bot.application_info()
|
||||
if ctx.message.author == info.owner or ctx.message.author.id in self.admins.value:
|
||||
await ctx.send("Updating core systems...")
|
||||
|
@ -144,19 +146,19 @@ class OwnerCog(commands.Cog):
|
|||
|
||||
@_system.command(name="refresh", hidden=True)
|
||||
@user_is_bot_admin()
|
||||
async def _refresh(self, ctx):
|
||||
async def _refresh(self, ctx: commands.Context) -> None:
|
||||
reload_config()
|
||||
await ctx.send("System refreshed")
|
||||
|
||||
@commands.group(name="admin", hidden=True, pass_context=True)
|
||||
@commands.is_owner()
|
||||
async def _admin(self, ctx):
|
||||
async def _admin(self, ctx: commands.Context) -> None:
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send("Usage: `admin <subcommand>`\n" + "Subcommands: `add`, `remove`")
|
||||
|
||||
@_admin.command(name="add", hidden=True)
|
||||
@commands.is_owner()
|
||||
async def _add(self, ctx, user: User):
|
||||
async def _add(self, ctx: commands.Context, user: User) -> None:
|
||||
if user.id in self.admins.value:
|
||||
await ctx.send(f"{user.mention} is already an admin.")
|
||||
return
|
||||
|
@ -167,7 +169,7 @@ class OwnerCog(commands.Cog):
|
|||
|
||||
@_admin.command(name="remove", hidden=True)
|
||||
@commands.is_owner()
|
||||
async def _remove(self, ctx, user: User):
|
||||
async def _remove(self, ctx: commands.Context, user: User) -> None:
|
||||
if user.id not in self.admins.value:
|
||||
await ctx.send(f"{user.mention} is not an admin.")
|
||||
return
|
||||
|
@ -176,7 +178,8 @@ class OwnerCog(commands.Cog):
|
|||
reload_config()
|
||||
await ctx.send(f"{user.mention} is no longer an admin.")
|
||||
|
||||
def resolve_variable(self, variable):
|
||||
def resolve_variable(self, variable: Any) -> Any:
|
||||
"""Resolve a variable from eval."""
|
||||
if hasattr(variable, "__iter__"):
|
||||
var_length = len(list(variable))
|
||||
if (var_length > 100) and (not isinstance(variable, str)):
|
||||
|
@ -192,7 +195,8 @@ class OwnerCog(commands.Cog):
|
|||
else f"<a long {type(variable).__name__} object " + f"with the length of {len(f'{variable}'):,}>"
|
||||
)
|
||||
|
||||
def prepare(self, string):
|
||||
def prepare(self, string: str) -> str:
|
||||
"""Prepare string for eval."""
|
||||
arr = string.strip("```").replace("py\n", "").replace("python\n", "").split("\n")
|
||||
if not arr[::-1][0].replace(" ", "").startswith("return"):
|
||||
arr[len(arr) - 1] = "return " + arr[::-1][0]
|
||||
|
@ -200,7 +204,7 @@ class OwnerCog(commands.Cog):
|
|||
|
||||
@commands.command(pass_context=True, aliases=["eval", "exec", "evaluate"])
|
||||
@user_is_bot_admin()
|
||||
async def _eval(self, ctx, *, code: str):
|
||||
async def _eval(self, ctx: commands.Context, *, code: str) -> None:
|
||||
if not isinstance(ctx.message.channel, DMChannel):
|
||||
return
|
||||
code = self.prepare(code)
|
||||
|
@ -215,13 +219,13 @@ class OwnerCog(commands.Cog):
|
|||
}
|
||||
|
||||
try:
|
||||
exec(
|
||||
exec( # noqa: S102
|
||||
f"async def func():{code}",
|
||||
globals().update(args),
|
||||
locals(),
|
||||
)
|
||||
a = time()
|
||||
response = await eval("func()", globals().update(args), locals())
|
||||
response = await eval("func()", globals().update(args), locals()) # noqa: S307
|
||||
if response is None or isinstance(response, discord.Message):
|
||||
del args, code
|
||||
return
|
||||
|
@ -230,8 +234,7 @@ class OwnerCog(commands.Cog):
|
|||
response = response.replace("`", "")
|
||||
|
||||
await ctx.send(
|
||||
f"```py\n{self.resolve_variable(response)}```"
|
||||
+ f"`{type(response).__name__} | {(time() - a) / 1000} ms`"
|
||||
f"```py\n{self.resolve_variable(response)}```\n`{type(response).__name__} | {(time() - a) / 1000} ms`"
|
||||
)
|
||||
except Exception:
|
||||
await ctx.send(f"Error occurred:```\n{traceback.format_exc()}```")
|
||||
|
@ -239,5 +242,6 @@ class OwnerCog(commands.Cog):
|
|||
del args, code
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add OwnerCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(OwnerCog(bot))
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
"""J.A.R.V.I.S. Remind Me Cog."""
|
||||
import asyncio
|
||||
import re
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
||||
from bson import ObjectId
|
||||
from discord.ext import commands
|
||||
from discord import Embed
|
||||
from discord.ext.commands import Bot
|
||||
from discord.ext.tasks import loop
|
||||
from discord.utils import find
|
||||
from discord_slash import cog_ext
|
||||
from discord_slash import SlashContext
|
||||
from discord_slash.utils.manage_commands import create_option
|
||||
|
@ -29,7 +31,9 @@ invites = re.compile(
|
|||
|
||||
|
||||
class RemindmeCog(CacheCog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. Remind Me Cog."""
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
super().__init__(bot)
|
||||
self._remind.start()
|
||||
|
||||
|
@ -77,7 +81,7 @@ class RemindmeCog(CacheCog):
|
|||
days: Optional[int] = 0,
|
||||
hours: Optional[int] = 0,
|
||||
minutes: Optional[int] = 0,
|
||||
):
|
||||
) -> None:
|
||||
if len(message) > 100:
|
||||
await ctx.send("Reminder cannot be > 100 characters.", hidden=True)
|
||||
return
|
||||
|
@ -120,7 +124,7 @@ class RemindmeCog(CacheCog):
|
|||
if reminders >= 5:
|
||||
await ctx.send(
|
||||
"You already have 5 (or more) active reminders. "
|
||||
+ "Please either remove an old one, or wait for one to pass",
|
||||
"Please either remove an old one, or wait for one to pass",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -162,7 +166,8 @@ class RemindmeCog(CacheCog):
|
|||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
async def get_reminders_embed(self, ctx, reminders):
|
||||
async def get_reminders_embed(self, ctx: SlashContext, reminders: List[Reminder]) -> Embed:
|
||||
"""Build embed for paginator."""
|
||||
fields = []
|
||||
for reminder in reminders:
|
||||
fields.append(
|
||||
|
@ -175,7 +180,7 @@ class RemindmeCog(CacheCog):
|
|||
|
||||
embed = build_embed(
|
||||
title=f"{len(reminders)} Active Reminder(s)",
|
||||
description="All active reminders for " + f"{ctx.author.mention}",
|
||||
description=f"All active reminders for {ctx.author.mention}",
|
||||
fields=fields,
|
||||
)
|
||||
|
||||
|
@ -192,12 +197,12 @@ class RemindmeCog(CacheCog):
|
|||
name="list",
|
||||
description="List reminders for a user",
|
||||
)
|
||||
async def _list(self, ctx: SlashContext):
|
||||
async def _list(self, ctx: SlashContext) -> None:
|
||||
exists = self.check_cache(ctx)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.send(
|
||||
"Please use existing interaction: " + f"{exists['paginator']._message.jump_url}",
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -215,7 +220,7 @@ class RemindmeCog(CacheCog):
|
|||
name="delete",
|
||||
description="Delete a reminder",
|
||||
)
|
||||
async def _delete(self, ctx: SlashContext):
|
||||
async def _delete(self, ctx: SlashContext) -> None:
|
||||
reminders = Reminder.objects(user=ctx.author.id, active=True)
|
||||
if not reminders:
|
||||
await ctx.send("You have no reminders set", hidden=True)
|
||||
|
@ -293,7 +298,7 @@ class RemindmeCog(CacheCog):
|
|||
await message.edit(components=components)
|
||||
|
||||
@loop(seconds=15)
|
||||
async def _remind(self):
|
||||
async def _remind(self) -> None:
|
||||
reminders = Reminder.objects(remind_at__lte=datetime.utcnow() + timedelta(seconds=30))
|
||||
for reminder in reminders:
|
||||
if reminder.remind_at <= datetime.utcnow():
|
||||
|
@ -313,7 +318,7 @@ class RemindmeCog(CacheCog):
|
|||
embed.set_thumbnail(url=user.avatar_url)
|
||||
try:
|
||||
await user.send(embed=embed)
|
||||
except:
|
||||
except Exception:
|
||||
guild = self.bot.fetch_guild(reminder.guild)
|
||||
channel = guild.get_channel(reminder.channel) if guild else None
|
||||
if channel:
|
||||
|
@ -322,5 +327,6 @@ class RemindmeCog(CacheCog):
|
|||
reminder.delete()
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: Bot) -> None:
|
||||
"""Add RemindmeCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(RemindmeCog(bot))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. Role Giver Cog."""
|
||||
from discord import Role
|
||||
from discord.ext import commands
|
||||
from discord_slash import cog_ext
|
||||
|
@ -11,7 +12,9 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class RolegiverCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. Role Giver Cog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -28,7 +31,7 @@ class RolegiverCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _rolegiver_add(self, ctx: SlashContext, role: Role):
|
||||
async def _rolegiver_add(self, ctx: SlashContext, role: Role) -> None:
|
||||
setting = Setting.objects(guild=ctx.guild.id, setting="rolegiver").first()
|
||||
if setting and role.id in setting.value:
|
||||
await ctx.send("Role already in rolegiver", hidden=True)
|
||||
|
@ -64,7 +67,7 @@ class RolegiverCog(commands.Cog):
|
|||
icon_url=ctx.author.avatar_url,
|
||||
)
|
||||
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} " + f"| {ctx.author.id}")
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} | {ctx.author.id}")
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
@ -82,7 +85,7 @@ class RolegiverCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _rolegiver_remove(self, ctx: SlashContext, role: Role):
|
||||
async def _rolegiver_remove(self, ctx: SlashContext, role: Role) -> None:
|
||||
setting = Setting.objects(guild=ctx.guild.id, setting="rolegiver").first()
|
||||
if not setting or (setting and not setting.value):
|
||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||
|
@ -120,7 +123,7 @@ class RolegiverCog(commands.Cog):
|
|||
icon_url=ctx.author.avatar_url,
|
||||
)
|
||||
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} " + f"| {ctx.author.id}")
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} | {ctx.author.id}")
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
@ -129,7 +132,7 @@ class RolegiverCog(commands.Cog):
|
|||
name="list",
|
||||
description="List roles rolegiver",
|
||||
)
|
||||
async def _rolegiver_list(self, ctx: SlashContext):
|
||||
async def _rolegiver_list(self, ctx: SlashContext) -> None:
|
||||
setting = Setting.objects(guild=ctx.guild.id, setting="rolegiver").first()
|
||||
if not setting or (setting and not setting.value):
|
||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||
|
@ -157,7 +160,7 @@ class RolegiverCog(commands.Cog):
|
|||
icon_url=ctx.author.avatar_url,
|
||||
)
|
||||
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} " + f"| {ctx.author.id}")
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} | {ctx.author.id}")
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
@ -175,7 +178,7 @@ class RolegiverCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@commands.cooldown(1, 10, commands.BucketType.user)
|
||||
async def _role_get(self, ctx: SlashContext, role: Role):
|
||||
async def _role_get(self, ctx: SlashContext, role: Role) -> None:
|
||||
setting = Setting.objects(guild=ctx.guild.id, setting="rolegiver").first()
|
||||
if not setting or (setting and not setting.value):
|
||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||
|
@ -212,7 +215,7 @@ class RolegiverCog(commands.Cog):
|
|||
icon_url=ctx.author.avatar_url,
|
||||
)
|
||||
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} " + f"| {ctx.author.id}")
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} | {ctx.author.id}")
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
@ -230,7 +233,7 @@ class RolegiverCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@commands.cooldown(1, 10, commands.BucketType.user)
|
||||
async def _role_forfeit(self, ctx: SlashContext, role: Role):
|
||||
async def _role_forfeit(self, ctx: SlashContext, role: Role) -> None:
|
||||
setting = Setting.objects(guild=ctx.guild.id, setting="rolegiver").first()
|
||||
if not setting or (setting and not setting.value):
|
||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||
|
@ -267,10 +270,11 @@ class RolegiverCog(commands.Cog):
|
|||
icon_url=ctx.author.avatar_url,
|
||||
)
|
||||
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} " + f"| {ctx.author.id}")
|
||||
embed.set_footer(text=f"{ctx.author.name}#{ctx.author.discriminator} | {ctx.author.id}")
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add RolegiverCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(RolegiverCog(bot))
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
"""J.A.R.V.I.S. Settings Management Cog."""
|
||||
from typing import Any
|
||||
|
||||
from discord import Role
|
||||
from discord import TextChannel
|
||||
from discord.ext import commands
|
||||
|
@ -13,10 +16,13 @@ from jarvis.utils.permissions import admin_or_permissions
|
|||
|
||||
|
||||
class SettingsCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. Settings Management Cog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
def update_settings(self, setting, value, guild):
|
||||
def update_settings(self, setting: str, value: Any, guild: int) -> bool:
|
||||
"""Update a guild setting."""
|
||||
setting = Setting.objects(setting=setting, guild=guild).first()
|
||||
if not setting:
|
||||
setting = Setting(setting=setting, guild=guild, value=value)
|
||||
|
@ -24,7 +30,8 @@ class SettingsCog(commands.Cog):
|
|||
|
||||
return updated is not None
|
||||
|
||||
def delete_settings(self, setting, guild):
|
||||
def delete_settings(self, setting: str, guild: int) -> bool:
|
||||
"""Delete a guild setting."""
|
||||
return Setting.objects(setting=setting, guild=guild).delete()
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -44,7 +51,7 @@ class SettingsCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _set_mute(self, ctx, role: Role):
|
||||
async def _set_mute(self, ctx: SlashContext, role: Role) -> None:
|
||||
await ctx.defer()
|
||||
self.update_settings("mute", role.id, ctx.guild.id)
|
||||
await ctx.send(f"Settings applied. New mute role is `{role.name}`")
|
||||
|
@ -64,7 +71,7 @@ class SettingsCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _set_modlog(self, ctx, channel: TextChannel):
|
||||
async def _set_modlog(self, ctx: SlashContext, channel: TextChannel) -> None:
|
||||
if not isinstance(channel, TextChannel):
|
||||
await ctx.send("Channel must be a TextChannel", hidden=True)
|
||||
return
|
||||
|
@ -86,7 +93,7 @@ class SettingsCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _set_userlog(self, ctx, channel: TextChannel):
|
||||
async def _set_userlog(self, ctx: SlashContext, channel: TextChannel) -> None:
|
||||
if not isinstance(channel, TextChannel):
|
||||
await ctx.send("Channel must be a TextChannel", hidden=True)
|
||||
return
|
||||
|
@ -108,7 +115,7 @@ class SettingsCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _set_massmention(self, ctx, amount: int):
|
||||
async def _set_massmention(self, ctx: SlashContext, amount: int) -> None:
|
||||
await ctx.defer()
|
||||
self.update_settings("massmention", amount, ctx.guild.id)
|
||||
await ctx.send(f"Settings applied. New massmention limit is {amount}")
|
||||
|
@ -128,7 +135,7 @@ class SettingsCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _set_verified(self, ctx, role: Role):
|
||||
async def _set_verified(self, ctx: SlashContext, role: Role) -> None:
|
||||
await ctx.defer()
|
||||
self.update_settings("verified", role.id, ctx.guild.id)
|
||||
await ctx.send(f"Settings applied. New verified role is `{role.name}`")
|
||||
|
@ -148,7 +155,7 @@ class SettingsCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _set_unverified(self, ctx, role: Role):
|
||||
async def _set_unverified(self, ctx: SlashContext, role: Role) -> None:
|
||||
await ctx.defer()
|
||||
self.update_settings("unverified", role.id, ctx.guild.id)
|
||||
await ctx.send(f"Settings applied. New unverified role is `{role.name}`")
|
||||
|
@ -161,7 +168,7 @@ class SettingsCog(commands.Cog):
|
|||
description="Unset mute role",
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _unset_mute(self, ctx):
|
||||
async def _unset_mute(self, ctx: SlashContext) -> None:
|
||||
await ctx.defer()
|
||||
self.delete_settings("mute", ctx.guild.id)
|
||||
await ctx.send("Setting removed.")
|
||||
|
@ -173,7 +180,7 @@ class SettingsCog(commands.Cog):
|
|||
description="Unset modlog channel",
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _unset_modlog(self, ctx):
|
||||
async def _unset_modlog(self, ctx: SlashContext) -> None:
|
||||
self.delete_settings("modlog", ctx.guild.id)
|
||||
await ctx.send("Setting removed.")
|
||||
|
||||
|
@ -184,7 +191,7 @@ class SettingsCog(commands.Cog):
|
|||
description="Unset userlog channel",
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _unset_userlog(self, ctx):
|
||||
async def _unset_userlog(self, ctx: SlashContext) -> None:
|
||||
self.delete_settings("userlog", ctx.guild.id)
|
||||
await ctx.send("Setting removed.")
|
||||
|
||||
|
@ -195,7 +202,7 @@ class SettingsCog(commands.Cog):
|
|||
description="Unet massmention amount",
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _massmention(self, ctx):
|
||||
async def _massmention(self, ctx: SlashContext) -> None:
|
||||
await ctx.defer()
|
||||
self.delete_settings("massmention", ctx.guild.id)
|
||||
await ctx.send("Setting removed.")
|
||||
|
@ -207,7 +214,7 @@ class SettingsCog(commands.Cog):
|
|||
description="Unset verified role",
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _verified(self, ctx):
|
||||
async def _verified(self, ctx: SlashContext) -> None:
|
||||
await ctx.defer()
|
||||
self.delete_settings("verified", ctx.guild.id)
|
||||
await ctx.send("Setting removed.")
|
||||
|
@ -219,14 +226,14 @@ class SettingsCog(commands.Cog):
|
|||
description="Unset unverified role",
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _unverified(self, ctx):
|
||||
async def _unverified(self, ctx: SlashContext) -> None:
|
||||
await ctx.defer()
|
||||
self.delete_settings("unverified", ctx.guild.id)
|
||||
await ctx.send("Setting removed.")
|
||||
|
||||
@cog_ext.cog_subcommand(base="settings", name="view", description="View settings")
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _view(self, ctx: SlashContext):
|
||||
async def _view(self, ctx: SlashContext) -> None:
|
||||
settings = Setting.objects(guild=ctx.guild.id)
|
||||
|
||||
fields = []
|
||||
|
@ -260,10 +267,11 @@ class SettingsCog(commands.Cog):
|
|||
|
||||
@cog_ext.cog_subcommand(base="settings", name="clear", description="Clear all settings")
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _clear(self, ctx: SlashContext):
|
||||
async def _clear(self, ctx: SlashContext) -> None:
|
||||
deleted = Setting.objects(guild=ctx.guild.id).delete()
|
||||
await ctx.send(f"Guild settings cleared: `{deleted is not None}`")
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add SettingsCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(SettingsCog(bot))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. Starboard Cog."""
|
||||
from discord import TextChannel
|
||||
from discord.ext import commands
|
||||
from discord.utils import find
|
||||
|
@ -24,7 +25,9 @@ supported_images = [
|
|||
|
||||
|
||||
class StarboardCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. Starboard Cog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@cog_ext.cog_subcommand(
|
||||
|
@ -33,7 +36,7 @@ class StarboardCog(commands.Cog):
|
|||
description="Lists all Starboards",
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _list(self, ctx):
|
||||
async def _list(self, ctx: SlashContext) -> None:
|
||||
starboards = Starboard.objects(guild=ctx.guild.id)
|
||||
if starboards != []:
|
||||
message = "Available Starboards:\n"
|
||||
|
@ -57,7 +60,7 @@ class StarboardCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _create(self, ctx, channel: TextChannel):
|
||||
async def _create(self, ctx: SlashContext, channel: TextChannel) -> None:
|
||||
if channel not in ctx.guild.channels:
|
||||
await ctx.send(
|
||||
"Channel not in guild. Choose an existing channel.",
|
||||
|
@ -99,7 +102,7 @@ class StarboardCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
async def _delete(self, ctx, channel: TextChannel):
|
||||
async def _delete(self, ctx: SlashContext, channel: TextChannel) -> None:
|
||||
deleted = Starboard.objects(channel=channel.id, guild=ctx.guild.id).delete()
|
||||
if deleted:
|
||||
_ = Star.objects(starboard=channel.id).delete()
|
||||
|
@ -120,7 +123,7 @@ class StarboardCog(commands.Cog):
|
|||
),
|
||||
create_option(
|
||||
name="channel",
|
||||
description="Channel that has the message, " + "required if different than command message",
|
||||
description="Channel that has the message, required if different than command message",
|
||||
option_type=7,
|
||||
required=False,
|
||||
),
|
||||
|
@ -132,7 +135,7 @@ class StarboardCog(commands.Cog):
|
|||
ctx: SlashContext,
|
||||
message: str,
|
||||
channel: TextChannel = None,
|
||||
):
|
||||
) -> None:
|
||||
if not channel:
|
||||
channel = ctx.channel
|
||||
starboards = Starboard.objects(guild=ctx.guild.id)
|
||||
|
@ -230,7 +233,7 @@ class StarboardCog(commands.Cog):
|
|||
components[0]["components"][0]["disabled"] = True
|
||||
|
||||
await com_ctx.edit_origin(
|
||||
content="Message saved to Starboard.\n" + f"See it in {starboard.mention}",
|
||||
content=f"Message saved to Starboard.\nSee it in {starboard.mention}",
|
||||
components=components,
|
||||
)
|
||||
|
||||
|
@ -259,14 +262,14 @@ class StarboardCog(commands.Cog):
|
|||
ctx: SlashContext,
|
||||
id: int,
|
||||
starboard: TextChannel,
|
||||
):
|
||||
) -> None:
|
||||
if not isinstance(starboard, TextChannel):
|
||||
await ctx.send("Channel must be a TextChannel", hidden=True)
|
||||
return
|
||||
exists = Starboard.objects(channel=starboard.id, guild=ctx.guild.id).first()
|
||||
if not exists:
|
||||
await ctx.send(
|
||||
f"Starboard does not exist in {starboard.mention}. " + "Please create it first",
|
||||
f"Starboard does not exist in {starboard.mention}. Please create it first",
|
||||
hidden=True,
|
||||
)
|
||||
return
|
||||
|
@ -291,5 +294,6 @@ class StarboardCog(commands.Cog):
|
|||
await ctx.send(f"Star {id} deleted")
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add StarboardCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(StarboardCog(bot))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. Utility Cog."""
|
||||
import re
|
||||
import secrets
|
||||
import string
|
||||
|
@ -35,7 +36,7 @@ class UtilCog(commands.Cog):
|
|||
Mostly system utility functions, but may change over time
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
def __init__(self, bot: commands.Cog):
|
||||
self.bot = bot
|
||||
self.config = get_config()
|
||||
|
||||
|
@ -44,7 +45,7 @@ class UtilCog(commands.Cog):
|
|||
description="Retrieve J.A.R.V.I.S. status",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _status(self, ctx):
|
||||
async def _status(self, ctx: SlashContext) -> None:
|
||||
title = "J.A.R.V.I.S. Status"
|
||||
desc = "All systems online"
|
||||
color = "#98CCDA"
|
||||
|
@ -68,12 +69,12 @@ class UtilCog(commands.Cog):
|
|||
description="Get the current logo",
|
||||
)
|
||||
@commands.cooldown(1, 30, commands.BucketType.channel)
|
||||
async def _logo(self, ctx):
|
||||
async def _logo(self, ctx: SlashContext) -> None:
|
||||
lo = logo.get_logo(self.config.logo)
|
||||
await ctx.send(f"```\n{lo}\n```")
|
||||
|
||||
@cog_ext.cog_slash(name="rchk", description="Robot Camo HK416")
|
||||
async def _rchk(self, ctx: SlashContext):
|
||||
async def _rchk(self, ctx: SlashContext) -> None:
|
||||
await ctx.send(content=hk)
|
||||
|
||||
@cog_ext.cog_slash(
|
||||
|
@ -88,7 +89,7 @@ class UtilCog(commands.Cog):
|
|||
)
|
||||
],
|
||||
)
|
||||
async def _rcauto(self, ctx: SlashContext, text: str):
|
||||
async def _rcauto(self, ctx: SlashContext, text: str) -> None:
|
||||
to_send = ""
|
||||
if len(text) == 1 and not re.match(r"^[A-Z0-9-()$@!?^'#. ]$", text.upper()):
|
||||
await ctx.send("Please use ASCII characters.", hidden=True)
|
||||
|
@ -120,7 +121,7 @@ class UtilCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@commands.cooldown(1, 5, commands.BucketType.user)
|
||||
async def _avatar(self, ctx, user: User = None):
|
||||
async def _avatar(self, ctx: SlashContext, user: User = None) -> None:
|
||||
if not user:
|
||||
user = ctx.author
|
||||
|
||||
|
@ -142,7 +143,7 @@ class UtilCog(commands.Cog):
|
|||
)
|
||||
],
|
||||
)
|
||||
async def _roleinfo(self, ctx: SlashContext, role: Role):
|
||||
async def _roleinfo(self, ctx: SlashContext, role: Role) -> None:
|
||||
|
||||
fields = [
|
||||
Field(name="ID", value=role.id),
|
||||
|
@ -193,7 +194,7 @@ class UtilCog(commands.Cog):
|
|||
)
|
||||
],
|
||||
)
|
||||
async def _userinfo(self, ctx: SlashContext, user: User = None):
|
||||
async def _userinfo(self, ctx: SlashContext, user: User = None) -> None:
|
||||
if not user:
|
||||
user = ctx.author
|
||||
user_roles = user.roles
|
||||
|
@ -230,7 +231,7 @@ class UtilCog(commands.Cog):
|
|||
await ctx.send(embed=embed)
|
||||
|
||||
@cog_ext.cog_slash(name="serverinfo", description="Get server info")
|
||||
async def _server_info(self, ctx: SlashContext):
|
||||
async def _server_info(self, ctx: SlashContext) -> None:
|
||||
guild: Guild = ctx.guild
|
||||
|
||||
owner = f"{guild.owner.name}#{guild.owner.discriminator}" if guild.owner else "||`[redacted]`||"
|
||||
|
@ -291,7 +292,7 @@ class UtilCog(commands.Cog):
|
|||
],
|
||||
)
|
||||
@commands.cooldown(1, 15, type=commands.BucketType.user)
|
||||
async def _pw_gen(self, ctx: SlashContext, length: int = 32, chars: int = 3):
|
||||
async def _pw_gen(self, ctx: SlashContext, length: int = 32, chars: int = 3) -> None:
|
||||
if length > 256:
|
||||
await ctx.send("Please limit password to 256 characters", hidden=True)
|
||||
return
|
||||
|
@ -305,11 +306,12 @@ class UtilCog(commands.Cog):
|
|||
pw = "".join(secrets.choice(choices[chars]) for i in range(length))
|
||||
await ctx.send(
|
||||
f"Generated password:\n`{pw}`\n\n"
|
||||
+ '**WARNING: Once you press "Dismiss Message", '
|
||||
+ "*the password is lost forever***",
|
||||
'**WARNING: Once you press "Dismiss Message", '
|
||||
"*the password is lost forever***",
|
||||
hidden=True,
|
||||
)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add UtilCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(UtilCog(bot))
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from random import randint
|
||||
"""J.A.R.V.I.S. Verify Cog."""
|
||||
from secrets import randint
|
||||
|
||||
from discord.ext import commands
|
||||
from discord_slash import cog_ext
|
||||
|
@ -10,7 +11,8 @@ from discord_slash.utils import manage_components
|
|||
from jarvis.db.models import Setting
|
||||
|
||||
|
||||
def create_layout():
|
||||
def create_layout() -> list:
|
||||
"""Create verify component layout."""
|
||||
buttons = []
|
||||
yes = randint(0, 2)
|
||||
for i in range(3):
|
||||
|
@ -29,7 +31,9 @@ def create_layout():
|
|||
|
||||
|
||||
class VerifyCog(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. Verify Cog."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
|
||||
@cog_ext.cog_slash(
|
||||
|
@ -37,7 +41,7 @@ class VerifyCog(commands.Cog):
|
|||
description="Verify that you've read the rules",
|
||||
)
|
||||
@commands.cooldown(1, 15, commands.BucketType.user)
|
||||
async def _verify(self, ctx: SlashContext):
|
||||
async def _verify(self, ctx: SlashContext) -> None:
|
||||
await ctx.defer()
|
||||
role = Setting.objects(guild=ctx.guild.id, setting="verified").first()
|
||||
if not role:
|
||||
|
@ -48,13 +52,13 @@ class VerifyCog(commands.Cog):
|
|||
return
|
||||
components = create_layout()
|
||||
message = await ctx.send(
|
||||
content=f"{ctx.author.mention}, " + "please press the button that says `YES`.",
|
||||
content=f"{ctx.author.mention}, please press the button that says `YES`.",
|
||||
components=components,
|
||||
)
|
||||
await message.delete(delay=15)
|
||||
|
||||
@cog_ext.cog_component(components=create_layout())
|
||||
async def _process(self, ctx: ComponentContext):
|
||||
async def _process(self, ctx: ComponentContext) -> None:
|
||||
await ctx.defer(edit_origin=True)
|
||||
try:
|
||||
if ctx.author.id != ctx.origin_message.mentions[0].id:
|
||||
|
@ -75,15 +79,16 @@ class VerifyCog(commands.Cog):
|
|||
role = ctx.guild.get_role(setting.value)
|
||||
await ctx.author.remove_roles(role, reason="Verification passed")
|
||||
await ctx.edit_origin(
|
||||
content=f"Welcome, {ctx.author.mention}. " + "Please enjoy your stay.",
|
||||
content=f"Welcome, {ctx.author.mention}. Please enjoy your stay.",
|
||||
components=manage_components.spread_to_rows(*components, max_in_row=5),
|
||||
)
|
||||
await ctx.origin_message.delete(delay=5)
|
||||
else:
|
||||
await ctx.edit_origin(
|
||||
content=f"{ctx.author.mention}, incorrect. " + "Please press the button that says `YES`",
|
||||
content=f"{ctx.author.mention}, incorrect. Please press the button that says `YES`",
|
||||
)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add VerifyCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(VerifyCog(bot))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""Load the config for J.A.R.V.I.S."""
|
||||
from yaml import load
|
||||
|
||||
from jarvis.db.models import Config as DBConfig
|
||||
|
@ -9,7 +10,10 @@ except ImportError:
|
|||
|
||||
|
||||
class Config(object):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
"""Config singleton object for J.A.R.V.I.S."""
|
||||
|
||||
def __new__(cls, *args: list, **kwargs: dict):
|
||||
"""Get the singleton config, or creates a new one."""
|
||||
it = cls.__dict__.get("it")
|
||||
if it is not None:
|
||||
return it
|
||||
|
@ -24,33 +28,39 @@ class Config(object):
|
|||
logo: str,
|
||||
mongo: dict,
|
||||
urls: dict,
|
||||
log_level: str = "WARNING",
|
||||
cogs: list = None,
|
||||
events: bool = True,
|
||||
gitlab_token: str = None,
|
||||
max_messages: int = 1000,
|
||||
):
|
||||
) -> None:
|
||||
"""Initialize the config object."""
|
||||
self.token = token
|
||||
self.client_id = client_id
|
||||
self.logo = logo
|
||||
self.mongo = mongo
|
||||
self.urls = urls
|
||||
self.log_level = log_level
|
||||
self.cogs = cogs
|
||||
self.events = events
|
||||
self.max_messages = max_messages
|
||||
self.gitlab_token = gitlab_token
|
||||
|
||||
def get_db_config(self):
|
||||
def get_db_config(self) -> None:
|
||||
"""Load the database config objects."""
|
||||
config = DBConfig.objects()
|
||||
for item in config:
|
||||
setattr(self, item.key, item.value)
|
||||
|
||||
@classmethod
|
||||
def from_yaml(cls, y):
|
||||
def from_yaml(cls, y: dict) -> "Config":
|
||||
"""Load the yaml config file."""
|
||||
instance = cls(**y)
|
||||
return instance
|
||||
|
||||
|
||||
def get_config(path: str = "config.yaml") -> Config:
|
||||
"""Get the config from the specified yaml file."""
|
||||
if Config.__dict__.get("it"):
|
||||
return Config()
|
||||
with open(path) as f:
|
||||
|
@ -59,6 +69,7 @@ def get_config(path: str = "config.yaml") -> Config:
|
|||
return Config.from_yaml(y)
|
||||
|
||||
|
||||
def reload_config():
|
||||
def reload_config() -> None:
|
||||
"""Force reload of the config singleton on next call."""
|
||||
if "it" in Config.__dict__:
|
||||
Config.__dict__.pop("it")
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""dbrand-specific data."""
|
||||
shipping_lookup = [
|
||||
{"country": "afghanistan", "code": "AF"},
|
||||
{"country": "albania", "code": "AL"},
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""Robot Camo emote lookups."""
|
||||
emotes = {
|
||||
"A": 852317928572715038,
|
||||
"B": 852317954975727679,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""Unicode emoji data."""
|
||||
import json
|
||||
from os import getcwd
|
||||
from os import sep as s
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. database object for mongoengine."""
|
||||
from datetime import datetime
|
||||
|
||||
from mongoengine import Document
|
||||
|
@ -12,10 +13,14 @@ from mongoengine.fields import StringField
|
|||
|
||||
|
||||
class SnowflakeField(LongField):
|
||||
"""Snowflake LongField Override."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class Autopurge(Document):
|
||||
"""Autopurge database object."""
|
||||
|
||||
guild = SnowflakeField(required=True)
|
||||
channel = SnowflakeField(required=True)
|
||||
delay = IntField(min_value=1, max_value=300, default=30)
|
||||
|
@ -26,6 +31,8 @@ class Autopurge(Document):
|
|||
|
||||
|
||||
class Autoreact(Document):
|
||||
"""Autoreact database object."""
|
||||
|
||||
guild = SnowflakeField(required=True)
|
||||
channel = SnowflakeField(required=True)
|
||||
reactions = ListField(field=StringField())
|
||||
|
@ -36,6 +43,8 @@ class Autoreact(Document):
|
|||
|
||||
|
||||
class Ban(Document):
|
||||
"""Ban database object."""
|
||||
|
||||
active = BooleanField(default=True)
|
||||
admin = SnowflakeField(required=True)
|
||||
user = SnowflakeField(required=True)
|
||||
|
@ -51,6 +60,8 @@ class Ban(Document):
|
|||
|
||||
|
||||
class Config(Document):
|
||||
"""Config database object."""
|
||||
|
||||
key = StringField(required=True)
|
||||
value = DynamicField(required=True)
|
||||
|
||||
|
@ -58,6 +69,8 @@ class Config(Document):
|
|||
|
||||
|
||||
class Guess(Document):
|
||||
"""Guess database object."""
|
||||
|
||||
correct = BooleanField(default=False)
|
||||
guess = StringField(max_length=800, required=True)
|
||||
user = SnowflakeField(required=True)
|
||||
|
@ -66,6 +79,8 @@ class Guess(Document):
|
|||
|
||||
|
||||
class Joke(Document):
|
||||
"""Joke database object."""
|
||||
|
||||
rid = StringField()
|
||||
body = StringField()
|
||||
title = StringField()
|
||||
|
@ -77,6 +92,8 @@ class Joke(Document):
|
|||
|
||||
|
||||
class Kick(Document):
|
||||
"""Kick database object."""
|
||||
|
||||
admin = SnowflakeField(required=True)
|
||||
guild = SnowflakeField(required=True)
|
||||
reason = StringField(max_length=100, required=True)
|
||||
|
@ -87,6 +104,8 @@ class Kick(Document):
|
|||
|
||||
|
||||
class Lock(Document):
|
||||
"""Lock database object."""
|
||||
|
||||
active = BooleanField(default=True)
|
||||
admin = SnowflakeField(required=True)
|
||||
channel = SnowflakeField(required=True)
|
||||
|
@ -99,6 +118,8 @@ class Lock(Document):
|
|||
|
||||
|
||||
class Mute(Document):
|
||||
"""Mute database object."""
|
||||
|
||||
active = BooleanField(default=True)
|
||||
user = SnowflakeField(required=True)
|
||||
admin = SnowflakeField(required=True)
|
||||
|
@ -111,6 +132,8 @@ class Mute(Document):
|
|||
|
||||
|
||||
class Purge(Document):
|
||||
"""Purge database object."""
|
||||
|
||||
admin = SnowflakeField(required=True)
|
||||
channel = SnowflakeField(required=True)
|
||||
guild = SnowflakeField(required=True)
|
||||
|
@ -121,6 +144,8 @@ class Purge(Document):
|
|||
|
||||
|
||||
class Reminder(Document):
|
||||
"""Reminder database object."""
|
||||
|
||||
active = BooleanField(default=True)
|
||||
user = SnowflakeField(required=True)
|
||||
guild = SnowflakeField(required=True)
|
||||
|
@ -133,6 +158,8 @@ class Reminder(Document):
|
|||
|
||||
|
||||
class Roleping(Document):
|
||||
"""Roleping database object."""
|
||||
|
||||
active = BooleanField(default=True)
|
||||
role = SnowflakeField(required=True)
|
||||
guild = SnowflakeField(required=True)
|
||||
|
@ -144,6 +171,8 @@ class Roleping(Document):
|
|||
|
||||
|
||||
class Setting(Document):
|
||||
"""Setting database object."""
|
||||
|
||||
guild = SnowflakeField(required=True)
|
||||
setting = StringField(required=True)
|
||||
value = DynamicField()
|
||||
|
@ -152,6 +181,8 @@ class Setting(Document):
|
|||
|
||||
|
||||
class Star(Document):
|
||||
"""Star database object."""
|
||||
|
||||
active = BooleanField(default=True)
|
||||
index = IntField(required=True)
|
||||
message = SnowflakeField(required=True)
|
||||
|
@ -166,6 +197,8 @@ class Star(Document):
|
|||
|
||||
|
||||
class Starboard(Document):
|
||||
"""Starboard database object."""
|
||||
|
||||
channel = SnowflakeField(required=True)
|
||||
guild = SnowflakeField(required=True)
|
||||
admin = SnowflakeField(required=True)
|
||||
|
@ -175,6 +208,8 @@ class Starboard(Document):
|
|||
|
||||
|
||||
class Unban(Document):
|
||||
"""Unban database object."""
|
||||
|
||||
user = SnowflakeField(required=True)
|
||||
username = StringField(required=True)
|
||||
discrim = IntField(min_value=1, max_value=9999, required=True)
|
||||
|
@ -187,6 +222,8 @@ class Unban(Document):
|
|||
|
||||
|
||||
class Warning(Document):
|
||||
"""Warning database object."""
|
||||
|
||||
active = BooleanField(default=True)
|
||||
admin = SnowflakeField(required=True)
|
||||
user = SnowflakeField(required=True)
|
||||
|
|
|
@ -1,24 +1,30 @@
|
|||
"""J.A.R.V.I.S. guild event handler."""
|
||||
import asyncio
|
||||
|
||||
from discord import Guild
|
||||
from discord.ext.commands import Bot
|
||||
from discord.utils import find
|
||||
|
||||
from jarvis.db.models import Setting
|
||||
|
||||
|
||||
class GuildEventHandler(object):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. guild event handler."""
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
self.bot = bot
|
||||
self.bot.add_listener(self.on_guild_join)
|
||||
|
||||
async def on_guild_join(self, guild):
|
||||
async def on_guild_join(self, guild: Guild) -> None:
|
||||
"""Handle on_guild_join event."""
|
||||
general = find(lambda x: x.name == "general", guild.channels)
|
||||
if general and general.permissions_for(guild.me).send_messages:
|
||||
user = self.bot.user
|
||||
await general.send(
|
||||
f"Allow me to introduce myself. I am {user.mention}, a virtual "
|
||||
+ "artificial intelligence, and I'm here to assist you with a "
|
||||
+ "variety of tasks as best I can, "
|
||||
+ "24 hours a day, seven days a week."
|
||||
"artificial intelligence, and I'm here to assist you with a "
|
||||
"variety of tasks as best I can, "
|
||||
"24 hours a day, seven days a week."
|
||||
)
|
||||
await asyncio.sleep(1)
|
||||
await general.send("Importing all preferences from home interface...")
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
"""J.A.R.V.I.S. Member event handler."""
|
||||
from discord import Member
|
||||
from discord.ext.commands import Bot
|
||||
|
||||
from jarvis.db.models import Mute
|
||||
from jarvis.db.models import Setting
|
||||
|
||||
|
||||
class MemberEventHandler(object):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. Member event handler."""
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
self.bot = bot
|
||||
self.bot.add_listener(self.on_member_join)
|
||||
|
||||
async def on_member_join(self, user: Member):
|
||||
async def on_member_join(self, user: Member) -> None:
|
||||
"""Handle on_member_join event."""
|
||||
guild = user.guild
|
||||
mute = Mute.objects(guild=guild.id, user=user.id, active=True).first()
|
||||
if mute:
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
"""J.A.R.V.I.S. Message event handler."""
|
||||
import re
|
||||
|
||||
from discord import DMChannel
|
||||
from discord import Message
|
||||
from discord.ext.commands import Bot
|
||||
from discord.utils import find
|
||||
|
||||
from jarvis.config import get_config
|
||||
|
@ -20,17 +22,21 @@ invites = re.compile(
|
|||
|
||||
|
||||
class MessageEventHandler(object):
|
||||
def __init__(self, bot):
|
||||
"""J.A.R.V.I.S. Message event handler."""
|
||||
|
||||
def __init__(self, bot: Bot):
|
||||
self.bot = bot
|
||||
self.bot.add_listener(self.on_message)
|
||||
self.bot.add_listener(self.on_message_edit)
|
||||
|
||||
async def autopurge(self, message: Message):
|
||||
async def autopurge(self, message: Message) -> None:
|
||||
"""Handle autopurge events."""
|
||||
autopurge = Autopurge.objects(guild=message.guild.id, channel=message.channel.id).first()
|
||||
if autopurge:
|
||||
await message.delete(delay=autopurge.delay)
|
||||
|
||||
async def autoreact(self, message: Message):
|
||||
async def autoreact(self, message: Message) -> None:
|
||||
"""Handle autoreact events."""
|
||||
autoreact = Autoreact.objects(
|
||||
guild=message.guild.id,
|
||||
channel=message.channel.id,
|
||||
|
@ -39,12 +45,13 @@ class MessageEventHandler(object):
|
|||
for reaction in autoreact.reactions:
|
||||
await message.add_reaction(reaction)
|
||||
|
||||
async def checks(self, message: Message):
|
||||
async def checks(self, message: Message) -> None:
|
||||
"""Other message checks."""
|
||||
# #tech
|
||||
channel = find(lambda x: x.id == 599068193339736096, message.channel_mentions)
|
||||
if channel and message.author.id == 293795462752894976:
|
||||
await channel.send(
|
||||
content="https://cdn.discordapp.com/attachments/" + "664621130044407838/805218508866453554/tech.gif"
|
||||
content="https://cdn.discordapp.com/attachments/664621130044407838/805218508866453554/tech.gif"
|
||||
)
|
||||
content = re.sub(r"\s+", "", message.content)
|
||||
match = invites.search(content)
|
||||
|
@ -81,20 +88,20 @@ class MessageEventHandler(object):
|
|||
name=message.author.nick if message.author.nick else message.author.name,
|
||||
icon_url=message.author.avatar_url,
|
||||
)
|
||||
embed.set_footer(
|
||||
text=f"{message.author.name}#" + f"{message.author.discriminator} " + f"| {message.author.id}"
|
||||
)
|
||||
embed.set_footer(text=f"{message.author.name}#{message.author.discriminator} | {message.author.id}")
|
||||
await message.channel.send(embed=embed)
|
||||
|
||||
async def massmention(self, message: Message):
|
||||
async def massmention(self, message: Message) -> None:
|
||||
"""Handle massmention events."""
|
||||
massmention = Setting.objects(
|
||||
guild=message.guild.id,
|
||||
setting="massmention",
|
||||
).first()
|
||||
if (
|
||||
massmention
|
||||
and massmention.value > 0
|
||||
and len(message.mentions) - (1 if message.author in message.mentions else 0) > massmention.value
|
||||
and massmention.value > 0 # noqa: W503
|
||||
and len(message.mentions) - (1 if message.author in message.mentions else 0) # noqa: W503
|
||||
> massmention.value # noqa: W503
|
||||
):
|
||||
_ = Warning(
|
||||
active=True,
|
||||
|
@ -114,10 +121,11 @@ class MessageEventHandler(object):
|
|||
name=message.author.nick if message.author.nick else message.author.name,
|
||||
icon_url=message.author.avatar_url,
|
||||
)
|
||||
embed.set_footer(text=f"{message.author.name}#{message.author.discriminator} " + f"| {message.author.id}")
|
||||
embed.set_footer(text=f"{message.author.name}#{message.author.discriminator} | {message.author.id}")
|
||||
await message.channel.send(embed=embed)
|
||||
|
||||
async def roleping(self, message: Message):
|
||||
async def roleping(self, message: Message) -> None:
|
||||
"""Handle roleping events."""
|
||||
rolepings = Roleping.objects(guild=message.guild.id, active=True)
|
||||
|
||||
if not rolepings:
|
||||
|
@ -181,10 +189,11 @@ class MessageEventHandler(object):
|
|||
name=message.author.nick if message.author.nick else message.author.name,
|
||||
icon_url=message.author.avatar_url,
|
||||
)
|
||||
embed.set_footer(text=f"{message.author.name}#{message.author.discriminator} " + f"| {message.author.id}")
|
||||
embed.set_footer(text=f"{message.author.name}#{message.author.discriminator} | {message.author.id}")
|
||||
await message.channel.send(embed=embed)
|
||||
|
||||
async def on_message(self, message: Message):
|
||||
async def on_message(self, message: Message) -> None:
|
||||
"""Handle on_message event. Calls other event handlers."""
|
||||
if not isinstance(message.channel, DMChannel) and not message.author.bot:
|
||||
await self.autoreact(message)
|
||||
await self.massmention(message)
|
||||
|
@ -192,8 +201,11 @@ class MessageEventHandler(object):
|
|||
await self.autopurge(message)
|
||||
await self.checks(message)
|
||||
|
||||
async def on_message_edit(self, before: Message, after: Message):
|
||||
async def on_message_edit(self, before: Message, after: Message) -> None:
|
||||
"""Handle on_message_edit event. Calls other event handlers."""
|
||||
if not isinstance(after.channel, DMChannel) and not after.author.bot:
|
||||
await self.massmention(after)
|
||||
await self.roleping(after)
|
||||
await self.checks(after)
|
||||
await self.roleping(after)
|
||||
await self.checks(after)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"""Logos for J.A.R.V.I.S."""
|
||||
|
||||
logo_doom = r"""
|
||||
___ ___ ______ _ _ _____ _____
|
||||
|_ | / _ \ | ___ \ | | | | |_ _| / ___|
|
||||
|
@ -82,7 +84,7 @@ logo_alligator = r"""
|
|||
#+# #+# #+# #+# #+# #+# #+# #+# #+# #+#+#+# #+# #+# #+# #+# #+# #+#
|
||||
##### ### ### ### ### ### ### ### ### ### ########### ### ######## ###
|
||||
|
||||
"""
|
||||
""" # noqa: E501
|
||||
|
||||
logo_alligator2 = r"""
|
||||
|
||||
|
@ -97,7 +99,8 @@ logo_alligator2 = r"""
|
|||
"""
|
||||
|
||||
|
||||
def get_logo(lo):
|
||||
def get_logo(lo: str) -> str:
|
||||
"""Get a logo."""
|
||||
if "logo_" not in lo:
|
||||
lo = "logo_" + lo
|
||||
return globals()[lo] if lo in globals() else logo_alligator2
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
"""J.A.R.V.I.S. background task handlers."""
|
||||
from jarvis.tasks import unban
|
||||
from jarvis.tasks import unlock
|
||||
from jarvis.tasks import unmute
|
||||
from jarvis.tasks import unwarn
|
||||
|
||||
|
||||
def init():
|
||||
def init() -> None:
|
||||
"""Start the background task handlers."""
|
||||
unban.unban.start()
|
||||
unlock.unlock.start()
|
||||
unmute.unmute.start()
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. unban background task handler."""
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
|
@ -12,7 +13,8 @@ jarvis_id = get_config().client_id
|
|||
|
||||
|
||||
@loop(minutes=10)
|
||||
async def unban():
|
||||
async def unban() -> None:
|
||||
"""J.A.R.V.I.S. unban background task."""
|
||||
bans = Ban.objects(type="temp", active=True)
|
||||
unbans = []
|
||||
for ban in bans:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. unlock background task handler."""
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
|
@ -8,7 +9,8 @@ from jarvis.db.models import Lock
|
|||
|
||||
|
||||
@loop(minutes=1)
|
||||
async def unlock():
|
||||
async def unlock() -> None:
|
||||
"""J.A.R.V.I.S. unlock background task."""
|
||||
locks = Lock.objects(active=True)
|
||||
for lock in locks:
|
||||
if lock.created_at + timedelta(minutes=lock.duration) < datetime.utcnow():
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""J.A.R.V.I.S. unmute background task handler."""
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
|
@ -9,7 +10,8 @@ from jarvis.db.models import Setting
|
|||
|
||||
|
||||
@loop(minutes=1)
|
||||
async def unmute():
|
||||
async def unmute() -> None:
|
||||
"""J.A.R.V.I.S. unmute background task."""
|
||||
mutes = Mute.objects(duration__gt=0, active=True)
|
||||
mute_roles = Setting.objects(setting="mute")
|
||||
for mute in mutes:
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
"""J.A.R.V.I.S. unwarn background task handler."""
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
from discord.ext.tasks import loop
|
||||
|
||||
import jarvis
|
||||
from jarvis.db.models import Warning
|
||||
|
||||
|
||||
@loop(hours=1)
|
||||
async def unwarn():
|
||||
async def unwarn() -> None:
|
||||
"""J.A.R.V.I.S. unwarn background task."""
|
||||
warns = Warning.objects(active=True)
|
||||
for warn in warns:
|
||||
if warn.created_at + timedelta(hours=warn.duration) < datetime.utcnow():
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
"""J.A.R.V.I.S. Utility Functions."""
|
||||
from datetime import datetime
|
||||
from pkgutil import iter_modules
|
||||
|
||||
import git
|
||||
from discord import Color
|
||||
from discord import Embed
|
||||
from discord import Message
|
||||
from discord.ext import commands
|
||||
|
||||
import jarvis.cogs
|
||||
|
@ -13,17 +15,19 @@ from jarvis.config import get_config
|
|||
__all__ = ["field", "db", "cachecog", "permissions"]
|
||||
|
||||
|
||||
def convert_bytesize(bytes: int) -> str:
|
||||
bytes = float(bytes)
|
||||
def convert_bytesize(b: int) -> str:
|
||||
"""Convert bytes amount to human readable."""
|
||||
b = float(b)
|
||||
sizes = ["B", "KB", "MB", "GB", "TB", "PB"]
|
||||
size = 0
|
||||
while bytes >= 1024 and size < len(sizes) - 1:
|
||||
bytes = bytes / 1024
|
||||
while b >= 1024 and size < len(sizes) - 1:
|
||||
b = b / 1024
|
||||
size += 1
|
||||
return "{:0.3f} {}".format(bytes, sizes[size])
|
||||
return "{:0.3f} {}".format(b, sizes[size])
|
||||
|
||||
|
||||
def unconvert_bytesize(size, ending: str):
|
||||
def unconvert_bytesize(size: int, ending: str) -> int:
|
||||
"""Convert human readable to bytes."""
|
||||
ending = ending.upper()
|
||||
sizes = ["B", "KB", "MB", "GB", "TB", "PB"]
|
||||
if ending == "B":
|
||||
|
@ -32,7 +36,8 @@ def unconvert_bytesize(size, ending: str):
|
|||
return round(size * (1024 ** sizes.index(ending)))
|
||||
|
||||
|
||||
def get_prefix(bot, message):
|
||||
def get_prefix(bot: commands.Bot, message: Message) -> list:
|
||||
"""Get bot prefixes."""
|
||||
prefixes = ["!", "-", "%"]
|
||||
# if not message.guild:
|
||||
# return "?"
|
||||
|
@ -40,13 +45,15 @@ def get_prefix(bot, message):
|
|||
return commands.when_mentioned_or(*prefixes)(bot, message)
|
||||
|
||||
|
||||
def get_extensions(path=jarvis.cogs.__path__) -> list:
|
||||
def get_extensions(path: str = jarvis.cogs.__path__) -> list:
|
||||
"""Get J.A.R.V.I.S. cogs."""
|
||||
config = get_config()
|
||||
vals = config.cogs or [x.name for x in iter_modules(path)]
|
||||
return ["jarvis.cogs.{}".format(x) for x in vals]
|
||||
|
||||
|
||||
def parse_color_hex(hex: str) -> Color:
|
||||
"""Convert a hex color to a d.py Color."""
|
||||
hex = hex.lstrip("#")
|
||||
rgb = tuple(int(hex[i : i + 2], 16) for i in (0, 2, 4)) # noqa: E203
|
||||
return Color.from_rgb(*rgb)
|
||||
|
@ -58,8 +65,9 @@ def build_embed(
|
|||
fields: list,
|
||||
color: str = "#FF0000",
|
||||
timestamp: datetime = None,
|
||||
**kwargs,
|
||||
**kwargs: dict,
|
||||
) -> Embed:
|
||||
"""Embed builder utility function."""
|
||||
if not timestamp:
|
||||
timestamp = datetime.utcnow()
|
||||
embed = Embed(
|
||||
|
@ -74,7 +82,8 @@ def build_embed(
|
|||
return embed
|
||||
|
||||
|
||||
def update():
|
||||
def update() -> int:
|
||||
"""J.A.R.V.I.S. update utility."""
|
||||
repo = git.Repo(".")
|
||||
dirty = repo.is_dirty()
|
||||
current_hash = repo.head.object.hexsha
|
||||
|
@ -88,6 +97,7 @@ def update():
|
|||
return 1
|
||||
|
||||
|
||||
def get_repo_hash():
|
||||
def get_repo_hash() -> str:
|
||||
"""J.A.R.V.I.S. current branch hash."""
|
||||
repo = git.Repo(".")
|
||||
return repo.head.object.hexsha
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
"""Cog wrapper for command caching."""
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
|
@ -8,24 +9,27 @@ from discord_slash import SlashContext
|
|||
|
||||
|
||||
class CacheCog(commands.Cog):
|
||||
"""Cog wrapper for command caching."""
|
||||
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.cache = {}
|
||||
self._expire_interaction.start()
|
||||
|
||||
def check_cache(self, ctx: SlashContext, **kwargs):
|
||||
def check_cache(self, ctx: SlashContext, **kwargs: dict) -> dict:
|
||||
"""Check the cache."""
|
||||
if not kwargs:
|
||||
kwargs = {}
|
||||
return find(
|
||||
lambda x: x["command"] == ctx.subcommand_name
|
||||
and x["user"] == ctx.author.id
|
||||
and x["guild"] == ctx.guild.id
|
||||
and all(x[k] == v for k, v in kwargs.items()),
|
||||
lambda x: x["command"] == ctx.subcommand_name # noqa: W503
|
||||
and x["user"] == ctx.author.id # noqa: W503
|
||||
and x["guild"] == ctx.guild.id # noqa: W503
|
||||
and all(x[k] == v for k, v in kwargs.items()), # noqa: W503
|
||||
self.cache.values(),
|
||||
)
|
||||
|
||||
@loop(minutes=1)
|
||||
async def _expire_interaction(self):
|
||||
async def _expire_interaction(self) -> None:
|
||||
keys = list(self.cache.keys())
|
||||
for key in keys:
|
||||
if self.cache[key]["timeout"] <= datetime.utcnow() + timedelta(minutes=1):
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
"""Embed field helper."""
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
|
||||
@dataclass
|
||||
class Field:
|
||||
"""Embed Field."""
|
||||
|
||||
name: Any
|
||||
value: Any
|
||||
inline: bool = True
|
||||
|
||||
def to_dict(self):
|
||||
def to_dict(self) -> dict:
|
||||
"""Convert Field to d.py field dict."""
|
||||
return {"name": self.name, "value": self.value, "inline": self.inline}
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
"""Permissions wrappers."""
|
||||
from discord.ext import commands
|
||||
|
||||
from jarvis.config import get_config
|
||||
|
||||
|
||||
def user_is_bot_admin():
|
||||
def predicate(ctx):
|
||||
def user_is_bot_admin() -> bool:
|
||||
"""Check if a user is a J.A.R.V.I.S. admin."""
|
||||
|
||||
def predicate(ctx: commands.Context) -> bool:
|
||||
"""Command check predicate."""
|
||||
if getattr(get_config(), "admins", None):
|
||||
return ctx.author.id in get_config().admins
|
||||
else:
|
||||
|
@ -13,10 +17,12 @@ def user_is_bot_admin():
|
|||
return commands.check(predicate)
|
||||
|
||||
|
||||
def admin_or_permissions(**perms):
|
||||
def admin_or_permissions(**perms: dict) -> bool:
|
||||
"""Check if a user is an admin or has other perms."""
|
||||
original = commands.has_permissions(**perms).predicate
|
||||
|
||||
async def extended_check(ctx):
|
||||
async def extended_check(ctx: commands.Context) -> bool:
|
||||
"""Extended check predicate.""" # noqa: D401
|
||||
return await commands.has_permissions(administrator=True).predicate(ctx) or await original(ctx)
|
||||
|
||||
return commands.check(extended_check)
|
||||
|
|
1
run.py
1
run.py
|
@ -1,4 +1,5 @@
|
|||
#!/bin/python3
|
||||
# flake8: noqa
|
||||
from importlib import reload as ireload
|
||||
from multiprocessing import freeze_support
|
||||
from multiprocessing import Process
|
||||
|
|
Loading…
Add table
Reference in a new issue