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