Reorganize commands for future opt-in structure
This commit is contained in:
parent
0a096e4831
commit
fe3ef1ad35
24 changed files with 143 additions and 278 deletions
11
jarvis/cogs/core/__init__.py
Normal file
11
jarvis/cogs/core/__init__.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
"""JARVIS Core Cogs."""
|
||||||
|
from naff import Client
|
||||||
|
|
||||||
|
from jarvis.cogs.core import admin, botutil, socials
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot: Client) -> None:
|
||||||
|
"""Add core cogs to JARVIS"""
|
||||||
|
admin.setup(bot)
|
||||||
|
botutil.setup(bot)
|
||||||
|
socials.setup(bot)
|
|
@ -3,7 +3,8 @@ import logging
|
||||||
|
|
||||||
from naff import Client
|
from naff import Client
|
||||||
|
|
||||||
from jarvis.cogs.admin import (
|
from jarvis.cogs.core.admin import (
|
||||||
|
autoreact,
|
||||||
ban,
|
ban,
|
||||||
filters,
|
filters,
|
||||||
kick,
|
kick,
|
||||||
|
@ -13,6 +14,9 @@ from jarvis.cogs.admin import (
|
||||||
mute,
|
mute,
|
||||||
purge,
|
purge,
|
||||||
roleping,
|
roleping,
|
||||||
|
settings,
|
||||||
|
temprole,
|
||||||
|
verify,
|
||||||
warning,
|
warning,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,8 +25,12 @@ def setup(bot: Client) -> None:
|
||||||
"""Add admin cogs to JARVIS"""
|
"""Add admin cogs to JARVIS"""
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
msg = "Loaded jarvis.cogs.admin.{}"
|
msg = "Loaded jarvis.cogs.admin.{}"
|
||||||
|
autoreact.AutoReactCog(bot)
|
||||||
|
logger.debug(msg.format("autoreact"))
|
||||||
ban.BanCog(bot)
|
ban.BanCog(bot)
|
||||||
logger.debug(msg.format("ban"))
|
logger.debug(msg.format("ban"))
|
||||||
|
filters.FilterCog(bot)
|
||||||
|
logger.debug(msg.format("filters"))
|
||||||
kick.KickCog(bot)
|
kick.KickCog(bot)
|
||||||
logger.debug(msg.format("kick"))
|
logger.debug(msg.format("kick"))
|
||||||
lock.LockCog(bot)
|
lock.LockCog(bot)
|
||||||
|
@ -37,7 +45,11 @@ def setup(bot: Client) -> None:
|
||||||
logger.debug(msg.format("purge"))
|
logger.debug(msg.format("purge"))
|
||||||
roleping.RolepingCog(bot)
|
roleping.RolepingCog(bot)
|
||||||
logger.debug(msg.format("roleping"))
|
logger.debug(msg.format("roleping"))
|
||||||
|
settings.SettingsCog(bot)
|
||||||
|
logger.debug(msg.format("settings"))
|
||||||
|
temprole.TemproleCog(bot)
|
||||||
|
logger.debug(msg.format("temprole"))
|
||||||
|
verify.VerifyCog(bot)
|
||||||
|
logger.debug(msg.format("verify"))
|
||||||
warning.WarningCog(bot)
|
warning.WarningCog(bot)
|
||||||
logger.debug(msg.format("warning"))
|
logger.debug(msg.format("warning"))
|
||||||
filters.FilterCog(bot)
|
|
||||||
logger.debug(msg.format("filters"))
|
|
|
@ -84,12 +84,8 @@ class AutoReactCog(Extension):
|
||||||
opt_type=OptionTypes.CHANNEL,
|
opt_type=OptionTypes.CHANNEL,
|
||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(name="thread", description="Create a thread?", opt_type=OptionTypes.BOOLEAN, required=False)
|
||||||
name="thread", description="Create a thread?", opt_type=OptionTypes.BOOLEAN, required=False
|
@slash_option(name="emote", description="Emote to add", opt_type=OptionTypes.STRING, required=False)
|
||||||
)
|
|
||||||
@slash_option(
|
|
||||||
name="emote", description="Emote to add", opt_type=OptionTypes.STRING, required=False
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||||
async def _autoreact_add(
|
async def _autoreact_add(
|
||||||
self, ctx: InteractionContext, channel: GuildText, thread: bool = True, emote: str = None
|
self, ctx: InteractionContext, channel: GuildText, thread: bool = True, emote: str = None
|
||||||
|
@ -152,9 +148,7 @@ class AutoReactCog(Extension):
|
||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||||
async def _autoreact_remove(
|
async def _autoreact_remove(self, ctx: InteractionContext, channel: GuildText, emote: str) -> None:
|
||||||
self, ctx: InteractionContext, channel: GuildText, emote: str
|
|
||||||
) -> None:
|
|
||||||
autoreact = await Autoreact.find_one(q(guild=ctx.guild.id, channel=channel.id))
|
autoreact = await Autoreact.find_one(q(guild=ctx.guild.id, channel=channel.id))
|
||||||
if not autoreact:
|
if not autoreact:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
|
@ -216,9 +210,7 @@ class AutoReactCog(Extension):
|
||||||
return
|
return
|
||||||
message = ""
|
message = ""
|
||||||
if len(exists.reactions) > 0:
|
if len(exists.reactions) > 0:
|
||||||
message = f"Current active autoreacts on {channel.mention}:\n" + "\n".join(
|
message = f"Current active autoreacts on {channel.mention}:\n" + "\n".join(exists.reactions)
|
||||||
exists.reactions
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
message = f"No reactions set on {channel.mention}"
|
message = f"No reactions set on {channel.mention}"
|
||||||
await ctx.send(message)
|
await ctx.send(message)
|
|
@ -163,6 +163,12 @@ class BanCog(ModcaseCog):
|
||||||
if mtype == "temp":
|
if mtype == "temp":
|
||||||
user_message += f"\nDuration: {duration} hours"
|
user_message += f"\nDuration: {duration} hours"
|
||||||
|
|
||||||
|
if btype != "temp":
|
||||||
|
duration = None
|
||||||
|
active = True
|
||||||
|
if btype == "soft":
|
||||||
|
active = False
|
||||||
|
|
||||||
user_embed = ban_embed(
|
user_embed = ban_embed(
|
||||||
user=user,
|
user=user,
|
||||||
admin=ctx.author,
|
admin=ctx.author,
|
||||||
|
@ -186,12 +192,6 @@ class BanCog(ModcaseCog):
|
||||||
if mtype == "soft":
|
if mtype == "soft":
|
||||||
await ctx.guild.unban(user, reason="Ban was softban")
|
await ctx.guild.unban(user, reason="Ban was softban")
|
||||||
|
|
||||||
if btype != "temp":
|
|
||||||
duration = None
|
|
||||||
active = True
|
|
||||||
if btype == "soft":
|
|
||||||
active = False
|
|
||||||
|
|
||||||
@slash_command(name="unban", description="Unban a user")
|
@slash_command(name="unban", description="Unban a user")
|
||||||
@slash_option(name="user", description="User to unban", opt_type=OptionTypes.STRING, required=True)
|
@slash_option(name="user", description="User to unban", opt_type=OptionTypes.STRING, required=True)
|
||||||
@slash_option(name="reason", description="Unban reason", opt_type=OptionTypes.STRING, required=True)
|
@slash_option(name="reason", description="Unban reason", opt_type=OptionTypes.STRING, required=True)
|
|
@ -82,9 +82,7 @@ class FilterCog(Extension):
|
||||||
filter_ = SlashCommand(name="filter", description="Manage keyword filters")
|
filter_ = SlashCommand(name="filter", description="Manage keyword filters")
|
||||||
|
|
||||||
@filter_.subcommand(sub_cmd_name="create", sub_cmd_description="Create a new filter")
|
@filter_.subcommand(sub_cmd_name="create", sub_cmd_description="Create a new filter")
|
||||||
@slash_option(
|
@slash_option(name="name", description="Name of new filter", required=True, opt_type=OptionTypes.STRING)
|
||||||
name="name", description="Name of new filter", required=True, opt_type=OptionTypes.STRING
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
|
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
|
||||||
async def _filter_create(self, ctx: InteractionContext, name: str) -> None:
|
async def _filter_create(self, ctx: InteractionContext, name: str) -> None:
|
||||||
return await self._edit_filter(ctx, name)
|
return await self._edit_filter(ctx, name)
|
|
@ -19,9 +19,7 @@ class KickCog(ModcaseCog):
|
||||||
|
|
||||||
@slash_command(name="kick", description="Kick a user")
|
@slash_command(name="kick", description="Kick a user")
|
||||||
@slash_option(name="user", description="User to kick", opt_type=OptionTypes.USER, required=True)
|
@slash_option(name="user", description="User to kick", opt_type=OptionTypes.USER, required=True)
|
||||||
@slash_option(
|
@slash_option(name="reason", description="Kick reason", opt_type=OptionTypes.STRING, required=True)
|
||||||
name="reason", description="Kick reason", opt_type=OptionTypes.STRING, required=True
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||||
async def _kick(self, ctx: InteractionContext, user: User, reason: str) -> None:
|
async def _kick(self, ctx: InteractionContext, user: User, reason: str) -> None:
|
||||||
if not user or user == ctx.author:
|
if not user or user == ctx.author:
|
|
@ -19,9 +19,7 @@ from naff.models.naff.command import check
|
||||||
from jarvis.utils.permissions import admin_or_permissions
|
from jarvis.utils.permissions import admin_or_permissions
|
||||||
|
|
||||||
|
|
||||||
async def lock(
|
async def lock(bot: Client, target: GuildChannel, admin: Member, reason: str, duration: int) -> None:
|
||||||
bot: Client, target: GuildChannel, admin: Member, reason: str, duration: int
|
|
||||||
) -> None:
|
|
||||||
"""
|
"""
|
||||||
Lock an existing channel
|
Lock an existing channel
|
||||||
|
|
||||||
|
@ -110,9 +108,7 @@ class LockdownCog(Extension):
|
||||||
sub_cmd_name="start",
|
sub_cmd_name="start",
|
||||||
sub_cmd_description="Lockdown the server",
|
sub_cmd_description="Lockdown the server",
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(name="reason", description="Lockdown reason", opt_type=OptionTypes.STRING, required=True)
|
||||||
name="reason", description="Lockdown reason", opt_type=OptionTypes.STRING, required=True
|
|
||||||
)
|
|
||||||
@slash_option(
|
@slash_option(
|
||||||
name="duration",
|
name="duration",
|
||||||
description="Duration in minutes",
|
description="Duration in minutes",
|
|
@ -114,9 +114,7 @@ class CaseCog(Extension):
|
||||||
note_output = f"```ansi\n{note_output}\n{note_output_extra}\n```"
|
note_output = f"```ansi\n{note_output}\n{note_output_extra}\n```"
|
||||||
|
|
||||||
fields = (
|
fields = (
|
||||||
EmbedField(
|
EmbedField(name="Actions", value=action_output if mod_case.actions else "No Actions Found"),
|
||||||
name="Actions", value=action_output if mod_case.actions else "No Actions Found"
|
|
||||||
),
|
|
||||||
EmbedField(name="Notes", value=note_output if mod_case.notes else "No Notes Found"),
|
EmbedField(name="Notes", value=note_output if mod_case.notes else "No Notes Found"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -196,9 +194,7 @@ class CaseCog(Extension):
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||||
async def _cases_list(
|
async def _cases_list(self, ctx: InteractionContext, user: Optional[Member] = None, closed: bool = False) -> None:
|
||||||
self, ctx: InteractionContext, user: Optional[Member] = None, closed: bool = False
|
|
||||||
) -> None:
|
|
||||||
query = q(guild=ctx.guild.id)
|
query = q(guild=ctx.guild.id)
|
||||||
if not closed:
|
if not closed:
|
||||||
query.update(q(open=True))
|
query.update(q(open=True))
|
||||||
|
@ -274,9 +270,7 @@ class CaseCog(Extension):
|
||||||
|
|
||||||
@case.subcommand(sub_cmd_name="note", sub_cmd_description="Add a note to a specific case")
|
@case.subcommand(sub_cmd_name="note", sub_cmd_description="Add a note to a specific case")
|
||||||
@slash_option(name="cid", description="Case ID", opt_type=OptionTypes.STRING, required=True)
|
@slash_option(name="cid", description="Case ID", opt_type=OptionTypes.STRING, required=True)
|
||||||
@slash_option(
|
@slash_option(name="note", description="Note to add", opt_type=OptionTypes.STRING, required=True)
|
||||||
name="note", description="Note to add", opt_type=OptionTypes.STRING, required=True
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||||
async def _case_note(self, ctx: InteractionContext, cid: str, note: str) -> None:
|
async def _case_note(self, ctx: InteractionContext, cid: str, note: str) -> None:
|
||||||
case = await Modlog.find_one(q(guild=ctx.guild.id, nanoid=cid))
|
case = await Modlog.find_one(q(guild=ctx.guild.id, nanoid=cid))
|
||||||
|
@ -302,9 +296,7 @@ class CaseCog(Extension):
|
||||||
|
|
||||||
@case.subcommand(sub_cmd_name="new", sub_cmd_description="Open a new case")
|
@case.subcommand(sub_cmd_name="new", sub_cmd_description="Open a new case")
|
||||||
@slash_option(name="user", description="Target user", opt_type=OptionTypes.USER, required=True)
|
@slash_option(name="user", description="Target user", opt_type=OptionTypes.USER, required=True)
|
||||||
@slash_option(
|
@slash_option(name="note", description="Note to add", opt_type=OptionTypes.STRING, required=True)
|
||||||
name="note", description="Note to add", opt_type=OptionTypes.STRING, required=True
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||||
async def _case_new(self, ctx: InteractionContext, user: Member, note: str) -> None:
|
async def _case_new(self, ctx: InteractionContext, user: Member, note: str) -> None:
|
||||||
case = await Modlog.find_one(q(guild=ctx.guild.id, user=user.id, open=True))
|
case = await Modlog.find_one(q(guild=ctx.guild.id, user=user.id, open=True))
|
||||||
|
@ -322,9 +314,7 @@ class CaseCog(Extension):
|
||||||
|
|
||||||
note = Note(admin=ctx.author.id, content=note)
|
note = Note(admin=ctx.author.id, content=note)
|
||||||
|
|
||||||
case = Modlog(
|
case = Modlog(user=user.id, guild=ctx.guild.id, admin=ctx.author.id, notes=[note], actions=[])
|
||||||
user=user.id, guild=ctx.guild.id, admin=ctx.author.id, notes=[note], actions=[]
|
|
||||||
)
|
|
||||||
await case.commit()
|
await case.commit()
|
||||||
await case.reload()
|
await case.reload()
|
||||||
|
|
|
@ -27,9 +27,7 @@ from jarvis.utils.permissions import admin_or_permissions
|
||||||
class MuteCog(ModcaseCog):
|
class MuteCog(ModcaseCog):
|
||||||
"""JARVIS MuteCog."""
|
"""JARVIS MuteCog."""
|
||||||
|
|
||||||
async def _apply_timeout(
|
async def _apply_timeout(self, ctx: InteractionContext, user: Member, reason: str, until: datetime) -> None:
|
||||||
self, ctx: InteractionContext, user: Member, reason: str, until: datetime
|
|
||||||
) -> None:
|
|
||||||
await user.timeout(communication_disabled_until=until, reason=reason)
|
await user.timeout(communication_disabled_until=until, reason=reason)
|
||||||
duration = int((until - datetime.now(tz=timezone.utc)).seconds / 60)
|
duration = int((until - datetime.now(tz=timezone.utc)).seconds / 60)
|
||||||
await Mute(
|
await Mute(
|
||||||
|
@ -44,11 +42,7 @@ class MuteCog(ModcaseCog):
|
||||||
return mute_embed(user=user, admin=ctx.author, reason=reason, guild=ctx.guild)
|
return mute_embed(user=user, admin=ctx.author, reason=reason, guild=ctx.guild)
|
||||||
|
|
||||||
@context_menu(name="Mute User", context_type=CommandTypes.USER)
|
@context_menu(name="Mute User", context_type=CommandTypes.USER)
|
||||||
@check(
|
@check(admin_or_permissions(Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS))
|
||||||
admin_or_permissions(
|
|
||||||
Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS
|
|
||||||
)
|
|
||||||
)
|
|
||||||
async def _timeout_cm(self, ctx: InteractionContext) -> None:
|
async def _timeout_cm(self, ctx: InteractionContext) -> None:
|
||||||
modal = Modal(
|
modal = Modal(
|
||||||
title=f"Muting {ctx.target.mention}",
|
title=f"Muting {ctx.target.mention}",
|
||||||
|
@ -82,9 +76,7 @@ class MuteCog(ModcaseCog):
|
||||||
"RETURN_AS_TIMEZONE_AWARE": True,
|
"RETURN_AS_TIMEZONE_AWARE": True,
|
||||||
}
|
}
|
||||||
rt_settings = base_settings.copy()
|
rt_settings = base_settings.copy()
|
||||||
rt_settings["PARSERS"] = [
|
rt_settings["PARSERS"] = [x for x in default_parsers if x not in ["absolute-time", "timestamp"]]
|
||||||
x for x in default_parsers if x not in ["absolute-time", "timestamp"]
|
|
||||||
]
|
|
||||||
|
|
||||||
rt_until = parse(until, settings=rt_settings)
|
rt_until = parse(until, settings=rt_settings)
|
||||||
|
|
||||||
|
@ -99,14 +91,10 @@ class MuteCog(ModcaseCog):
|
||||||
until = at_until
|
until = at_until
|
||||||
else:
|
else:
|
||||||
self.logger.debug(f"Failed to parse delay: {until}")
|
self.logger.debug(f"Failed to parse delay: {until}")
|
||||||
await response.send(
|
await response.send(f"`{until}` is not a parsable date, please try again", ephemeral=True)
|
||||||
f"`{until}` is not a parsable date, please try again", ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
if until < datetime.now(tz=timezone.utc):
|
if until < datetime.now(tz=timezone.utc):
|
||||||
await response.send(
|
await response.send(f"`{old_until}` is in the past, which isn't allowed", ephemeral=True)
|
||||||
f"`{old_until}` is in the past, which isn't allowed", ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
embed = await self._apply_timeout(ctx, ctx.target, reason, until)
|
embed = await self._apply_timeout(ctx, ctx.target, reason, until)
|
||||||
|
@ -140,11 +128,7 @@ class MuteCog(ModcaseCog):
|
||||||
SlashCommandChoice(name="Week(s)", value=10080),
|
SlashCommandChoice(name="Week(s)", value=10080),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@check(
|
@check(admin_or_permissions(Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS))
|
||||||
admin_or_permissions(
|
|
||||||
Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS
|
|
||||||
)
|
|
||||||
)
|
|
||||||
async def _timeout(
|
async def _timeout(
|
||||||
self, ctx: InteractionContext, user: Member, reason: str, time: int = 1, scale: int = 60
|
self, ctx: InteractionContext, user: Member, reason: str, time: int = 1, scale: int = 60
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -175,22 +159,13 @@ class MuteCog(ModcaseCog):
|
||||||
await ctx.send("Unable to mute this user", ephemeral=True)
|
await ctx.send("Unable to mute this user", ephemeral=True)
|
||||||
|
|
||||||
@slash_command(name="unmute", description="Unmute a user")
|
@slash_command(name="unmute", description="Unmute a user")
|
||||||
@slash_option(
|
@slash_option(name="user", description="User to unmute", opt_type=OptionTypes.USER, required=True)
|
||||||
name="user", description="User to unmute", opt_type=OptionTypes.USER, required=True
|
@slash_option(name="reason", description="Reason for unmute", opt_type=OptionTypes.STRING, required=True)
|
||||||
)
|
@check(admin_or_permissions(Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS))
|
||||||
@slash_option(
|
|
||||||
name="reason", description="Reason for unmute", opt_type=OptionTypes.STRING, required=True
|
|
||||||
)
|
|
||||||
@check(
|
|
||||||
admin_or_permissions(
|
|
||||||
Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS
|
|
||||||
)
|
|
||||||
)
|
|
||||||
async def _unmute(self, ctx: InteractionContext, user: Member, reason: str) -> None:
|
async def _unmute(self, ctx: InteractionContext, user: Member, reason: str) -> None:
|
||||||
if (
|
if (
|
||||||
not user.communication_disabled_until
|
not user.communication_disabled_until
|
||||||
or user.communication_disabled_until.timestamp()
|
or user.communication_disabled_until.timestamp() < datetime.now(tz=timezone.utc).timestamp() # noqa: W503
|
||||||
< datetime.now(tz=timezone.utc).timestamp() # noqa: W503
|
|
||||||
):
|
):
|
||||||
await ctx.send("User is not muted", ephemeral=True)
|
await ctx.send("User is not muted", ephemeral=True)
|
||||||
return
|
return
|
|
@ -47,9 +47,7 @@ class PurgeCog(Extension):
|
||||||
count=amount,
|
count=amount,
|
||||||
).commit()
|
).commit()
|
||||||
|
|
||||||
@slash_command(
|
@slash_command(name="autopurge", sub_cmd_name="add", sub_cmd_description="Automatically purge messages")
|
||||||
name="autopurge", sub_cmd_name="add", sub_cmd_description="Automatically purge messages"
|
|
||||||
)
|
|
||||||
@slash_option(
|
@slash_option(
|
||||||
name="channel",
|
name="channel",
|
||||||
description="Channel to autopurge",
|
description="Channel to autopurge",
|
||||||
|
@ -63,9 +61,7 @@ class PurgeCog(Extension):
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
|
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
|
||||||
async def _autopurge_add(
|
async def _autopurge_add(self, ctx: InteractionContext, channel: GuildText, delay: int = 30) -> None:
|
||||||
self, ctx: InteractionContext, channel: GuildText, delay: int = 30
|
|
||||||
) -> None:
|
|
||||||
if not isinstance(channel, GuildText):
|
if not isinstance(channel, GuildText):
|
||||||
await ctx.send("Channel must be a GuildText channel", ephemeral=True)
|
await ctx.send("Channel must be a GuildText channel", ephemeral=True)
|
||||||
return
|
return
|
||||||
|
@ -90,9 +86,7 @@ class PurgeCog(Extension):
|
||||||
|
|
||||||
await ctx.send(f"Autopurge set up on {channel.mention}, delay is {delay} seconds")
|
await ctx.send(f"Autopurge set up on {channel.mention}, delay is {delay} seconds")
|
||||||
|
|
||||||
@slash_command(
|
@slash_command(name="autopurge", sub_cmd_name="remove", sub_cmd_description="Remove an autopurge")
|
||||||
name="autopurge", sub_cmd_name="remove", sub_cmd_description="Remove an autopurge"
|
|
||||||
)
|
|
||||||
@slash_option(
|
@slash_option(
|
||||||
name="channel",
|
name="channel",
|
||||||
description="Channel to remove from autopurge",
|
description="Channel to remove from autopurge",
|
||||||
|
@ -126,9 +120,7 @@ class PurgeCog(Extension):
|
||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
|
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
|
||||||
async def _autopurge_update(
|
async def _autopurge_update(self, ctx: InteractionContext, channel: GuildText, delay: int) -> None:
|
||||||
self, ctx: InteractionContext, channel: GuildText, delay: int
|
|
||||||
) -> None:
|
|
||||||
autopurge = await Autopurge.find_one(q(guild=ctx.guild.id, channel=channel.id))
|
autopurge = await Autopurge.find_one(q(guild=ctx.guild.id, channel=channel.id))
|
||||||
if not autopurge:
|
if not autopurge:
|
||||||
await ctx.send("Autopurge does not exist.", ephemeral=True)
|
await ctx.send("Autopurge does not exist.", ephemeral=True)
|
|
@ -27,9 +27,7 @@ class RolepingCog(Extension):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
roleping = SlashCommand(
|
roleping = SlashCommand(name="roleping", description="Set up warnings for pinging specific roles")
|
||||||
name="roleping", description="Set up warnings for pinging specific roles"
|
|
||||||
)
|
|
||||||
|
|
||||||
@roleping.subcommand(
|
@roleping.subcommand(
|
||||||
sub_cmd_name="add",
|
sub_cmd_name="add",
|
||||||
|
@ -57,9 +55,7 @@ class RolepingCog(Extension):
|
||||||
await ctx.send(f"Role `{role.name}` added to roleping.")
|
await ctx.send(f"Role `{role.name}` added to roleping.")
|
||||||
|
|
||||||
@roleping.subcommand(sub_cmd_name="remove", sub_cmd_description="Remove a role")
|
@roleping.subcommand(sub_cmd_name="remove", sub_cmd_description="Remove a role")
|
||||||
@slash_option(
|
@slash_option(name="role", description="Role to remove", opt_type=OptionTypes.ROLE, required=True)
|
||||||
name="role", description="Role to remove", opt_type=OptionTypes.ROLE, required=True
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||||
async def _roleping_remove(self, ctx: InteractionContext, role: Role) -> None:
|
async def _roleping_remove(self, ctx: InteractionContext, role: Role) -> None:
|
||||||
roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
|
roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
|
||||||
|
@ -87,11 +83,10 @@ class RolepingCog(Extension):
|
||||||
if not role:
|
if not role:
|
||||||
await roleping.delete()
|
await roleping.delete()
|
||||||
continue
|
continue
|
||||||
broles = find_all(lambda x: x.id in roleping.bypass["roles"], ctx.guild.roles)
|
broles = find_all(lambda x: x.id in roleping.bypass["roles"], ctx.guild.roles) # noqa: B023
|
||||||
bypass_roles = [r.mention or "||`[redacted]`||" for r in broles]
|
bypass_roles = [r.mention or "||`[redacted]`||" for r in broles]
|
||||||
bypass_users = [
|
bypass_users = [
|
||||||
(await ctx.guild.fetch_member(u)).mention or "||`[redacted]`||"
|
(await ctx.guild.fetch_member(u)).mention or "||`[redacted]`||" for u in roleping.bypass["users"]
|
||||||
for u in roleping.bypass["users"]
|
|
||||||
]
|
]
|
||||||
bypass_roles = bypass_roles or ["None"]
|
bypass_roles = bypass_roles or ["None"]
|
||||||
bypass_users = bypass_users or ["None"]
|
bypass_users = bypass_users or ["None"]
|
||||||
|
@ -132,24 +127,16 @@ class RolepingCog(Extension):
|
||||||
|
|
||||||
await paginator.send(ctx)
|
await paginator.send(ctx)
|
||||||
|
|
||||||
bypass = roleping.group(
|
bypass = roleping.group(name="bypass", description="Allow specific users/roles to ping rolepings")
|
||||||
name="bypass", description="Allow specific users/roles to ping rolepings"
|
|
||||||
)
|
|
||||||
|
|
||||||
@bypass.subcommand(
|
@bypass.subcommand(
|
||||||
sub_cmd_name="user",
|
sub_cmd_name="user",
|
||||||
sub_cmd_description="Add a user as a bypass to a roleping",
|
sub_cmd_description="Add a user as a bypass to a roleping",
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(name="bypass", description="User to add", opt_type=OptionTypes.USER, required=True)
|
||||||
name="bypass", description="User to add", opt_type=OptionTypes.USER, required=True
|
@slash_option(name="role", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True)
|
||||||
)
|
|
||||||
@slash_option(
|
|
||||||
name="role", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||||
async def _roleping_bypass_user(
|
async def _roleping_bypass_user(self, ctx: InteractionContext, bypass: Member, role: Role) -> None:
|
||||||
self, ctx: InteractionContext, bypass: Member, role: Role
|
|
||||||
) -> None:
|
|
||||||
roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
|
roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
|
||||||
if not roleping:
|
if not roleping:
|
||||||
await ctx.send(f"Roleping not configured for {role.mention}", ephemeral=True)
|
await ctx.send(f"Roleping not configured for {role.mention}", ephemeral=True)
|
||||||
|
@ -183,16 +170,10 @@ class RolepingCog(Extension):
|
||||||
sub_cmd_name="role",
|
sub_cmd_name="role",
|
||||||
sub_cmd_description="Add a role as a bypass to roleping",
|
sub_cmd_description="Add a role as a bypass to roleping",
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(name="bypass", description="Role to add", opt_type=OptionTypes.ROLE, required=True)
|
||||||
name="bypass", description="Role to add", opt_type=OptionTypes.ROLE, required=True
|
@slash_option(name="role", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True)
|
||||||
)
|
|
||||||
@slash_option(
|
|
||||||
name="role", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||||
async def _roleping_bypass_role(
|
async def _roleping_bypass_role(self, ctx: InteractionContext, bypass: Role, role: Role) -> None:
|
||||||
self, ctx: InteractionContext, bypass: Role, role: Role
|
|
||||||
) -> None:
|
|
||||||
if bypass.id == ctx.guild.id:
|
if bypass.id == ctx.guild.id:
|
||||||
await ctx.send("Cannot add `@everyone` as a bypass", ephemeral=True)
|
await ctx.send("Cannot add `@everyone` as a bypass", ephemeral=True)
|
||||||
return
|
return
|
||||||
|
@ -207,8 +188,7 @@ class RolepingCog(Extension):
|
||||||
|
|
||||||
if len(roleping.bypass["roles"]) == 10:
|
if len(roleping.bypass["roles"]) == 10:
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"Already have 10 roles in bypass. "
|
"Already have 10 roles in bypass. " "Please consider consolidating roles for roleping bypass",
|
||||||
"Please consider consolidating roles for roleping bypass",
|
|
||||||
ephemeral=True,
|
ephemeral=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
@ -223,16 +203,10 @@ class RolepingCog(Extension):
|
||||||
sub_cmd_name="user",
|
sub_cmd_name="user",
|
||||||
sub_cmd_description="Remove a bypass from a roleping (restoring it)",
|
sub_cmd_description="Remove a bypass from a roleping (restoring it)",
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(name="bypass", description="User to remove", opt_type=OptionTypes.USER, required=True)
|
||||||
name="bypass", description="User to remove", opt_type=OptionTypes.USER, required=True
|
@slash_option(name="role", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True)
|
||||||
)
|
|
||||||
@slash_option(
|
|
||||||
name="role", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||||
async def _roleping_restore_user(
|
async def _roleping_restore_user(self, ctx: InteractionContext, bypass: Member, role: Role) -> None:
|
||||||
self, ctx: InteractionContext, bypass: Member, role: Role
|
|
||||||
) -> None:
|
|
||||||
roleping: Roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
|
roleping: Roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
|
||||||
if not roleping:
|
if not roleping:
|
||||||
await ctx.send(f"Roleping not configured for {role.mention}", ephemeral=True)
|
await ctx.send(f"Roleping not configured for {role.mention}", ephemeral=True)
|
||||||
|
@ -250,16 +224,10 @@ class RolepingCog(Extension):
|
||||||
sub_cmd_name="role",
|
sub_cmd_name="role",
|
||||||
sub_cmd_description="Remove a bypass from a roleping (restoring it)",
|
sub_cmd_description="Remove a bypass from a roleping (restoring it)",
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(name="bypass", description="Role to remove", opt_type=OptionTypes.ROLE, required=True)
|
||||||
name="bypass", description="Role to remove", opt_type=OptionTypes.ROLE, required=True
|
@slash_option(name="role", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True)
|
||||||
)
|
|
||||||
@slash_option(
|
|
||||||
name="role", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||||
async def _roleping_restore_role(
|
async def _roleping_restore_role(self, ctx: InteractionContext, bypass: Role, role: Role) -> None:
|
||||||
self, ctx: InteractionContext, bypass: Role, role: Role
|
|
||||||
) -> None:
|
|
||||||
roleping: Roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
|
roleping: Roleping = await Roleping.find_one(q(guild=ctx.guild.id, role=role.id))
|
||||||
if not roleping:
|
if not roleping:
|
||||||
await ctx.send(f"Roleping not configured for {role.mention}", ephemeral=True)
|
await ctx.send(f"Roleping not configured for {role.mention}", ephemeral=True)
|
|
@ -30,12 +30,8 @@ class TemproleCog(Extension):
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@slash_command(name="temprole", description="Give a user a temporary role")
|
@slash_command(name="temprole", description="Give a user a temporary role")
|
||||||
@slash_option(
|
@slash_option(name="user", description="User to grant role", opt_type=OptionTypes.USER, required=True)
|
||||||
name="user", description="User to grant role", opt_type=OptionTypes.USER, required=True
|
@slash_option(name="role", description="Role to grant", opt_type=OptionTypes.ROLE, required=True)
|
||||||
)
|
|
||||||
@slash_option(
|
|
||||||
name="role", description="Role to grant", opt_type=OptionTypes.ROLE, required=True
|
|
||||||
)
|
|
||||||
@slash_option(
|
@slash_option(
|
||||||
name="duration",
|
name="duration",
|
||||||
description="Duration of temp role (i.e. 2 hours)",
|
description="Duration of temp role (i.e. 2 hours)",
|
||||||
|
@ -74,9 +70,7 @@ class TemproleCog(Extension):
|
||||||
"RETURN_AS_TIMEZONE_AWARE": True,
|
"RETURN_AS_TIMEZONE_AWARE": True,
|
||||||
}
|
}
|
||||||
rt_settings = base_settings.copy()
|
rt_settings = base_settings.copy()
|
||||||
rt_settings["PARSERS"] = [
|
rt_settings["PARSERS"] = [x for x in default_parsers if x not in ["absolute-time", "timestamp"]]
|
||||||
x for x in default_parsers if x not in ["absolute-time", "timestamp"]
|
|
||||||
]
|
|
||||||
|
|
||||||
rt_duration = parse(duration, settings=rt_settings)
|
rt_duration = parse(duration, settings=rt_settings)
|
||||||
|
|
||||||
|
@ -94,9 +88,7 @@ class TemproleCog(Extension):
|
||||||
return
|
return
|
||||||
|
|
||||||
if duration < datetime.now(tz=timezone.utc):
|
if duration < datetime.now(tz=timezone.utc):
|
||||||
await ctx.send(
|
await ctx.send(f"`{duration}` is in the past. Past durations aren't allowed", ephemeral=True)
|
||||||
f"`{duration}` is in the past. Past durations aren't allowed", ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
await user.add_role(role, reason=reason)
|
await user.add_role(role, reason=reason)
|
||||||
|
@ -116,15 +108,6 @@ class TemproleCog(Extension):
|
||||||
description=f"Role temporarily granted to {user.mention}",
|
description=f"Role temporarily granted to {user.mention}",
|
||||||
fields=fields,
|
fields=fields,
|
||||||
)
|
)
|
||||||
embed.set_author(
|
embed.set_author(name=f"{user.username}#{user.discriminator}", icon_url=user.display_avatar.url)
|
||||||
name=f"{user.username}#{user.discriminator}", icon_url=user.display_avatar.url
|
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||||
)
|
|
||||||
components = Button(
|
|
||||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
|
||||||
)
|
|
||||||
await ctx.send(embeds=embed, components=components)
|
await ctx.send(embeds=embed, components=components)
|
||||||
|
|
||||||
|
|
||||||
def setup(bot: Client) -> None:
|
|
||||||
"""Add TemproleCog to JARVIS"""
|
|
||||||
TemproleCog(bot)
|
|
|
@ -85,9 +85,7 @@ class VerifyCog(Extension):
|
||||||
role = await ctx.guild.fetch_role(setting.value)
|
role = await ctx.guild.fetch_role(setting.value)
|
||||||
await ctx.author.remove_role(role, reason="Verification passed")
|
await ctx.author.remove_role(role, reason="Verification passed")
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.logger.warning(
|
self.logger.warning("Unverified role deleted before verification finished")
|
||||||
"Unverified role deleted before verification finished"
|
|
||||||
)
|
|
||||||
|
|
||||||
await response.context.edit_origin(
|
await response.context.edit_origin(
|
||||||
content=f"Welcome, {ctx.author.mention}. Please enjoy your stay.",
|
content=f"Welcome, {ctx.author.mention}. Please enjoy your stay.",
|
||||||
|
@ -97,10 +95,7 @@ class VerifyCog(Extension):
|
||||||
self.logger.debug(f"User {ctx.author.id} verified successfully")
|
self.logger.debug(f"User {ctx.author.id} verified successfully")
|
||||||
else:
|
else:
|
||||||
await response.context.edit_origin(
|
await response.context.edit_origin(
|
||||||
content=(
|
content=(f"{ctx.author.mention}, incorrect. " "Please press the button that says `YES`")
|
||||||
f"{ctx.author.mention}, incorrect. "
|
|
||||||
"Please press the button that says `YES`"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
await message.delete(delay=2)
|
await message.delete(delay=2)
|
|
@ -39,9 +39,7 @@ class WarningCog(ModcaseCog):
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||||
async def _warn(
|
async def _warn(self, ctx: InteractionContext, user: Member, reason: str, duration: int = 24) -> None:
|
||||||
self, ctx: InteractionContext, user: Member, reason: str, duration: int = 24
|
|
||||||
) -> None:
|
|
||||||
if len(reason) > 100:
|
if len(reason) > 100:
|
||||||
await ctx.send("Reason must be < 100 characters", ephemeral=True)
|
await ctx.send("Reason must be < 100 characters", ephemeral=True)
|
||||||
return
|
return
|
||||||
|
@ -122,9 +120,7 @@ class WarningCog(ModcaseCog):
|
||||||
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=(
|
description=(f"{len(warnings)} total | {len(active_warns)} currently active"),
|
||||||
f"{len(warnings)} total | {len(active_warns)} currently active"
|
|
||||||
),
|
|
||||||
fields=fields[i : i + 5],
|
fields=fields[i : i + 5],
|
||||||
)
|
)
|
||||||
embed.set_author(
|
embed.set_author(
|
||||||
|
@ -153,9 +149,7 @@ class WarningCog(ModcaseCog):
|
||||||
description=(f"{len(warnings)} total | {len(active_warns)} currently active"),
|
description=(f"{len(warnings)} total | {len(active_warns)} currently active"),
|
||||||
fields=fields[i : i + 5],
|
fields=fields[i : i + 5],
|
||||||
)
|
)
|
||||||
embed.set_author(
|
embed.set_author(name=user.username + "#" + user.discriminator, icon_url=user.display_avatar.url)
|
||||||
name=user.username + "#" + user.discriminator, icon_url=user.display_avatar.url
|
|
||||||
)
|
|
||||||
embed.set_thumbnail(url=ctx.guild.icon.url)
|
embed.set_thumbnail(url=ctx.guild.icon.url)
|
||||||
pages.append(embed)
|
pages.append(embed)
|
||||||
|
|
|
@ -84,9 +84,7 @@ class BotutilCog(Extension):
|
||||||
)
|
)
|
||||||
embed = build_embed(title="System Info", description="", fields=fields)
|
embed = build_embed(title="System Info", description="", fields=fields)
|
||||||
embed.set_image(url=self.bot.user.avatar.url)
|
embed.set_image(url=self.bot.user.avatar.url)
|
||||||
components = Button(
|
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
|
||||||
)
|
|
||||||
await ctx.send(embeds=embed, components=components)
|
await ctx.send(embeds=embed, components=components)
|
||||||
|
|
||||||
@prefixed_command(name="update")
|
@prefixed_command(name="update")
|
||||||
|
@ -113,16 +111,12 @@ class BotutilCog(Extension):
|
||||||
if changed:
|
if changed:
|
||||||
fields.append(EmbedField(name="Changed Modules", value=f"```\n{changed}\n```"))
|
fields.append(EmbedField(name="Changed Modules", value=f"```\n{changed}\n```"))
|
||||||
|
|
||||||
embed = build_embed(
|
embed = build_embed("Update Status", description="Updates have been applied", fields=fields)
|
||||||
"Update Status", description="Updates have been applied", fields=fields
|
|
||||||
)
|
|
||||||
embed.set_thumbnail(url="https://dev.zevaryx.com/git.png")
|
embed.set_thumbnail(url="https://dev.zevaryx.com/git.png")
|
||||||
|
|
||||||
self.logger.info("Updates applied")
|
self.logger.info("Updates applied")
|
||||||
content = f"```ansi\n{capture.get()}\n```"
|
content = f"```ansi\n{capture.get()}\n```"
|
||||||
components = Button(
|
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
|
||||||
)
|
|
||||||
if len(content) < 3000:
|
if len(content) < 3000:
|
||||||
await ctx.reply(content, embeds=embed, components=components)
|
await ctx.reply(content, embeds=embed, components=components)
|
||||||
else:
|
else:
|
||||||
|
@ -135,9 +129,7 @@ class BotutilCog(Extension):
|
||||||
else:
|
else:
|
||||||
embed = build_embed(title="Update Status", description="No changes applied", fields=[])
|
embed = build_embed(title="Update Status", description="No changes applied", fields=[])
|
||||||
embed.set_thumbnail(url="https://dev.zevaryx.com/git.png")
|
embed.set_thumbnail(url="https://dev.zevaryx.com/git.png")
|
||||||
components = Button(
|
components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
|
||||||
)
|
|
||||||
await ctx.reply(embeds=embed, components=components)
|
await ctx.reply(embeds=embed, components=components)
|
||||||
|
|
||||||
|
|
11
jarvis/cogs/core/socials/__init__.py
Normal file
11
jarvis/cogs/core/socials/__init__.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
"""JARVIS Social Cogs."""
|
||||||
|
|
||||||
|
from naff import Client
|
||||||
|
|
||||||
|
from jarvis.cogs.core.socials import reddit, twitter
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot: Client) -> None:
|
||||||
|
"""Add social cogs to JARVIS"""
|
||||||
|
reddit.RedditCog(bot)
|
||||||
|
twitter.TwitterCog(bot)
|
11
jarvis/cogs/unique/__init__.py
Normal file
11
jarvis/cogs/unique/__init__.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
"""JARVIS guild-specific cogs"""
|
||||||
|
from naff import Client
|
||||||
|
|
||||||
|
from jarvis.cogs.unique import ctc2, dbrand, gl
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bot: Client) -> None:
|
||||||
|
"""Add guild-specific cogs to JARVIS"""
|
||||||
|
ctc2.setup(bot)
|
||||||
|
dbrand.setup(bot)
|
||||||
|
gl.setup(bot)
|
|
@ -46,39 +46,25 @@ class CTCCog(Extension):
|
||||||
@ctc2.subcommand(sub_cmd_name="about")
|
@ctc2.subcommand(sub_cmd_name="about")
|
||||||
@cooldown(bucket=Buckets.USER, rate=1, interval=30)
|
@cooldown(bucket=Buckets.USER, rate=1, interval=30)
|
||||||
async def _about(self, ctx: InteractionContext) -> None:
|
async def _about(self, ctx: InteractionContext) -> None:
|
||||||
components = [
|
components = [ActionRow(Button(style=ButtonStyles.URL, url="https://completethecode.com", label="More Info"))]
|
||||||
ActionRow(
|
await ctx.send("See https://completethecode.com for more information", components=components)
|
||||||
Button(style=ButtonStyles.URL, url="https://completethecode.com", label="More Info")
|
|
||||||
)
|
|
||||||
]
|
|
||||||
await ctx.send(
|
|
||||||
"See https://completethecode.com for more information", components=components
|
|
||||||
)
|
|
||||||
|
|
||||||
@ctc2.subcommand(
|
@ctc2.subcommand(
|
||||||
sub_cmd_name="pw",
|
sub_cmd_name="pw",
|
||||||
sub_cmd_description="Guess a password for https://completethecodetwo.cards",
|
sub_cmd_description="Guess a password for https://completethecodetwo.cards",
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(name="guess", description="Guess a password", opt_type=OptionTypes.STRING, required=True)
|
||||||
name="guess", description="Guess a password", opt_type=OptionTypes.STRING, required=True
|
|
||||||
)
|
|
||||||
@cooldown(bucket=Buckets.USER, rate=1, interval=2)
|
@cooldown(bucket=Buckets.USER, rate=1, interval=2)
|
||||||
async def _pw(self, ctx: InteractionContext, guess: str) -> None:
|
async def _pw(self, ctx: InteractionContext, 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."
|
|
||||||
),
|
|
||||||
ephemeral=True,
|
ephemeral=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*."
|
|
||||||
),
|
|
||||||
ephemeral=True,
|
ephemeral=True,
|
||||||
)
|
)
|
||||||
return
|
return
|
|
@ -63,9 +63,7 @@ async def parse_db_status() -> dict:
|
||||||
else:
|
else:
|
||||||
cell = cell.get_text().strip()
|
cell = cell.get_text().strip()
|
||||||
row_data.append(cell)
|
row_data.append(cell)
|
||||||
data[data_key].append(
|
data[data_key].append({headers[idx]: value for idx, value in enumerate(row_data)})
|
||||||
{headers[idx]: value for idx, value in enumerate(row_data)}
|
|
||||||
)
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,9 +97,7 @@ class DbrandCog(Extension):
|
||||||
self.cache["status"] = status
|
self.cache["status"] = status
|
||||||
status = status.get("operations")
|
status = status.get("operations")
|
||||||
emojies = [x["Status"] for x in status]
|
emojies = [x["Status"] for x in status]
|
||||||
fields = [
|
fields = [EmbedField(name=f'{x["Status"]} {x["Service"]}', value=x["Detail"]) for x in status]
|
||||||
EmbedField(name=f'{x["Status"]} {x["Service"]}', value=x["Detail"]) for x in status
|
|
||||||
]
|
|
||||||
color = "#FBBD1E"
|
color = "#FBBD1E"
|
||||||
if all("green" in x for x in emojies):
|
if all("green" in x for x in emojies):
|
||||||
color = "#38F657"
|
color = "#38F657"
|
||||||
|
@ -192,17 +188,13 @@ class DbrandCog(Extension):
|
||||||
f"[Be (not) extorted]({self.base_url + 'not-extortion'})",
|
f"[Be (not) extorted]({self.base_url + 'not-extortion'})",
|
||||||
"[Robot Camo Wallpapers](https://db.io/wallpapers)",
|
"[Robot Camo Wallpapers](https://db.io/wallpapers)",
|
||||||
]
|
]
|
||||||
embed = build_embed(
|
embed = build_embed(title="Useful Links", description="\n\n".join(urls), fields=[], color="#FFBB00")
|
||||||
title="Useful Links", description="\n\n".join(urls), fields=[], color="#FFBB00"
|
|
||||||
)
|
|
||||||
embed.set_footer(
|
embed.set_footer(
|
||||||
text="dbrand.com",
|
text="dbrand.com",
|
||||||
icon_url="https://dev.zevaryx.com/db_logo.png",
|
icon_url="https://dev.zevaryx.com/db_logo.png",
|
||||||
)
|
)
|
||||||
embed.set_thumbnail(url="https://dev.zevaryx.com/db_logo.png")
|
embed.set_thumbnail(url="https://dev.zevaryx.com/db_logo.png")
|
||||||
embed.set_author(
|
embed.set_author(name="dbrand", url=self.base_url, icon_url="https://dev.zevaryx.com/db_logo.png")
|
||||||
name="dbrand", url=self.base_url, icon_url="https://dev.zevaryx.com/db_logo.png"
|
|
||||||
)
|
|
||||||
await ctx.send(embeds=embed)
|
await ctx.send(embeds=embed)
|
||||||
|
|
||||||
@db.subcommand(
|
@db.subcommand(
|
||||||
|
@ -264,15 +256,11 @@ class DbrandCog(Extension):
|
||||||
for service in data["shipping_services_available"]:
|
for service in data["shipping_services_available"]:
|
||||||
service_data = self.cache.get(f"{dest}-{service}")
|
service_data = self.cache.get(f"{dest}-{service}")
|
||||||
if not service_data or service_data["cache_expiry"] < datetime.now(tz=timezone.utc):
|
if not service_data or service_data["cache_expiry"] < datetime.now(tz=timezone.utc):
|
||||||
service_data = await self._session.get(
|
service_data = await self._session.get(self.api_url + dest + "/" + service["url"])
|
||||||
self.api_url + dest + "/" + service["url"]
|
|
||||||
)
|
|
||||||
if service_data.status > 400:
|
if service_data.status > 400:
|
||||||
continue
|
continue
|
||||||
service_data = await service_data.json()
|
service_data = await service_data.json()
|
||||||
service_data["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta(
|
service_data["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta(hours=24)
|
||||||
hours=24
|
|
||||||
)
|
|
||||||
self.cache[f"{dest}-{service}"] = service_data
|
self.cache[f"{dest}-{service}"] = service_data
|
||||||
title = f'{service_data["carrier"]} {service_data["tier-title"]} | {service_data["costs-min"]}'
|
title = f'{service_data["carrier"]} {service_data["tier-title"]} | {service_data["costs-min"]}'
|
||||||
message = service_data["time-title"]
|
message = service_data["time-title"]
|
||||||
|
@ -296,7 +284,9 @@ class DbrandCog(Extension):
|
||||||
description = ""
|
description = ""
|
||||||
color = "#FFBB00"
|
color = "#FFBB00"
|
||||||
if shipping_info:
|
if shipping_info:
|
||||||
description = f'{shipping_info["Status"]}\u200b \u200b {shipping_info["Est. Delivery Time"].split(":")[0]}'
|
description = (
|
||||||
|
f'{shipping_info["Status"]}\u200b \u200b {shipping_info["Est. Delivery Time"].split(":")[0]}'
|
||||||
|
)
|
||||||
created = self.cache.get("status").get("cache_expiry") - timedelta(hours=2)
|
created = self.cache.get("status").get("cache_expiry") - timedelta(hours=2)
|
||||||
ts = int(created.timestamp())
|
ts = int(created.timestamp())
|
||||||
description += f" \u200b | \u200b Last updated: <t:{ts}:R>\n\u200b"
|
description += f" \u200b | \u200b Last updated: <t:{ts}:R>\n\u200b"
|
||||||
|
@ -326,8 +316,7 @@ class DbrandCog(Extension):
|
||||||
embed = build_embed(
|
embed = build_embed(
|
||||||
title="Check Shipping Times",
|
title="Check Shipping Times",
|
||||||
description=(
|
description=(
|
||||||
"Country not found.\nYou can [view all shipping "
|
"Country not found.\nYou can [view all shipping " "destinations here](https://dbrand.com/shipping)"
|
||||||
"destinations here](https://dbrand.com/shipping)"
|
|
||||||
),
|
),
|
||||||
fields=[],
|
fields=[],
|
||||||
url="https://dbrand.com/shipping",
|
url="https://dbrand.com/shipping",
|
|
@ -53,9 +53,7 @@ class GitlabCog(Extension):
|
||||||
else:
|
else:
|
||||||
assignee = "None"
|
assignee = "None"
|
||||||
|
|
||||||
created_at = datetime.strptime(issue.created_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(
|
created_at = datetime.strptime(issue.created_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||||
"%Y-%m-%d %H:%M:%S UTC"
|
|
||||||
)
|
|
||||||
|
|
||||||
labels = issue.labels
|
labels = issue.labels
|
||||||
if labels:
|
if labels:
|
||||||
|
@ -73,9 +71,7 @@ class GitlabCog(Extension):
|
||||||
color = self.project.labels.get(issue.labels[0]).color
|
color = self.project.labels.get(issue.labels[0]).color
|
||||||
fields.append(EmbedField(name="Created At", value=created_at))
|
fields.append(EmbedField(name="Created At", value=created_at))
|
||||||
if issue.state == "closed":
|
if issue.state == "closed":
|
||||||
closed_at = datetime.strptime(issue.closed_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(
|
closed_at = datetime.strptime(issue.closed_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||||
"%Y-%m-%d %H:%M:%S UTC"
|
|
||||||
)
|
|
||||||
fields.append(EmbedField(name="Closed At", value=closed_at))
|
fields.append(EmbedField(name="Closed At", value=closed_at))
|
||||||
if issue.milestone:
|
if issue.milestone:
|
||||||
fields.append(
|
fields.append(
|
||||||
|
@ -99,18 +95,14 @@ class GitlabCog(Extension):
|
||||||
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(
|
embed.set_thumbnail(url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png")
|
||||||
url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png"
|
|
||||||
)
|
|
||||||
await ctx.send(embeds=embed)
|
await ctx.send(embeds=embed)
|
||||||
|
|
||||||
@gl.subcommand(
|
@gl.subcommand(
|
||||||
sub_cmd_name="milestone",
|
sub_cmd_name="milestone",
|
||||||
sub_cmd_description="Get a milestone from GitLab",
|
sub_cmd_description="Get a milestone from GitLab",
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(name="id", description="Milestone ID", opt_type=OptionTypes.INTEGER, required=True)
|
||||||
name="id", description="Milestone ID", opt_type=OptionTypes.INTEGER, required=True
|
|
||||||
)
|
|
||||||
async def _milestone(self, ctx: InteractionContext, id: int) -> None:
|
async def _milestone(self, ctx: InteractionContext, id: int) -> None:
|
||||||
try:
|
try:
|
||||||
milestone = self.project.milestones.get(int(id))
|
milestone = self.project.milestones.get(int(id))
|
||||||
|
@ -118,9 +110,7 @@ class GitlabCog(Extension):
|
||||||
await ctx.send("Milestone does not exist.", ephemeral=True)
|
await ctx.send("Milestone does not exist.", ephemeral=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
created_at = datetime.strptime(milestone.created_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(
|
created_at = datetime.strptime(milestone.created_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||||
"%Y-%m-%d %H:%M:%S UTC"
|
|
||||||
)
|
|
||||||
|
|
||||||
fields = [
|
fields = [
|
||||||
EmbedField(
|
EmbedField(
|
||||||
|
@ -153,18 +143,14 @@ class GitlabCog(Extension):
|
||||||
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(
|
embed.set_thumbnail(url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png")
|
||||||
url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png"
|
|
||||||
)
|
|
||||||
await ctx.send(embeds=embed)
|
await ctx.send(embeds=embed)
|
||||||
|
|
||||||
@gl.subcommand(
|
@gl.subcommand(
|
||||||
sub_cmd_name="mr",
|
sub_cmd_name="mr",
|
||||||
sub_cmd_description="Get a merge request from GitLab",
|
sub_cmd_description="Get a merge request from GitLab",
|
||||||
)
|
)
|
||||||
@slash_option(
|
@slash_option(name="id", description="Merge Request ID", opt_type=OptionTypes.INTEGER, required=True)
|
||||||
name="id", description="Merge Request ID", opt_type=OptionTypes.INTEGER, required=True
|
|
||||||
)
|
|
||||||
async def _mergerequest(self, ctx: InteractionContext, id: int) -> None:
|
async def _mergerequest(self, ctx: InteractionContext, id: int) -> None:
|
||||||
try:
|
try:
|
||||||
mr = self.project.mergerequests.get(int(id))
|
mr = self.project.mergerequests.get(int(id))
|
||||||
|
@ -177,9 +163,7 @@ class GitlabCog(Extension):
|
||||||
else:
|
else:
|
||||||
assignee = "None"
|
assignee = "None"
|
||||||
|
|
||||||
created_at = datetime.strptime(mr.created_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(
|
created_at = datetime.strptime(mr.created_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||||
"%Y-%m-%d %H:%M:%S UTC"
|
|
||||||
)
|
|
||||||
|
|
||||||
labels = mr.labels
|
labels = mr.labels
|
||||||
if labels:
|
if labels:
|
||||||
|
@ -199,14 +183,10 @@ class GitlabCog(Extension):
|
||||||
color = "#00FFEE"
|
color = "#00FFEE"
|
||||||
fields.append(EmbedField(name="Created At", value=created_at, inline=True))
|
fields.append(EmbedField(name="Created At", value=created_at, inline=True))
|
||||||
if mr.state == "merged":
|
if mr.state == "merged":
|
||||||
merged_at = datetime.strptime(mr.merged_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(
|
merged_at = datetime.strptime(mr.merged_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||||
"%Y-%m-%d %H:%M:%S UTC"
|
|
||||||
)
|
|
||||||
fields.append(EmbedField(name="Merged At", value=merged_at, inline=True))
|
fields.append(EmbedField(name="Merged At", value=merged_at, inline=True))
|
||||||
elif mr.state == "closed":
|
elif mr.state == "closed":
|
||||||
closed_at = datetime.strptime(mr.closed_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(
|
closed_at = datetime.strptime(mr.closed_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||||
"%Y-%m-%d %H:%M:%S UTC"
|
|
||||||
)
|
|
||||||
fields.append(EmbedField(name="Closed At", value=closed_at, inline=True))
|
fields.append(EmbedField(name="Closed At", value=closed_at, inline=True))
|
||||||
if mr.milestone:
|
if mr.milestone:
|
||||||
fields.append(
|
fields.append(
|
||||||
|
@ -230,9 +210,7 @@ class GitlabCog(Extension):
|
||||||
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(
|
embed.set_thumbnail(url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png")
|
||||||
url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png"
|
|
||||||
)
|
|
||||||
await ctx.send(embeds=embed)
|
await ctx.send(embeds=embed)
|
||||||
|
|
||||||
def build_embed_page(self, api_list: list, t_state: str, name: str) -> Embed:
|
def build_embed_page(self, api_list: list, t_state: str, name: str) -> Embed:
|
||||||
|
@ -263,9 +241,7 @@ class GitlabCog(Extension):
|
||||||
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(
|
embed.set_thumbnail(url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png")
|
||||||
url="https://about.gitlab.com/images/press/logo/png/gitlab-icon-rgb.png"
|
|
||||||
)
|
|
||||||
return embed
|
return embed
|
||||||
|
|
||||||
@gl.subcommand(
|
@gl.subcommand(
|
||||||
|
@ -370,9 +346,7 @@ class GitlabCog(Extension):
|
||||||
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(
|
pages.append(self.build_embed_page(merges[i : i + 5], t_state=t_state, name="merge request"))
|
||||||
self.build_embed_page(merges[i : i + 5], t_state=t_state, name="merge request")
|
|
||||||
)
|
|
||||||
|
|
||||||
paginator = Paginator.create_from_embeds(self.bot, *pages, timeout=300)
|
paginator = Paginator.create_from_embeds(self.bot, *pages, timeout=300)
|
||||||
|
|
||||||
|
@ -407,9 +381,7 @@ class GitlabCog(Extension):
|
||||||
|
|
||||||
pages = []
|
pages = []
|
||||||
for i in range(0, len(milestones), 5):
|
for i in range(0, len(milestones), 5):
|
||||||
pages.append(
|
pages.append(self.build_embed_page(milestones[i : i + 5], t_state=None, name="milestone"))
|
||||||
self.build_embed_page(milestones[i : i + 5], t_state=None, name="milestone")
|
|
||||||
)
|
|
||||||
|
|
||||||
paginator = Paginator.create_from_embeds(self.bot, *pages, timeout=300)
|
paginator = Paginator.create_from_embeds(self.bot, *pages, timeout=300)
|
||||||
|
|
Loading…
Add table
Reference in a new issue