Fix common issues in cogs (ephemeral, opt_type, check)
This commit is contained in:
parent
fa4785f073
commit
88d596cad7
22 changed files with 310 additions and 396 deletions
|
@ -12,6 +12,7 @@ from dis_snek.models.snek.application_commands import (
|
|||
slash_command,
|
||||
slash_option,
|
||||
)
|
||||
from dis_snek.models.snek.command import check
|
||||
|
||||
from jarvis.db.models import Ban, Unban
|
||||
from jarvis.utils import build_embed, find
|
||||
|
@ -90,16 +91,14 @@ class BanCog(CacheCog):
|
|||
await ctx.send(embed=embed)
|
||||
|
||||
@slash_command(name="ban", description="Ban a user")
|
||||
@slash_option(name="user", description="User to ban", opt_type=OptionTypes.USER, required=True)
|
||||
@slash_option(
|
||||
name="user", description="User to ban", option_type=OptionTypes.USER, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="reason", description="Ban reason", option_type=OptionTypes.STRING, required=True
|
||||
name="reason", description="Ban reason", opt_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="btype",
|
||||
description="Ban type",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
choices=[
|
||||
SlashCommandChoice(name="Permanent", value="perm"),
|
||||
|
@ -107,7 +106,7 @@ class BanCog(CacheCog):
|
|||
SlashCommandChoice(name="Soft", value="soft"),
|
||||
],
|
||||
)
|
||||
@admin_or_permissions(Permissions.BAN_MEMBERS)
|
||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||
async def _ban(
|
||||
self,
|
||||
ctx: InteractionContext,
|
||||
|
@ -117,19 +116,19 @@ class BanCog(CacheCog):
|
|||
duration: int = 4,
|
||||
) -> None:
|
||||
if not user or user == ctx.author:
|
||||
await ctx.send("You cannot ban yourself.", hidden=True)
|
||||
await ctx.send("You cannot ban yourself.", ephemeral=True)
|
||||
return
|
||||
if user == self.bot.user:
|
||||
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", ephemeral=True)
|
||||
return
|
||||
if btype == "temp" and duration < 0:
|
||||
await ctx.send("You cannot set a temp ban to < 0 hours.", hidden=True)
|
||||
await ctx.send("You cannot set a temp ban to < 0 hours.", ephemeral=True)
|
||||
return
|
||||
elif btype == "temp" and duration > 744:
|
||||
await ctx.send("You cannot set a temp ban to > 1 month", hidden=True)
|
||||
await ctx.send("You cannot set a temp ban to > 1 month", ephemeral=True)
|
||||
return
|
||||
if len(reason) > 100:
|
||||
await ctx.send("Reason must be < 100 characters", hidden=True)
|
||||
await ctx.send("Reason must be < 100 characters", ephemeral=True)
|
||||
return
|
||||
|
||||
await ctx.defer()
|
||||
|
@ -167,7 +166,7 @@ class BanCog(CacheCog):
|
|||
try:
|
||||
await ctx.guild.ban(user, reason=reason)
|
||||
except Exception as e:
|
||||
await ctx.send(f"Failed to ban user:\n```\n{e}\n```", hidden=True)
|
||||
await ctx.send(f"Failed to ban user:\n```\n{e}\n```", ephemeral=True)
|
||||
return
|
||||
send_failed = False
|
||||
if mtype == "soft":
|
||||
|
@ -184,12 +183,12 @@ class BanCog(CacheCog):
|
|||
|
||||
@slash_command(name="unban", description="Unban a user")
|
||||
@slash_option(
|
||||
name="user", description="User to unban", option_type=OptionTypes.STRING, required=True
|
||||
name="user", description="User to unban", opt_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="reason", description="Unban reason", option_type=OptionTypes.STRING, required=True
|
||||
name="reason", description="Unban reason", opt_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
@admin_or_permissions(Permissions.BAN_MEMBERS)
|
||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||
async def _unban(
|
||||
self,
|
||||
ctx: InteractionContext,
|
||||
|
@ -197,7 +196,7 @@ class BanCog(CacheCog):
|
|||
reason: str,
|
||||
) -> None:
|
||||
if len(reason) > 100:
|
||||
await ctx.send("Reason must be < 100 characters", hidden=True)
|
||||
await ctx.send("Reason must be < 100 characters", ephemeral=True)
|
||||
return
|
||||
|
||||
orig_user = user
|
||||
|
@ -255,7 +254,7 @@ class BanCog(CacheCog):
|
|||
database_ban_info = Ban.objects(**search).first()
|
||||
|
||||
if not discord_ban_info and not database_ban_info:
|
||||
await ctx.send(f"Unable to find user {orig_user}", hidden=True)
|
||||
await ctx.send(f"Unable to find user {orig_user}", ephemeral=True)
|
||||
|
||||
elif discord_ban_info:
|
||||
await self.discord_apply_unban(ctx, discord_ban_info.user, reason)
|
||||
|
@ -284,7 +283,7 @@ class BanCog(CacheCog):
|
|||
@slash_option(
|
||||
name="btype",
|
||||
description="Ban type",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
choices=[
|
||||
SlashCommandChoice(name="All", value=0),
|
||||
|
@ -296,19 +295,19 @@ class BanCog(CacheCog):
|
|||
@slash_option(
|
||||
name="active",
|
||||
description="Active bans",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
choices=[SlashCommandChoice(name="Yes", value=1), SlashCommandChoice(name="No", value=0)],
|
||||
)
|
||||
@admin_or_permissions(Permissions.BAN_MEMBERS)
|
||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||
async def _bans_list(self, ctx: InteractionContext, type: int = 0, active: int = 1) -> None:
|
||||
active = bool(active)
|
||||
exists = self.check_cache(ctx, type=type, active=active)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.defer(ephemeral=True)
|
||||
await ctx.send(
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
types = [0, "perm", "temp", "soft"]
|
||||
|
|
|
@ -7,6 +7,7 @@ from dis_snek.models.snek.application_commands import (
|
|||
slash_command,
|
||||
slash_option,
|
||||
)
|
||||
from dis_snek.models.snek.command import check
|
||||
|
||||
from jarvis.db.models import Kick
|
||||
from jarvis.utils import build_embed
|
||||
|
@ -17,22 +18,20 @@ class KickCog(Scale):
|
|||
"""J.A.R.V.I.S. KickCog."""
|
||||
|
||||
@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", option_type=OptionTypes.USER, required=True
|
||||
name="reason", description="Kick reason", opt_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="reason", description="Kick reason", option_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
@admin_or_permissions(Permissions.BAN_MEMBERS)
|
||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||
async def _kick(self, ctx: InteractionContext, user: User, reason: str) -> None:
|
||||
if not user or user == ctx.author:
|
||||
await ctx.send("You cannot kick yourself.", hidden=True)
|
||||
await ctx.send("You cannot kick yourself.", ephemeral=True)
|
||||
return
|
||||
if user == self.bot.user:
|
||||
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", ephemeral=True)
|
||||
return
|
||||
if len(reason) > 100:
|
||||
await ctx.send("Reason must be < 100 characters", hidden=True)
|
||||
await ctx.send("Reason must be < 100 characters", ephemeral=True)
|
||||
return
|
||||
guild_name = ctx.guild.name
|
||||
embed = build_embed(
|
||||
|
|
|
@ -10,6 +10,7 @@ from dis_snek.models.snek.application_commands import (
|
|||
slash_command,
|
||||
slash_option,
|
||||
)
|
||||
from dis_snek.models.snek.command import check
|
||||
|
||||
from jarvis.db.models import Mute
|
||||
from jarvis.utils import build_embed
|
||||
|
@ -23,25 +24,23 @@ class MuteCog(Scale):
|
|||
self.bot = bot
|
||||
|
||||
@slash_command(name="mute", description="Mute a user")
|
||||
@slash_option(
|
||||
name="user", description="User to mute", option_type=OptionTypes.USER, required=True
|
||||
)
|
||||
@slash_option(name="user", description="User to mute", opt_type=OptionTypes.USER, required=True)
|
||||
@slash_option(
|
||||
name="reason",
|
||||
description="Reason for mute",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="time",
|
||||
description="Duration of mute, default 1",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
)
|
||||
@slash_option(
|
||||
name="scale",
|
||||
description="Time scale, default Hour(s)",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
choices=[
|
||||
SlashCommandChoice(name="Minute(s)", value=1),
|
||||
|
@ -50,26 +49,28 @@ class MuteCog(Scale):
|
|||
SlashCommandChoice(name="Week(s)", value=604800),
|
||||
],
|
||||
)
|
||||
@admin_or_permissions(
|
||||
@check(
|
||||
admin_or_permissions(
|
||||
Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS
|
||||
)
|
||||
)
|
||||
async def _timeout(
|
||||
self, ctx: InteractionContext, user: Member, reason: str, time: int = 1, scale: int = 60
|
||||
) -> None:
|
||||
if user == ctx.author:
|
||||
await ctx.send("You cannot mute yourself.", hidden=True)
|
||||
await ctx.send("You cannot mute yourself.", ephemeral=True)
|
||||
return
|
||||
if user == self.bot.user:
|
||||
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", ephemeral=True)
|
||||
return
|
||||
if len(reason) > 100:
|
||||
await ctx.send("Reason must be < 100 characters", hidden=True)
|
||||
await ctx.send("Reason must be < 100 characters", ephemeral=True)
|
||||
return
|
||||
|
||||
# Max 4 weeks (2419200 seconds) per API
|
||||
duration = time * scale
|
||||
if duration > 2419200:
|
||||
await ctx.send("Mute must be less than 4 weeks (2419200 seconds)", hidden=True)
|
||||
await ctx.send("Mute must be less than 4 weeks (2419200 seconds)", ephemeral=True)
|
||||
return
|
||||
|
||||
await user.timeout(communication_disabled_until=duration, reason=reason)
|
||||
|
@ -97,17 +98,19 @@ class MuteCog(Scale):
|
|||
|
||||
@slash_command(name="unmute", description="Unmute a user")
|
||||
@slash_option(
|
||||
name="user", description="User to unmute", option_type=OptionTypes.USER, required=True
|
||||
name="user", description="User to unmute", opt_type=OptionTypes.USER, required=True
|
||||
)
|
||||
@admin_or_permissions(
|
||||
@check(
|
||||
admin_or_permissions(
|
||||
Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS
|
||||
)
|
||||
)
|
||||
async def _unmute(self, ctx: InteractionContext, user: Member) -> None:
|
||||
if (
|
||||
not user.communication_disabled_until
|
||||
or user.communication_disabled_until < datetime.now() # noqa: W503
|
||||
):
|
||||
await ctx.send("User is not muted", hidden=True)
|
||||
await ctx.send("User is not muted", ephemeral=True)
|
||||
return
|
||||
|
||||
embed = build_embed(
|
||||
|
|
|
@ -6,6 +6,7 @@ from dis_snek.models.snek.application_commands import (
|
|||
slash_command,
|
||||
slash_option,
|
||||
)
|
||||
from dis_snek.models.snek.command import check
|
||||
|
||||
from jarvis.db.models import Autopurge, Purge
|
||||
from jarvis.utils.permissions import admin_or_permissions
|
||||
|
@ -21,13 +22,13 @@ class PurgeCog(Scale):
|
|||
@slash_option(
|
||||
name="amount",
|
||||
description="Amount of messages to purge, default 10",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_MESSAGES)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
|
||||
async def _purge(self, ctx: InteractionContext, amount: int = 10) -> None:
|
||||
if amount < 1:
|
||||
await ctx.send("Amount must be >= 1", hidden=True)
|
||||
await ctx.send("Amount must be >= 1", ephemeral=True)
|
||||
return
|
||||
await ctx.defer()
|
||||
channel = ctx.channel
|
||||
|
@ -48,31 +49,31 @@ class PurgeCog(Scale):
|
|||
@slash_option(
|
||||
name="channel",
|
||||
description="Channel to autopurge",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="delay",
|
||||
description="Seconds to keep message before purge, default 30",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_MESSAGES)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
|
||||
async def _autopurge_add(
|
||||
self, ctx: InteractionContext, channel: GuildText, delay: int = 30
|
||||
) -> None:
|
||||
if not isinstance(channel, GuildText):
|
||||
await ctx.send("Channel must be a GuildText channel", hidden=True)
|
||||
await ctx.send("Channel must be a GuildText channel", ephemeral=True)
|
||||
return
|
||||
if delay <= 0:
|
||||
await ctx.send("Delay must be > 0", hidden=True)
|
||||
await ctx.send("Delay must be > 0", ephemeral=True)
|
||||
return
|
||||
elif delay > 300:
|
||||
await ctx.send("Delay must be < 5 minutes", hidden=True)
|
||||
await ctx.send("Delay must be < 5 minutes", ephemeral=True)
|
||||
return
|
||||
autopurge = Autopurge.objects(guild=ctx.guild.id, channel=channel.id).first()
|
||||
if autopurge:
|
||||
await ctx.send("Autopurge already exists.", hidden=True)
|
||||
await ctx.send("Autopurge already exists.", ephemeral=True)
|
||||
return
|
||||
_ = Autopurge(
|
||||
guild=ctx.guild.id,
|
||||
|
@ -88,14 +89,14 @@ class PurgeCog(Scale):
|
|||
@slash_option(
|
||||
name="channel",
|
||||
description="Channel to remove from autopurge",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=True,
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_MESSAGES)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
|
||||
async def _autopurge_remove(self, ctx: InteractionContext, channel: GuildText) -> None:
|
||||
autopurge = Autopurge.objects(guild=ctx.guild.id, channel=channel.id)
|
||||
if not autopurge:
|
||||
await ctx.send("Autopurge does not exist.", hidden=True)
|
||||
await ctx.send("Autopurge does not exist.", ephemeral=True)
|
||||
return
|
||||
autopurge.delete()
|
||||
await ctx.send(f"Autopurge removed from {channel.mention}.")
|
||||
|
@ -108,22 +109,22 @@ class PurgeCog(Scale):
|
|||
@slash_option(
|
||||
name="channel",
|
||||
description="Channel to update",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="delay",
|
||||
description="New time to save",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=True,
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_MESSAGES)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_MESSAGES))
|
||||
async def _autopurge_update(
|
||||
self, ctx: InteractionContext, channel: GuildText, delay: int
|
||||
) -> None:
|
||||
autopurge = Autopurge.objects(guild=ctx.guild.id, channel=channel.id)
|
||||
if not autopurge:
|
||||
await ctx.send("Autopurge does not exist.", hidden=True)
|
||||
await ctx.send("Autopurge does not exist.", ephemeral=True)
|
||||
return
|
||||
autopurge.delay = delay
|
||||
autopurge.save()
|
||||
|
|
|
@ -11,6 +11,7 @@ from dis_snek.models.snek.application_commands import (
|
|||
slash_command,
|
||||
slash_option,
|
||||
)
|
||||
from dis_snek.models.snek.command import check
|
||||
|
||||
from jarvis.db.models import Roleping
|
||||
from jarvis.utils import build_embed
|
||||
|
@ -27,14 +28,12 @@ class RolepingCog(CacheCog):
|
|||
@slash_command(
|
||||
name="roleping", sub_cmd_name="add", sub_cmd_description="Add a role to roleping"
|
||||
)
|
||||
@slash_option(
|
||||
name="role", description="Role to add", option_type=OptionTypes.ROLE, required=True
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@slash_option(name="role", description="Role to add", opt_type=OptionTypes.ROLE, required=True)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _roleping_add(self, ctx: InteractionContext, role: Role) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=role.id).first()
|
||||
if roleping:
|
||||
await ctx.send(f"Role `{role.name}` already in roleping.", hidden=True)
|
||||
await ctx.send(f"Role `{role.name}` already in roleping.", ephemeral=True)
|
||||
return
|
||||
_ = Roleping(
|
||||
role=role.id,
|
||||
|
@ -47,13 +46,13 @@ class RolepingCog(CacheCog):
|
|||
|
||||
@slash_command(name="roleping", sub_cmd_name="remove", sub_cmd_description="Remove a role")
|
||||
@slash_option(
|
||||
name="role", description="Role to remove", option_type=OptionTypes.ROLE, required=True
|
||||
name="role", description="Role to remove", opt_type=OptionTypes.ROLE, required=True
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _roleping_remove(self, ctx: InteractionContext, role: Role) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=role.id)
|
||||
if not roleping:
|
||||
await ctx.send("Roleping does not exist", hidden=True)
|
||||
await ctx.send("Roleping does not exist", ephemeral=True)
|
||||
return
|
||||
|
||||
roleping.delete()
|
||||
|
@ -63,16 +62,16 @@ class RolepingCog(CacheCog):
|
|||
async def _roleping_list(self, ctx: InteractionContext) -> None:
|
||||
exists = self.check_cache(ctx)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.defer(ephemeral=True)
|
||||
await ctx.send(
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
|
||||
rolepings = Roleping.objects(guild=ctx.guild.id)
|
||||
if not rolepings:
|
||||
await ctx.send("No rolepings configured", hidden=True)
|
||||
await ctx.send("No rolepings configured", ephemeral=True)
|
||||
return
|
||||
|
||||
embeds = []
|
||||
|
@ -137,29 +136,27 @@ class RolepingCog(CacheCog):
|
|||
sub_cmd_name="user",
|
||||
sub_cmd_description="Add a user as a bypass to a roleping",
|
||||
)
|
||||
@slash_option(name="user", description="User to add", opt_type=OptionTypes.USER, required=True)
|
||||
@slash_option(
|
||||
name="user", description="User to add", option_type=OptionTypes.USER, required=True
|
||||
name="rping", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="rping", description="Rolepinged role", option_type=OptionTypes.ROLE, required=True
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _roleping_bypass_user(
|
||||
self, ctx: InteractionContext, user: Member, rping: Role
|
||||
) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||
if not roleping:
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", hidden=True)
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", ephemeral=True)
|
||||
return
|
||||
|
||||
if user.id in roleping.bypass["users"]:
|
||||
await ctx.send(f"{user.mention} already in bypass", hidden=True)
|
||||
await ctx.send(f"{user.mention} already in bypass", ephemeral=True)
|
||||
return
|
||||
|
||||
if len(roleping.bypass["users"]) == 10:
|
||||
await ctx.send(
|
||||
"Already have 10 users in bypass. Please consider using roles for roleping bypass",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
|
||||
|
@ -168,7 +165,7 @@ class RolepingCog(CacheCog):
|
|||
if matching_role:
|
||||
await ctx.send(
|
||||
f"{user.mention} already has bypass via {matching_role[0].mention}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
|
||||
|
@ -182,28 +179,26 @@ class RolepingCog(CacheCog):
|
|||
sub_cmd_name="role",
|
||||
description="Add a role as a bypass to roleping",
|
||||
)
|
||||
@slash_option(name="role", description="Role to add", opt_type=OptionTypes.ROLE, required=True)
|
||||
@slash_option(
|
||||
name="role", description="Role to add", option_type=OptionTypes.ROLE, required=True
|
||||
name="rping", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="rping", description="Rolepinged role", option_type=OptionTypes.ROLE, required=True
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _roleping_bypass_role(self, ctx: InteractionContext, role: Role, rping: Role) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||
if not roleping:
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", hidden=True)
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", ephemeral=True)
|
||||
return
|
||||
|
||||
if role.id in roleping.bypass["roles"]:
|
||||
await ctx.send(f"{role.mention} already in bypass", hidden=True)
|
||||
await ctx.send(f"{role.mention} already in bypass", ephemeral=True)
|
||||
return
|
||||
|
||||
if len(roleping.bypass["roles"]) == 10:
|
||||
await ctx.send(
|
||||
"Already have 10 roles in bypass. "
|
||||
"Please consider consolidating roles for roleping bypass",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
|
||||
|
@ -220,22 +215,22 @@ class RolepingCog(CacheCog):
|
|||
sub_cmd_description="Remove a bypass from a roleping (restoring it)",
|
||||
)
|
||||
@slash_option(
|
||||
name="user", description="User to remove", option_type=OptionTypes.USER, required=True
|
||||
name="user", description="User to remove", opt_type=OptionTypes.USER, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="rping", description="Rolepinged role", option_type=OptionTypes.ROLE, required=True
|
||||
name="rping", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _roleping_restore_user(
|
||||
self, ctx: InteractionContext, user: Member, rping: Role
|
||||
) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||
if not roleping:
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", hidden=True)
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", ephemeral=True)
|
||||
return
|
||||
|
||||
if user.id not in roleping.bypass["users"]:
|
||||
await ctx.send(f"{user.mention} not in bypass", hidden=True)
|
||||
await ctx.send(f"{user.mention} not in bypass", ephemeral=True)
|
||||
return
|
||||
|
||||
roleping.bypass["users"].delete(user.id)
|
||||
|
@ -249,29 +244,29 @@ class RolepingCog(CacheCog):
|
|||
description="Remove a bypass from a roleping (restoring it)",
|
||||
)
|
||||
@slash_option(
|
||||
name="role", description="Role to remove", option_type=OptionTypes.ROLE, required=True
|
||||
name="role", description="Role to remove", opt_type=OptionTypes.ROLE, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="rping", description="Rolepinged role", option_type=OptionTypes.ROLE, required=True
|
||||
name="rping", description="Rolepinged role", opt_type=OptionTypes.ROLE, required=True
|
||||
)
|
||||
@admin_or_permissions(manage_guild=True)
|
||||
@check(admin_or_permissions(manage_guild=True))
|
||||
async def _roleping_restore_role(
|
||||
self, ctx: InteractionContext, role: Role, rping: Role
|
||||
) -> None:
|
||||
roleping = Roleping.objects(guild=ctx.guild.id, role=rping.id).first()
|
||||
if not roleping:
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", hidden=True)
|
||||
await ctx.send(f"Roleping not configured for {rping.mention}", ephemeral=True)
|
||||
return
|
||||
|
||||
if role.id in roleping.bypass["roles"]:
|
||||
await ctx.send(f"{role.mention} already in bypass", hidden=True)
|
||||
await ctx.send(f"{role.mention} already in bypass", ephemeral=True)
|
||||
return
|
||||
|
||||
if len(roleping.bypass["roles"]) == 10:
|
||||
await ctx.send(
|
||||
"Already have 10 roles in bypass. "
|
||||
"Please consider consolidating roles for roleping bypass",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ from dis_snek.models.snek.application_commands import (
|
|||
slash_command,
|
||||
slash_option,
|
||||
)
|
||||
from dis_snek.models.snek.command import check
|
||||
|
||||
from jarvis.db.models import Warning
|
||||
from jarvis.utils import build_embed
|
||||
|
@ -25,33 +26,31 @@ class WarningCog(CacheCog):
|
|||
super().__init__(bot)
|
||||
|
||||
@slash_command(name="warn", description="Warn a user")
|
||||
@slash_option(
|
||||
name="user", description="User to warn", option_type=OptionTypes.USER, required=True
|
||||
)
|
||||
@slash_option(name="user", description="User to warn", opt_type=OptionTypes.USER, required=True)
|
||||
@slash_option(
|
||||
name="reason",
|
||||
description="Reason for warning",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="duration",
|
||||
description="Duration of warning in hours, default 24",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _warn(
|
||||
self, ctx: InteractionContext, user: User, reason: str, duration: int = 24
|
||||
) -> None:
|
||||
if len(reason) > 100:
|
||||
await ctx.send("Reason must be < 100 characters", hidden=True)
|
||||
await ctx.send("Reason must be < 100 characters", ephemeral=True)
|
||||
return
|
||||
if duration <= 0:
|
||||
await ctx.send("Duration must be > 0", hidden=True)
|
||||
await ctx.send("Duration must be > 0", ephemeral=True)
|
||||
return
|
||||
elif duration >= 120:
|
||||
await ctx.send("Duration must be < 5 days", hidden=True)
|
||||
await ctx.send("Duration must be < 5 days", ephemeral=True)
|
||||
return
|
||||
await ctx.defer()
|
||||
_ = Warning(
|
||||
|
@ -77,28 +76,26 @@ class WarningCog(CacheCog):
|
|||
await ctx.send(embed=embed)
|
||||
|
||||
@slash_command(name="warnings", description="Get count of user warnings")
|
||||
@slash_option(
|
||||
name="user", description="User to view", option_type=OptionTypes.USER, required=True
|
||||
)
|
||||
@slash_option(name="user", description="User to view", opt_type=OptionTypes.USER, required=True)
|
||||
@slash_option(
|
||||
name="active",
|
||||
description="View active only",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
choices=[
|
||||
SlashCommandChoice(name="Yes", value=1),
|
||||
SlashCommandChoice(name="No", value=0),
|
||||
],
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _warnings(self, ctx: InteractionContext, user: User, active: bool = 1) -> None:
|
||||
active = bool(active)
|
||||
exists = self.check_cache(ctx, user_id=user.id, active=active)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.defer(ephemeral=True)
|
||||
await ctx.send(
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
warnings = Warning.objects(
|
||||
|
|
|
@ -9,6 +9,7 @@ from dis_snek.models.snek.application_commands import (
|
|||
slash_command,
|
||||
slash_option,
|
||||
)
|
||||
from dis_snek.models.snek.command import check
|
||||
|
||||
from jarvis.data.unicode import emoji_list
|
||||
from jarvis.db.models import Autoreact
|
||||
|
@ -70,13 +71,13 @@ class AutoReactCog(Scale):
|
|||
@slash_option(
|
||||
name="channel",
|
||||
description="Autoreact channel to add emote to",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="emote", description="Emote to add", option_type=OptionTypes.STRING, required=True
|
||||
name="emote", description="Emote to add", opt_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _autoreact_add(self, ctx: InteractionContext, channel: GuildText, emote: str) -> None:
|
||||
await ctx.defer()
|
||||
custom_emoji = self.custom_emote.match(emote)
|
||||
|
@ -84,13 +85,13 @@ class AutoReactCog(Scale):
|
|||
if not custom_emoji and not standard_emoji:
|
||||
await ctx.send(
|
||||
"Please use either an emote from this server or a unicode emoji.",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
if custom_emoji:
|
||||
emoji_id = int(custom_emoji.group(1))
|
||||
if not find(lambda x: x.id == emoji_id, ctx.guild.emojis):
|
||||
await ctx.send("Please use a custom emote from this server.", hidden=True)
|
||||
await ctx.send("Please use a custom emote from this server.", ephemeral=True)
|
||||
return
|
||||
autoreact = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
|
||||
if not autoreact:
|
||||
|
@ -99,13 +100,13 @@ class AutoReactCog(Scale):
|
|||
if emote in autoreact.reactions:
|
||||
await ctx.send(
|
||||
f"Emote already added to {channel.mention} autoreactions.",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
if len(autoreact.reactions) >= 5:
|
||||
await ctx.send(
|
||||
"Max number of reactions hit. Remove a different one to add this one",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
autoreact.reactions.append(emote)
|
||||
|
@ -120,16 +121,16 @@ class AutoReactCog(Scale):
|
|||
@slash_option(
|
||||
name="channel",
|
||||
description="Autoreact channel to remove emote from",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="emote",
|
||||
description="Emote to remove (use all to delete)",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _autoreact_remove(
|
||||
self, ctx: InteractionContext, channel: GuildText, emote: str
|
||||
) -> None:
|
||||
|
@ -137,7 +138,7 @@ class AutoReactCog(Scale):
|
|||
if not autoreact:
|
||||
await ctx.send(
|
||||
f"Please create autoreact first with /autoreact add {channel.mention} {emote}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
if emote.lower() == "all":
|
||||
|
@ -146,7 +147,7 @@ class AutoReactCog(Scale):
|
|||
elif emote not in autoreact.reactions:
|
||||
await ctx.send(
|
||||
f"{emote} not used in {channel.mention} autoreactions.",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
else:
|
||||
|
@ -164,7 +165,7 @@ class AutoReactCog(Scale):
|
|||
@slash_option(
|
||||
name="channel",
|
||||
description="Autoreact channel to list",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=True,
|
||||
)
|
||||
async def _autoreact_list(self, ctx: InteractionContext, channel: GuildText) -> None:
|
||||
|
@ -172,7 +173,7 @@ class AutoReactCog(Scale):
|
|||
if not exists:
|
||||
await ctx.send(
|
||||
f"Please create autoreact first with /autoreact add {channel.mention} <emote>",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
message = ""
|
||||
|
@ -187,4 +188,4 @@ class AutoReactCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add AutoReactCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(AutoReactCog(bot))
|
||||
AutoReactCog(bot)
|
||||
|
|
|
@ -56,7 +56,7 @@ class CTCCog(CacheCog):
|
|||
"Listen here, dipshit. Don't be like <@256110768724901889>. "
|
||||
"Make your guesses < 800 characters."
|
||||
),
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
elif not valid.fullmatch(guess):
|
||||
|
@ -65,18 +65,18 @@ class CTCCog(CacheCog):
|
|||
"Listen here, dipshit. Don't be like <@256110768724901889>. "
|
||||
"Make your guesses *readable*."
|
||||
),
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
elif invites.search(guess):
|
||||
await ctx.send(
|
||||
"Listen here, dipshit. No using this to bypass sending invite links.",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
guessed = Guess.objects(guess=guess).first()
|
||||
if guessed:
|
||||
await ctx.send("Already guessed, dipshit.", hidden=True)
|
||||
await ctx.send("Already guessed, dipshit.", ephemeral=True)
|
||||
return
|
||||
result = await self._session.post(self.url, data=guess)
|
||||
correct = False
|
||||
|
@ -84,7 +84,7 @@ class CTCCog(CacheCog):
|
|||
await ctx.send(f"{ctx.author.mention} got it! Password is {guess}!")
|
||||
correct = True
|
||||
else:
|
||||
await ctx.send("Nope.", hidden=True)
|
||||
await ctx.send("Nope.", ephemeral=True)
|
||||
_ = Guess(guess=guess, user=ctx.author.id, correct=correct).save()
|
||||
|
||||
@slash_command(
|
||||
|
@ -97,10 +97,10 @@ class CTCCog(CacheCog):
|
|||
async def _guesses(self, ctx: InteractionContext) -> None:
|
||||
exists = self.check_cache(ctx)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.defer(ephemeral=True)
|
||||
await ctx.send(
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
|
||||
|
@ -153,4 +153,4 @@ class CTCCog(CacheCog):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add CTCCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(CTCCog(bot))
|
||||
CTCCog(bot)
|
||||
|
|
|
@ -156,7 +156,7 @@ class DbrandCog(Scale):
|
|||
@slash_option(
|
||||
name="search",
|
||||
description="Country search query (2 character code, country name, flag emoji)",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
)
|
||||
@cooldown(bucket=Buckets.USER, rate=1, interval=2)
|
||||
|
@ -266,4 +266,4 @@ class DbrandCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add dbrandcog to J.A.R.V.I.S."""
|
||||
bot.add_cog(DbrandCog(bot))
|
||||
DbrandCog(bot)
|
||||
|
|
|
@ -68,14 +68,14 @@ class DevCog(Scale):
|
|||
@slash_option(
|
||||
name="method",
|
||||
description="Hash method",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
choices=[SlashCommandChoice(name=x, value=x) for x in supported_hashes],
|
||||
)
|
||||
@slash_option(
|
||||
name="data",
|
||||
description="Data to hash",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
)
|
||||
@cooldown(bucket=Buckets.USER, rate=1, interval=2)
|
||||
|
@ -83,7 +83,7 @@ class DevCog(Scale):
|
|||
if not data:
|
||||
await ctx.send(
|
||||
"No data to hash",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
text = True
|
||||
|
@ -105,20 +105,20 @@ class DevCog(Scale):
|
|||
@slash_option(
|
||||
name="version",
|
||||
description="UUID version",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
choices=[SlashCommandChoice(name=x, value=x) for x in ["3", "4", "5"]],
|
||||
)
|
||||
@slash_option(
|
||||
name="data",
|
||||
description="Data for UUID version 3,5",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=False,
|
||||
)
|
||||
async def _uuid(self, ctx: InteractionContext, version: str, data: str = None) -> None:
|
||||
version = int(version)
|
||||
if version in [3, 5] and not data:
|
||||
await ctx.send(f"UUID{version} requires data.", hidden=True)
|
||||
await ctx.send(f"UUID{version} requires data.", ephemeral=True)
|
||||
return
|
||||
if version == 4:
|
||||
await ctx.send(f"UUID4: `{uuidpy.uuid4()}`")
|
||||
|
@ -180,14 +180,14 @@ class DevCog(Scale):
|
|||
@slash_option(
|
||||
name="method",
|
||||
description="Encode method",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
choices=[SlashCommandChoice(name=x, value=x) for x in base64_methods],
|
||||
)
|
||||
@slash_option(
|
||||
name="data",
|
||||
description="Data to encode",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
)
|
||||
async def _encode(self, ctx: InteractionContext, method: str, data: str) -> None:
|
||||
|
@ -205,14 +205,14 @@ class DevCog(Scale):
|
|||
@slash_option(
|
||||
name="method",
|
||||
description="Decode method",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
choices=[SlashCommandChoice(name=x, value=x) for x in base64_methods],
|
||||
)
|
||||
@slash_option(
|
||||
name="data",
|
||||
description="Data to encode",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
)
|
||||
async def _decode(self, ctx: InteractionContext, method: str, data: str) -> None:
|
||||
|
@ -222,7 +222,7 @@ class DevCog(Scale):
|
|||
if invites.search(decoded):
|
||||
await ctx.send(
|
||||
"Please don't use this to bypass invite restrictions",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
fields = [
|
||||
|
@ -243,4 +243,4 @@ class DevCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add DevCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(DevCog(bot))
|
||||
DevCog(bot)
|
||||
|
|
|
@ -33,19 +33,19 @@ class ErrorHandlerCog(commands.Cog):
|
|||
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.", ephemeral=True)
|
||||
elif isinstance(error, commands.errors.CommandNotFound):
|
||||
return
|
||||
elif isinstance(error, commands.errors.CommandOnCooldown):
|
||||
await ctx.send(
|
||||
"Command on cooldown. "
|
||||
f"Please wait {error.retry_after:0.2f}s before trying again",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
else:
|
||||
await ctx.send(
|
||||
f"Error processing command:\n```{error}```",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
raise error
|
||||
slash.commands[ctx.command].reset_cooldown(ctx)
|
||||
|
@ -53,4 +53,4 @@ class ErrorHandlerCog(commands.Cog):
|
|||
|
||||
def setup(bot: commands.Bot) -> None:
|
||||
"""Add ErrorHandlerCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(ErrorHandlerCog(bot))
|
||||
ErrorHandlerCog(bot)
|
||||
|
|
|
@ -32,12 +32,12 @@ class GitlabCog(CacheCog):
|
|||
@slash_command(
|
||||
name="gl", sub_cmd_name="issue", description="Get an issue from GitLab", scopes=guild_ids
|
||||
)
|
||||
@slash_option(name="id", description="Issue ID", option_type=OptionTypes.INTEGER, required=True)
|
||||
@slash_option(name="id", description="Issue ID", opt_type=OptionTypes.INTEGER, required=True)
|
||||
async def _issue(self, ctx: InteractionContext, id: int) -> None:
|
||||
try:
|
||||
issue = self.project.issues.get(int(id))
|
||||
except gitlab.exceptions.GitlabGetError:
|
||||
await ctx.send("Issue does not exist.", hidden=True)
|
||||
await ctx.send("Issue does not exist.", ephemeral=True)
|
||||
return
|
||||
assignee = issue.assignee
|
||||
if assignee:
|
||||
|
@ -101,13 +101,13 @@ class GitlabCog(CacheCog):
|
|||
scopes=guild_ids,
|
||||
)
|
||||
@slash_option(
|
||||
name="id", description="Milestone ID", option_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:
|
||||
try:
|
||||
milestone = self.project.milestones.get(int(id))
|
||||
except gitlab.exceptions.GitlabGetError:
|
||||
await ctx.send("Milestone does not exist.", hidden=True)
|
||||
await ctx.send("Milestone does not exist.", ephemeral=True)
|
||||
return
|
||||
|
||||
created_at = datetime.strptime(milestone.created_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(
|
||||
|
@ -157,13 +157,13 @@ class GitlabCog(CacheCog):
|
|||
scopes=guild_ids,
|
||||
)
|
||||
@slash_option(
|
||||
name="id", description="Merge Request ID", option_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:
|
||||
try:
|
||||
mr = self.project.mergerequests.get(int(id))
|
||||
except gitlab.exceptions.GitlabGetError:
|
||||
await ctx.send("Merge request does not exist.", hidden=True)
|
||||
await ctx.send("Merge request does not exist.", ephemeral=True)
|
||||
return
|
||||
assignee = mr.assignee
|
||||
if assignee:
|
||||
|
@ -266,7 +266,7 @@ class GitlabCog(CacheCog):
|
|||
@slash_option(
|
||||
name="state",
|
||||
description="State of issues to get",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=False,
|
||||
choices=[
|
||||
SlashCommandChoice(name="Open", value="opened"),
|
||||
|
@ -277,10 +277,10 @@ class GitlabCog(CacheCog):
|
|||
async def _issues(self, ctx: InteractionContext, state: str = "opened") -> None:
|
||||
exists = self.check_cache(ctx, state=state)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.defer(ephemeral=True)
|
||||
await ctx.send(
|
||||
"Please use existing interaction: " + f"{exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
await ctx.defer()
|
||||
|
@ -339,7 +339,7 @@ class GitlabCog(CacheCog):
|
|||
@slash_option(
|
||||
name="state",
|
||||
description="State of merge requests to get",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=False,
|
||||
choices=[
|
||||
SlashCommandChoice(name="Open", value="opened"),
|
||||
|
@ -350,10 +350,10 @@ class GitlabCog(CacheCog):
|
|||
async def _mergerequests(self, ctx: InteractionContext, state: str = "opened") -> None:
|
||||
exists = self.check_cache(ctx, state=state)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.defer(ephemeral=True)
|
||||
await ctx.send(
|
||||
"Please use existing interaction: " + f"{exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
await ctx.defer()
|
||||
|
@ -414,10 +414,10 @@ class GitlabCog(CacheCog):
|
|||
async def _milestones(self, ctx: InteractionContext) -> None:
|
||||
exists = self.check_cache(ctx)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.defer(ephemeral=True)
|
||||
await ctx.send(
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
await ctx.defer()
|
||||
|
@ -464,4 +464,4 @@ class GitlabCog(CacheCog):
|
|||
def setup(bot: Snake) -> None:
|
||||
"""Add GitlabCog to J.A.R.V.I.S. if Gitlab token exists."""
|
||||
if get_config().gitlab_token:
|
||||
bot.add_cog(GitlabCog(bot))
|
||||
GitlabCog(bot)
|
||||
|
|
|
@ -105,4 +105,4 @@ class ImageCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add ImageCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(ImageCog(bot))
|
||||
ImageCog(bot)
|
||||
|
|
|
@ -34,7 +34,7 @@ class JokeCog(Scale):
|
|||
name="joke",
|
||||
description="Hear a joke",
|
||||
)
|
||||
@slash_option(name="id", description="Joke ID", required=False, option_type=OptionTypes.INTEGER)
|
||||
@slash_option(name="id", description="Joke ID", required=False, opt_type=OptionTypes.INTEGER)
|
||||
@cooldown(bucket=Buckets.CHANNEL, rate=1, interval=10)
|
||||
async def _joke(self, ctx: InteractionContext, id: str = None) -> None:
|
||||
"""Get a joke from the database."""
|
||||
|
@ -57,7 +57,7 @@ class JokeCog(Scale):
|
|||
result = Joke.objects().aggregate(pipeline).next()
|
||||
|
||||
if result is None:
|
||||
await ctx.send("Humor module failed. Please try again later.", hidden=True)
|
||||
await ctx.send("Humor module failed. Please try again later.", ephemeral=True)
|
||||
return
|
||||
emotes = re.findall(r"(&#x[a-fA-F0-9]*;)", result["body"])
|
||||
for match in emotes:
|
||||
|
@ -118,4 +118,4 @@ class JokeCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add JokeCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(JokeCog(bot))
|
||||
JokeCog(bot)
|
||||
|
|
|
@ -6,6 +6,6 @@ from jarvis.cogs.modlog import command, member, message
|
|||
|
||||
def setup(bot: Bot) -> None:
|
||||
"""Add modlog cogs to J.A.R.V.I.S."""
|
||||
bot.add_cog(command.ModlogCommandCog(bot))
|
||||
bot.add_cog(member.ModlogMemberCog(bot))
|
||||
bot.add_cog(message.ModlogMessageCog(bot))
|
||||
command.ModlogCommandCog(bot)
|
||||
member.ModlogMemberCog(bot)
|
||||
message.ModlogMessageCog(bot)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
from dis_snek import MessageContext, Scale, Snake, message_command
|
||||
from dis_snek.models.discord.user import User
|
||||
from dis_snek.models.snek.checks import is_owner
|
||||
from dis_snek.models.snek.command import check
|
||||
|
||||
from jarvis.config import reload_config
|
||||
from jarvis.db.models import Config
|
||||
|
@ -19,7 +20,7 @@ class OwnerCog(Scale):
|
|||
self.admins = Config.objects(key="admins").first()
|
||||
|
||||
@message_command(name="addadmin")
|
||||
@is_owner()
|
||||
@check(is_owner())
|
||||
async def _add(self, ctx: MessageContext, user: User) -> None:
|
||||
if user.id in self.admins.value:
|
||||
await ctx.send(f"{user.mention} is already an admin.")
|
||||
|
@ -43,4 +44,4 @@ class OwnerCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add OwnerCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(OwnerCog(bot))
|
||||
OwnerCog(bot)
|
||||
|
|
|
@ -6,8 +6,6 @@ from typing import List, Optional
|
|||
|
||||
from bson import ObjectId
|
||||
from dis_snek import InteractionContext, Snake
|
||||
from dis_snek.ext.tasks.task import Task
|
||||
from dis_snek.ext.tasks.triggers import IntervalTrigger
|
||||
from dis_snek.models.discord.components import ActionRow, Select, SelectOption
|
||||
from dis_snek.models.discord.embed import Embed, EmbedField
|
||||
from dis_snek.models.snek.application_commands import (
|
||||
|
@ -32,34 +30,33 @@ class RemindmeCog(CacheCog):
|
|||
|
||||
def __init__(self, bot: Snake):
|
||||
super().__init__(bot)
|
||||
self._remind.start()
|
||||
|
||||
@slash_command(name="remindme", description="Set a reminder")
|
||||
@slash_option(
|
||||
name="message",
|
||||
description="What to remind you of?",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="weeks",
|
||||
description="Number of weeks?",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
)
|
||||
@slash_option(
|
||||
name="days", description="Number of days?", option_type=OptionTypes.INTEGER, required=False
|
||||
name="days", description="Number of days?", opt_type=OptionTypes.INTEGER, required=False
|
||||
)
|
||||
@slash_option(
|
||||
name="hours",
|
||||
description="Number of hours?",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
)
|
||||
@slash_option(
|
||||
name="minutes",
|
||||
description="Number of minutes?",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
)
|
||||
async def _remindme(
|
||||
|
@ -72,20 +69,20 @@ class RemindmeCog(CacheCog):
|
|||
minutes: Optional[int] = 0,
|
||||
) -> None:
|
||||
if len(message) > 100:
|
||||
await ctx.send("Reminder cannot be > 100 characters.", hidden=True)
|
||||
await ctx.send("Reminder cannot be > 100 characters.", ephemeral=True)
|
||||
return
|
||||
elif invites.search(message):
|
||||
await ctx.send(
|
||||
"Listen, don't use this to try and bypass the rules",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
elif not valid.fullmatch(message):
|
||||
await ctx.send("Hey, you should probably make this readable", hidden=True)
|
||||
await ctx.send("Hey, you should probably make this readable", ephemeral=True)
|
||||
return
|
||||
|
||||
if not any([weeks, days, hours, minutes]):
|
||||
await ctx.send("At least one time period is required", hidden=True)
|
||||
await ctx.send("At least one time period is required", ephemeral=True)
|
||||
return
|
||||
|
||||
weeks = abs(weeks)
|
||||
|
@ -94,19 +91,19 @@ class RemindmeCog(CacheCog):
|
|||
minutes = abs(minutes)
|
||||
|
||||
if weeks and weeks > 4:
|
||||
await ctx.send("Cannot be farther than 4 weeks out!", hidden=True)
|
||||
await ctx.send("Cannot be farther than 4 weeks out!", ephemeral=True)
|
||||
return
|
||||
|
||||
elif days and days > 6:
|
||||
await ctx.send("Use weeks instead of 7+ days, please.", hidden=True)
|
||||
await ctx.send("Use weeks instead of 7+ days, please.", ephemeral=True)
|
||||
return
|
||||
|
||||
elif hours and hours > 23:
|
||||
await ctx.send("Use days instead of 24+ hours, please.", hidden=True)
|
||||
await ctx.send("Use days instead of 24+ hours, please.", ephemeral=True)
|
||||
return
|
||||
|
||||
elif minutes and minutes > 59:
|
||||
await ctx.send("Use hours instead of 59+ minutes, please.", hidden=True)
|
||||
await ctx.send("Use hours instead of 59+ minutes, please.", ephemeral=True)
|
||||
return
|
||||
|
||||
reminders = Reminder.objects(user=ctx.author.id, active=True).count()
|
||||
|
@ -114,7 +111,7 @@ class RemindmeCog(CacheCog):
|
|||
await ctx.send(
|
||||
"You already have 5 (or more) active reminders. "
|
||||
"Please either remove an old one, or wait for one to pass",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
|
||||
|
@ -187,15 +184,15 @@ class RemindmeCog(CacheCog):
|
|||
async def _list(self, ctx: InteractionContext) -> None:
|
||||
exists = self.check_cache(ctx)
|
||||
if exists:
|
||||
await ctx.defer(hidden=True)
|
||||
await ctx.defer(ephemeral=True)
|
||||
await ctx.send(
|
||||
f"Please use existing interaction: {exists['paginator']._message.jump_url}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
reminders = Reminder.objects(user=ctx.author.id, active=True)
|
||||
if not reminders:
|
||||
await ctx.send("You have no reminders set.", hidden=True)
|
||||
await ctx.send("You have no reminders set.", ephemeral=True)
|
||||
return
|
||||
|
||||
embed = await self.get_reminders_embed(ctx, reminders)
|
||||
|
@ -206,7 +203,7 @@ class RemindmeCog(CacheCog):
|
|||
async def _delete(self, ctx: InteractionContext) -> None:
|
||||
reminders = Reminder.objects(user=ctx.author.id, active=True)
|
||||
if not reminders:
|
||||
await ctx.send("You have no reminders set", hidden=True)
|
||||
await ctx.send("You have no reminders set", ephemeral=True)
|
||||
return
|
||||
|
||||
options = []
|
||||
|
@ -279,36 +276,7 @@ class RemindmeCog(CacheCog):
|
|||
component["disabled"] = True
|
||||
await message.edit(components=components)
|
||||
|
||||
@Task.create(trigger=IntervalTrigger(seconds=15))
|
||||
async def _remind(self) -> None:
|
||||
reminders = Reminder.objects(remind_at__lte=datetime.utcnow() + timedelta(seconds=30))
|
||||
for reminder in reminders:
|
||||
if reminder.remind_at <= datetime.utcnow():
|
||||
user = await self.bot.fetch_user(reminder.user)
|
||||
if not user:
|
||||
reminder.delete()
|
||||
continue
|
||||
embed = build_embed(
|
||||
title="You have a reminder",
|
||||
description=reminder.message,
|
||||
fields=[],
|
||||
)
|
||||
embed.set_author(
|
||||
name=user.name + "#" + user.discriminator,
|
||||
icon_url=user.display_avatar,
|
||||
)
|
||||
embed.set_thumbnail(url=user.display_avatar)
|
||||
try:
|
||||
await user.send(embed=embed)
|
||||
except Exception:
|
||||
guild = self.bot.fetch_guild(reminder.guild)
|
||||
channel = guild.get_channel(reminder.channel) if guild else None
|
||||
if channel:
|
||||
await channel.send(f"{user.mention}", embed=embed)
|
||||
finally:
|
||||
reminder.delete()
|
||||
|
||||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add RemindmeCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(RemindmeCog(bot))
|
||||
RemindmeCog(bot)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import asyncio
|
||||
|
||||
from dis_snek import InteractionContext, Permissions, Scale, Snake
|
||||
from dis_snek.client.utils import get
|
||||
from dis_snek.models.discord.components import ActionRow, Select, SelectOption
|
||||
from dis_snek.models.discord.embed import EmbedField
|
||||
from dis_snek.models.discord.role import Role
|
||||
|
@ -11,11 +10,11 @@ from dis_snek.models.snek.application_commands import (
|
|||
slash_command,
|
||||
slash_option,
|
||||
)
|
||||
from dis_snek.models.snek.command import cooldown
|
||||
from dis_snek.models.snek.command import check, cooldown
|
||||
from dis_snek.models.snek.cooldowns import Buckets
|
||||
|
||||
from jarvis.db.models import Rolegiver
|
||||
from jarvis.utils import build_embed
|
||||
from jarvis.utils import build_embed, get
|
||||
from jarvis.utils.permissions import admin_or_permissions
|
||||
|
||||
|
||||
|
@ -28,21 +27,19 @@ class RolegiverCog(Scale):
|
|||
@slash_command(
|
||||
name="rolegiver", sub_cmd_name="add", sub_cmd_description="Add a role to rolegiver"
|
||||
)
|
||||
@slash_option(
|
||||
name="role", description="Role to add", optin_type=OptionTypes.ROLE, required=True
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@slash_option(name="role", description="Role to add", opt_type=OptionTypes.ROLE, required=True)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _rolegiver_add(self, ctx: InteractionContext, role: Role) -> None:
|
||||
setting = Rolegiver.objects(guild=ctx.guild.id).first()
|
||||
if setting and role.id in setting.roles:
|
||||
await ctx.send("Role already in rolegiver", hidden=True)
|
||||
await ctx.send("Role already in rolegiver", ephemeral=True)
|
||||
return
|
||||
|
||||
if not setting:
|
||||
setting = Rolegiver(guild=ctx.guild.id, roles=[])
|
||||
|
||||
if len(setting.roles) >= 20:
|
||||
await ctx.send("You can only have 20 roles in the rolegiver", hidden=True)
|
||||
await ctx.send("You can only have 20 roles in the rolegiver", ephemeral=True)
|
||||
return
|
||||
|
||||
setting.roles.append(role.id)
|
||||
|
@ -84,11 +81,11 @@ class RolegiverCog(Scale):
|
|||
@slash_command(
|
||||
name="rolegiver", sub_cmd_name="remove", sub_cmd_description="Remove a role from rolegiver"
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _rolegiver_remove(self, ctx: InteractionContext) -> None:
|
||||
setting = Rolegiver.objects(guild=ctx.guild.id).first()
|
||||
if not setting or (setting and not setting.roles):
|
||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||
await ctx.send("Rolegiver has no roles", ephemeral=True)
|
||||
return
|
||||
|
||||
options = []
|
||||
|
@ -168,7 +165,7 @@ class RolegiverCog(Scale):
|
|||
async def _rolegiver_list(self, ctx: InteractionContext) -> None:
|
||||
setting = Rolegiver.objects(guild=ctx.guild.id).first()
|
||||
if not setting or (setting and not setting.roles):
|
||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||
await ctx.send("Rolegiver has no roles", ephemeral=True)
|
||||
return
|
||||
|
||||
roles = []
|
||||
|
@ -204,7 +201,7 @@ class RolegiverCog(Scale):
|
|||
async def _role_get(self, ctx: InteractionContext) -> None:
|
||||
setting = Rolegiver.objects(guild=ctx.guild.id).first()
|
||||
if not setting or (setting and not setting.roles):
|
||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||
await ctx.send("Rolegiver has no roles", ephemeral=True)
|
||||
return
|
||||
|
||||
options = []
|
||||
|
@ -283,10 +280,10 @@ class RolegiverCog(Scale):
|
|||
|
||||
setting = Rolegiver.objects(guild=ctx.guild.id).first()
|
||||
if not setting or (setting and not setting.roles):
|
||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||
await ctx.send("Rolegiver has no roles", ephemeral=True)
|
||||
return
|
||||
elif not any(x.id in setting.roles for x in user_roles):
|
||||
await ctx.send("You have no rolegiver roles", hidden=True)
|
||||
await ctx.send("You have no rolegiver roles", ephemeral=True)
|
||||
return
|
||||
|
||||
valid = list(filter(lambda x: x.id in setting.roles, user_roles))
|
||||
|
@ -361,11 +358,11 @@ class RolegiverCog(Scale):
|
|||
@slash_command(
|
||||
name="rolegiver", sub_cmd_name="cleanup", description="Removed deleted roles from rolegiver"
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _rolegiver_cleanup(self, ctx: InteractionContext) -> None:
|
||||
setting = Rolegiver.objects(guild=ctx.guild.id).first()
|
||||
if not setting or not setting.roles:
|
||||
await ctx.send("Rolegiver has no roles", hidden=True)
|
||||
await ctx.send("Rolegiver has no roles", ephemeral=True)
|
||||
guild_role_ids = [r.id for r in ctx.guild.roles]
|
||||
for role_id in setting.roles:
|
||||
if role_id not in guild_role_ids:
|
||||
|
@ -377,5 +374,4 @@ class RolegiverCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add RolegiverCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(RolegiverCog(bot))
|
||||
bot.add_cog(RolegiverCog(bot))
|
||||
RolegiverCog(bot)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
"""J.A.R.V.I.S. Starboard Cog."""
|
||||
from dis_snek import InteractionContext, Permissions, Scale, Snake
|
||||
from dis_snek.client.utils import find
|
||||
from dis_snek.models.discord.channel import GuildText
|
||||
from dis_snek.models.discord.components import ActionRow, Select, SelectOption
|
||||
from dis_snek.models.discord.message import Message
|
||||
|
@ -11,9 +10,10 @@ from dis_snek.models.snek.application_commands import (
|
|||
slash_command,
|
||||
slash_option,
|
||||
)
|
||||
from dis_snek.models.snek.command import check
|
||||
|
||||
from jarvis.db.models import Star, Starboard
|
||||
from jarvis.utils import build_embed
|
||||
from jarvis.utils import build_embed, find
|
||||
from jarvis.utils.permissions import admin_or_permissions
|
||||
|
||||
supported_images = [
|
||||
|
@ -32,7 +32,7 @@ class StarboardCog(Scale):
|
|||
self.bot = bot
|
||||
|
||||
@slash_command(name="starboard", sub_cmd_name="list", sub_cmd_description="List all starboards")
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _list(self, ctx: InteractionContext) -> None:
|
||||
starboards = Starboard.objects(guild=ctx.guild.id)
|
||||
if starboards != []:
|
||||
|
@ -49,29 +49,29 @@ class StarboardCog(Scale):
|
|||
@slash_option(
|
||||
name="channel",
|
||||
description="Starboard channel",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=True,
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _create(self, ctx: InteractionContext, channel: GuildText) -> None:
|
||||
if channel not in ctx.guild.channels:
|
||||
await ctx.send(
|
||||
"Channel not in guild. Choose an existing channel.",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
if not isinstance(channel, GuildText):
|
||||
await ctx.send("Channel must be a GuildText", hidden=True)
|
||||
await ctx.send("Channel must be a GuildText", ephemeral=True)
|
||||
return
|
||||
|
||||
exists = Starboard.objects(channel=channel.id, guild=ctx.guild.id).first()
|
||||
if exists:
|
||||
await ctx.send(f"Starboard already exists at {channel.mention}.", hidden=True)
|
||||
await ctx.send(f"Starboard already exists at {channel.mention}.", ephemeral=True)
|
||||
return
|
||||
|
||||
count = Starboard.objects(guild=ctx.guild.id).count()
|
||||
if count >= 25:
|
||||
await ctx.send("25 starboard limit reached", hidden=True)
|
||||
await ctx.send("25 starboard limit reached", ephemeral=True)
|
||||
return
|
||||
|
||||
_ = Starboard(
|
||||
|
@ -87,33 +87,33 @@ class StarboardCog(Scale):
|
|||
@slash_option(
|
||||
name="channel",
|
||||
description="Starboard channel",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=True,
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _delete(self, ctx: InteractionContext, channel: GuildText) -> None:
|
||||
deleted = Starboard.objects(channel=channel.id, guild=ctx.guild.id).delete()
|
||||
if deleted:
|
||||
_ = Star.objects(starboard=channel.id).delete()
|
||||
await ctx.send(f"Starboard deleted from {channel.mention}.", hidden=True)
|
||||
await ctx.send(f"Starboard deleted from {channel.mention}.", ephemeral=True)
|
||||
else:
|
||||
await ctx.send(f"Starboard not found in {channel.mention}.", hidden=True)
|
||||
await ctx.send(f"Starboard not found in {channel.mention}.", ephemeral=True)
|
||||
|
||||
@context_menu(name="Star Message", target=CommandTypes.MESSAGE)
|
||||
@context_menu(name="Star Message", context_type=CommandTypes.MESSAGE)
|
||||
async def _star_message(self, ctx: InteractionContext) -> None:
|
||||
await self._star_add.invoke(ctx, ctx.target_message)
|
||||
|
||||
@slash_command(name="star", sub_cmd_name="add", description="Star a message")
|
||||
@slash_option(
|
||||
name="message", description="Message to star", option_type=OptionTypes.STRING, required=True
|
||||
name="message", description="Message to star", opt_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="channel",
|
||||
description="Channel that has the message, not required if used in same channel",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=False,
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _star_add(
|
||||
self,
|
||||
ctx: InteractionContext,
|
||||
|
@ -124,7 +124,7 @@ class StarboardCog(Scale):
|
|||
channel = ctx.channel
|
||||
starboards = Starboard.objects(guild=ctx.guild.id)
|
||||
if not starboards:
|
||||
await ctx.send("No starboards exist.", hidden=True)
|
||||
await ctx.send("No starboards exist.", ephemeral=True)
|
||||
return
|
||||
|
||||
await ctx.defer()
|
||||
|
@ -135,7 +135,7 @@ class StarboardCog(Scale):
|
|||
message = await channel.get_message(int(message))
|
||||
|
||||
if not message:
|
||||
await ctx.send("Message not found", hidden=True)
|
||||
await ctx.send("Message not found", ephemeral=True)
|
||||
return
|
||||
|
||||
channel_list = []
|
||||
|
@ -174,7 +174,7 @@ class StarboardCog(Scale):
|
|||
if exists:
|
||||
await ctx.send(
|
||||
f"Message already sent to Starboard {starboard.mention}",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
|
||||
|
@ -229,15 +229,15 @@ class StarboardCog(Scale):
|
|||
|
||||
@slash_command(name="star", sub_cmd_name="delete", description="Delete a starred message")
|
||||
@slash_option(
|
||||
name="message", description="Star to delete", option_type=OptionTypes.INTEGER, required=True
|
||||
name="message", description="Star to delete", opt_type=OptionTypes.INTEGER, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="starboard",
|
||||
description="Starboard to delete star from",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=True,
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _star_delete(
|
||||
self,
|
||||
ctx: InteractionContext,
|
||||
|
@ -245,13 +245,13 @@ class StarboardCog(Scale):
|
|||
starboard: GuildText,
|
||||
) -> None:
|
||||
if not isinstance(starboard, GuildText):
|
||||
await ctx.send("Channel must be a GuildText channel", hidden=True)
|
||||
await ctx.send("Channel must be a GuildText channel", ephemeral=True)
|
||||
return
|
||||
exists = Starboard.objects(channel=starboard.id, guild=ctx.guild.id).first()
|
||||
if not exists:
|
||||
await ctx.send(
|
||||
f"Starboard does not exist in {starboard.mention}. Please create it first",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
|
||||
|
@ -262,7 +262,7 @@ class StarboardCog(Scale):
|
|||
active=True,
|
||||
).first()
|
||||
if not star:
|
||||
await ctx.send(f"No star exists with id {id}", hidden=True)
|
||||
await ctx.send(f"No star exists with id {id}", ephemeral=True)
|
||||
return
|
||||
|
||||
message = await starboard.fetch_message(star.star)
|
||||
|
@ -277,5 +277,4 @@ class StarboardCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add StarboardCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(StarboardCog(bot))
|
||||
bot.add_cog(StarboardCog(bot))
|
||||
StarboardCog(bot)
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
"""J.A.R.V.I.S. Twitter Cog."""
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
import tweepy
|
||||
from bson import ObjectId
|
||||
from dis_snek import InteractionContext, Permissions, Scale, Snake
|
||||
from dis_snek.ext.tasks.task import Task
|
||||
from dis_snek.ext.tasks.triggers import IntervalTrigger
|
||||
from dis_snek.models.discord.channel import GuildText
|
||||
from dis_snek.models.discord.components import ActionRow, Select, SelectOption
|
||||
from dis_snek.models.snek.application_commands import (
|
||||
|
@ -15,13 +12,12 @@ from dis_snek.models.snek.application_commands import (
|
|||
slash_command,
|
||||
slash_option,
|
||||
)
|
||||
from dis_snek.models.snek.command import check
|
||||
|
||||
from jarvis.config import get_config
|
||||
from jarvis.db.models import Twitter
|
||||
from jarvis.utils.permissions import admin_or_permissions
|
||||
|
||||
logger = logging.getLogger("discord")
|
||||
|
||||
|
||||
class TwitterCog(Scale):
|
||||
"""J.A.R.V.I.S. Twitter Cog."""
|
||||
|
@ -33,102 +29,59 @@ class TwitterCog(Scale):
|
|||
config.twitter["consumer_key"], config.twitter["consumer_secret"]
|
||||
)
|
||||
self.api = tweepy.API(auth)
|
||||
self._tweets.start()
|
||||
self._guild_cache = {}
|
||||
self._channel_cache = {}
|
||||
|
||||
@Task.create(trigger=IntervalTrigger(minutes=1))
|
||||
async def _tweets(self) -> None:
|
||||
twitters = Twitter.objects(active=True)
|
||||
handles = Twitter.objects.distinct("handle")
|
||||
twitter_data = {}
|
||||
for handle in handles:
|
||||
try:
|
||||
data = await asyncio.to_thread(self.api.user_timeline, screen_name=handle)
|
||||
twitter_data[handle] = data
|
||||
except Exception as e:
|
||||
logger.error(f"Error with fetching: {e}")
|
||||
for twitter in twitters:
|
||||
try:
|
||||
tweets = list(
|
||||
filter(lambda x: x.id > twitter.last_tweet, twitter_data[twitter.handle])
|
||||
)
|
||||
if tweets:
|
||||
guild_id = twitter.guild
|
||||
channel_id = twitter.channel
|
||||
tweets = sorted(tweets, key=lambda x: x.id)
|
||||
if guild_id not in self._guild_cache:
|
||||
self._guild_cache[guild_id] = await self.bot.get_guild(guild_id)
|
||||
guild = self._guild_cache[twitter.guild]
|
||||
if channel_id not in self._channel_cache:
|
||||
self._channel_cache[channel_id] = await guild.fetch_channel(channel_id)
|
||||
channel = self._channel_cache[channel_id]
|
||||
for tweet in tweets:
|
||||
retweet = "retweeted_status" in tweet.__dict__
|
||||
if retweet and not twitter.retweets:
|
||||
continue
|
||||
timestamp = int(tweet.created_at.timestamp())
|
||||
url = f"https://twitter.com/{twitter.handle}/status/{tweet.id}"
|
||||
verb = "re" if retweet else ""
|
||||
await channel.send(
|
||||
f"`@{twitter.handle}` {verb}tweeted this at <t:{timestamp}:f>: {url}"
|
||||
)
|
||||
newest = max(tweets, key=lambda x: x.id)
|
||||
twitter.last_tweet = newest.id
|
||||
twitter.save()
|
||||
except Exception as e:
|
||||
logger.error(f"Error with tweets: {e}")
|
||||
|
||||
@slash_command(name="twitter", sub_cmd_name="follow", description="Follow a Twitter acount")
|
||||
@slash_option(
|
||||
name="handle", description="Twitter account", option_type=OptionTypes.STRING, required=True
|
||||
name="handle", description="Twitter account", opt_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
@slash_option(
|
||||
name="channel",
|
||||
description="Channel to post tweets to",
|
||||
option_type=OptionTypes.CHANNEL,
|
||||
opt_type=OptionTypes.CHANNEL,
|
||||
required=True,
|
||||
)
|
||||
@slash_option(
|
||||
name="retweets",
|
||||
description="Mirror re-tweets?",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=False,
|
||||
choices=[
|
||||
SlashCommandChoice(name="Yes", value="Yes"),
|
||||
SlashCommandChoice(name="No", value="No"),
|
||||
],
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _twitter_follow(
|
||||
self, ctx: InteractionContext, handle: str, channel: GuildText, retweets: str = "Yes"
|
||||
) -> None:
|
||||
handle = handle.lower()
|
||||
retweets = retweets == "Yes"
|
||||
if len(handle) > 15:
|
||||
await ctx.send("Invalid Twitter handle", hidden=True)
|
||||
await ctx.send("Invalid Twitter handle", ephemeral=True)
|
||||
return
|
||||
|
||||
if not isinstance(channel, GuildText):
|
||||
await ctx.send("Channel must be a text channel", hidden=True)
|
||||
await ctx.send("Channel must be a text channel", ephemeral=True)
|
||||
return
|
||||
|
||||
try:
|
||||
latest_tweet = await asyncio.to_thread(self.api.user_timeline, screen_name=handle)[0]
|
||||
except Exception:
|
||||
await ctx.send(
|
||||
"Unable to get user timeline. Are you sure the handle is correct?", hidden=True
|
||||
"Unable to get user timeline. Are you sure the handle is correct?", ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
count = Twitter.objects(guild=ctx.guild.id).count()
|
||||
if count >= 12:
|
||||
await ctx.send("Cannot follow more than 12 Twitter accounts", hidden=True)
|
||||
await ctx.send("Cannot follow more than 12 Twitter accounts", ephemeral=True)
|
||||
return
|
||||
|
||||
exists = Twitter.objects(handle=handle, guild=ctx.guild.id)
|
||||
if exists:
|
||||
await ctx.send("Twitter handle already being followed in this guild", hidden=True)
|
||||
await ctx.send("Twitter handle already being followed in this guild", ephemeral=True)
|
||||
return
|
||||
|
||||
t = Twitter(
|
||||
|
@ -145,11 +98,11 @@ class TwitterCog(Scale):
|
|||
await ctx.send(f"Now following `@{handle}` in {channel.mention}")
|
||||
|
||||
@slash_command(name="twitter", sub_cmd_name="unfollow", description="Unfollow Twitter accounts")
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _twitter_unfollow(self, ctx: InteractionContext) -> None:
|
||||
twitters = Twitter.objects(guild=ctx.guild.id)
|
||||
if not twitters:
|
||||
await ctx.send("You need to follow a Twitter account first", hidden=True)
|
||||
await ctx.send("You need to follow a Twitter account first", ephemeral=True)
|
||||
return
|
||||
|
||||
options = []
|
||||
|
@ -198,19 +151,19 @@ class TwitterCog(Scale):
|
|||
@slash_option(
|
||||
name="retweets",
|
||||
description="Mirror re-tweets?",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=False,
|
||||
choices=[
|
||||
SlashCommandChoice(name="Yes", value="Yes"),
|
||||
SlashCommandChoice(name="No", value="No"),
|
||||
],
|
||||
)
|
||||
@admin_or_permissions(Permissions.MANAGE_GUILD)
|
||||
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
||||
async def _twitter_modify(self, ctx: InteractionContext, retweets: str) -> None:
|
||||
retweets = retweets == "Yes"
|
||||
twitters = Twitter.objects(guild=ctx.guild.id)
|
||||
if not twitters:
|
||||
await ctx.send("You need to follow a Twitter account first", hidden=True)
|
||||
await ctx.send("You need to follow a Twitter account first", ephemeral=True)
|
||||
return
|
||||
|
||||
options = []
|
||||
|
@ -265,4 +218,4 @@ class TwitterCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add TwitterCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(TwitterCog(bot))
|
||||
TwitterCog(bot)
|
||||
|
|
|
@ -6,7 +6,8 @@ from io import BytesIO
|
|||
|
||||
import numpy as np
|
||||
from dis_snek import InteractionContext, Scale, Snake, const
|
||||
from dis_snek.models.discord.embed import Color, EmbedField
|
||||
from dis_snek.models.discord.channel import GuildCategory, GuildText, GuildVoice
|
||||
from dis_snek.models.discord.embed import EmbedField
|
||||
from dis_snek.models.discord.file import File
|
||||
from dis_snek.models.discord.guild import Guild
|
||||
from dis_snek.models.discord.role import Role
|
||||
|
@ -41,7 +42,7 @@ class UtilCog(Scale):
|
|||
self.bot = bot
|
||||
self.config = get_config()
|
||||
|
||||
@slash_command(name="Status", description="Retrieve J.A.R.V.I.S. status")
|
||||
@slash_command(name="status", description="Retrieve J.A.R.V.I.S. status")
|
||||
@cooldown(bucket=Buckets.CHANNEL, rate=1, interval=30)
|
||||
async def _status(self, ctx: InteractionContext) -> None:
|
||||
title = "J.A.R.V.I.S. Status"
|
||||
|
@ -49,7 +50,7 @@ class UtilCog(Scale):
|
|||
color = "#3498db"
|
||||
fields = []
|
||||
|
||||
fields.append(EmbedField(name="discord.py", value=const.__version__))
|
||||
fields.append(EmbedField(name="dis-snek", value=const.__version__))
|
||||
fields.append(EmbedField(name="Version", value=jarvis.__version__, inline=False))
|
||||
fields.append(EmbedField(name="Git Hash", value=get_repo_hash()[:7], inline=False))
|
||||
embed = build_embed(title=title, description=desc, fields=fields, color=color)
|
||||
|
@ -64,7 +65,7 @@ class UtilCog(Scale):
|
|||
with BytesIO() as image_bytes:
|
||||
JARVIS_LOGO.save(image_bytes, "PNG")
|
||||
image_bytes.seek(0)
|
||||
logo = File(image_bytes, filename="logo.png")
|
||||
logo = File(image_bytes, file_name="logo.png")
|
||||
await ctx.send(file=logo)
|
||||
|
||||
@slash_command(name="rchk", description="Robot Camo HK416")
|
||||
|
@ -78,13 +79,13 @@ class UtilCog(Scale):
|
|||
@slash_option(
|
||||
name="text",
|
||||
description="Text to camo-ify",
|
||||
option_type=OptionTypes.STRING,
|
||||
opt_type=OptionTypes.STRING,
|
||||
required=True,
|
||||
)
|
||||
async def _rcauto(self, ctx: InteractionContext, text: str) -> None:
|
||||
to_send = ""
|
||||
if len(text) == 1 and not re.match(r"^[A-Z0-9-()$@!?^'#. ]$", text.upper()):
|
||||
await ctx.send("Please use ASCII characters.", hidden=True)
|
||||
await ctx.send("Please use ASCII characters.", ephemeral=True)
|
||||
return
|
||||
for letter in text.upper():
|
||||
if letter == " ":
|
||||
|
@ -96,7 +97,7 @@ class UtilCog(Scale):
|
|||
else:
|
||||
to_send += f"<:{names[id]}:{id}>"
|
||||
if len(to_send) > 2000:
|
||||
await ctx.send("Too long.", hidden=True)
|
||||
await ctx.send("Too long.", ephemeral=True)
|
||||
else:
|
||||
await ctx.send(to_send)
|
||||
|
||||
|
@ -104,7 +105,7 @@ class UtilCog(Scale):
|
|||
@slash_option(
|
||||
name="user",
|
||||
description="User to view avatar of",
|
||||
option_type=OptionTypes.USER,
|
||||
opt_type=OptionTypes.USER,
|
||||
required=False,
|
||||
)
|
||||
@cooldown(bucket=Buckets.USER, rate=1, interval=5)
|
||||
|
@ -112,7 +113,7 @@ class UtilCog(Scale):
|
|||
if not user:
|
||||
user = ctx.author
|
||||
|
||||
avatar = user.display_avatar
|
||||
avatar = user.display_avatar.url
|
||||
embed = build_embed(title="Avatar", description="", fields=[], color="#00FFEE")
|
||||
embed.set_image(url=avatar)
|
||||
embed.set_author(name=f"{user.username}#{user.discriminator}", icon_url=avatar)
|
||||
|
@ -125,25 +126,25 @@ class UtilCog(Scale):
|
|||
@slash_option(
|
||||
name="role",
|
||||
description="Role to get info of",
|
||||
option_type=OptionTypes.ROLE,
|
||||
opt_type=OptionTypes.ROLE,
|
||||
required=True,
|
||||
)
|
||||
async def _roleinfo(self, ctx: InteractionContext, role: Role) -> None:
|
||||
fields = [
|
||||
EmbedField(name="ID", value=role.id),
|
||||
EmbedField(name="Name", value=role.name),
|
||||
EmbedField(name="Color", value=str(role.color)),
|
||||
EmbedField(name="Mention", value=f"`{role.mention}`"),
|
||||
EmbedField(name="Hoisted", value="Yes" if role.hoist else "No"),
|
||||
EmbedField(name="Position", value=str(role.position)),
|
||||
EmbedField(name="Mentionable", value="Yes" if role.mentionable else "No"),
|
||||
EmbedField(name="Member Count", value=role.members),
|
||||
EmbedField(name="ID", value=str(role.id), inline=True),
|
||||
EmbedField(name="Name", value=role.name, inline=True),
|
||||
EmbedField(name="Color", value=str(role.color.hex), inline=True),
|
||||
EmbedField(name="Mention", value=f"`{role.mention}`", inline=True),
|
||||
EmbedField(name="Hoisted", value="Yes" if role.hoist else "No", inline=True),
|
||||
EmbedField(name="Position", value=str(role.position), inline=True),
|
||||
EmbedField(name="Mentionable", value="Yes" if role.mentionable else "No", inline=True),
|
||||
EmbedField(name="Member Count", value=str(len(role.members)), inline=True),
|
||||
]
|
||||
embed = build_embed(
|
||||
title="",
|
||||
description="",
|
||||
fields=fields,
|
||||
color=Color.from_hex(role.color),
|
||||
color=role.color,
|
||||
timestamp=role.created_at,
|
||||
)
|
||||
embed.set_footer(text="Role Created")
|
||||
|
@ -154,14 +155,14 @@ class UtilCog(Scale):
|
|||
|
||||
fill = a > 0
|
||||
|
||||
data[..., :-1][fill.T] = list(role.color.to_rgb())
|
||||
data[..., :-1][fill.T] = list(role.color.rgb)
|
||||
|
||||
im = Image.fromarray(data)
|
||||
|
||||
with BytesIO() as image_bytes:
|
||||
im.save(image_bytes, "PNG")
|
||||
image_bytes.seek(0)
|
||||
color_show = File(image_bytes, filename="color_show.png")
|
||||
color_show = File(image_bytes, file_name="color_show.png")
|
||||
|
||||
await ctx.send(embed=embed, file=color_show)
|
||||
|
||||
|
@ -172,7 +173,7 @@ class UtilCog(Scale):
|
|||
@slash_option(
|
||||
name="user",
|
||||
description="User to get info of",
|
||||
option_type=OptionTypes.USER,
|
||||
opt_type=OptionTypes.USER,
|
||||
required=False,
|
||||
)
|
||||
async def _userinfo(self, ctx: InteractionContext, user: User = None) -> None:
|
||||
|
@ -181,15 +182,15 @@ class UtilCog(Scale):
|
|||
user_roles = user.roles
|
||||
if user_roles:
|
||||
user_roles = sorted(user.roles, key=lambda x: -x.position)
|
||||
_ = user_roles.pop(-1)
|
||||
|
||||
fields = [
|
||||
EmbedField(
|
||||
name="Joined",
|
||||
value=user.joined_at.strftime("%a, %b %-d, %Y %-I:%M %p"),
|
||||
value=user.joined_at.strftime("%a, %b %#d, %Y %#I:%M %p"),
|
||||
),
|
||||
EmbedField(
|
||||
name="Registered",
|
||||
value=user.created_at.strftime("%a, %b %-d, %Y %-I:%M %p"),
|
||||
value=user.created_at.strftime("%a, %b %#d, %Y %#I:%M %p"),
|
||||
),
|
||||
EmbedField(
|
||||
name=f"Roles [{len(user_roles)}]",
|
||||
|
@ -202,13 +203,13 @@ class UtilCog(Scale):
|
|||
title="",
|
||||
description=user.mention,
|
||||
fields=fields,
|
||||
color=Color.from_hex(str(user_roles[0].color) if user_roles else "#3498db"),
|
||||
color=str(user_roles[0].color) if user_roles else "#3498db",
|
||||
)
|
||||
|
||||
embed.set_author(
|
||||
name=f"{user.display_name}#{user.discriminator}", icon_url=user.display_avatar
|
||||
name=f"{user.display_name}#{user.discriminator}", icon_url=user.display_avatar.url
|
||||
)
|
||||
embed.set_thumbnail(url=user.display_avatar)
|
||||
embed.set_thumbnail(url=user.display_avatar.url)
|
||||
embed.set_footer(text=f"ID: {user.id}")
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
@ -217,34 +218,35 @@ class UtilCog(Scale):
|
|||
async def _server_info(self, ctx: InteractionContext) -> None:
|
||||
guild: Guild = ctx.guild
|
||||
|
||||
owner = (
|
||||
f"{guild.owner.display_name}#{guild.owner.discriminator}"
|
||||
if guild.owner
|
||||
else "||`[redacted]`||"
|
||||
)
|
||||
owner = await guild.get_owner()
|
||||
|
||||
categories = len(guild.categories)
|
||||
text_channels = len(guild.text_channels)
|
||||
voice_channels = len(guild.voice_channels)
|
||||
owner = f"{owner.username}#{owner.discriminator}" if owner else "||`[redacted]`||"
|
||||
|
||||
categories = len([x for x in guild.channels if isinstance(x, GuildCategory)])
|
||||
text_channels = len([x for x in guild.channels if isinstance(x, GuildText)])
|
||||
voice_channels = len([x for x in guild.channels if isinstance(x, GuildVoice)])
|
||||
threads = len(guild.threads)
|
||||
members = guild.member_count
|
||||
roles = len(guild.roles)
|
||||
role_list = ", ".join(role.name for role in guild.roles)
|
||||
role_list = sorted(guild.roles, key=lambda x: x.position, reverse=True)
|
||||
role_list = ", ".join(role.mention for role in role_list)
|
||||
|
||||
fields = [
|
||||
EmbedField(name="Owner", value=owner),
|
||||
EmbedField(name="Channel Categories", value=categories),
|
||||
EmbedField(name="Text Channels", value=text_channels),
|
||||
EmbedField(name="Voice Channels", value=voice_channels),
|
||||
EmbedField(name="Members", value=members),
|
||||
EmbedField(name="Roles", value=roles),
|
||||
EmbedField(name="Owner", value=owner, inline=True),
|
||||
EmbedField(name="Channel Categories", value=str(categories), inline=True),
|
||||
EmbedField(name="Text Channels", value=str(text_channels), inline=True),
|
||||
EmbedField(name="Voice Channels", value=str(voice_channels), inline=True),
|
||||
EmbedField(name="Threads", value=str(threads), inline=True),
|
||||
EmbedField(name="Members", value=str(members), inline=True),
|
||||
EmbedField(name="Roles", value=str(roles), inline=True),
|
||||
]
|
||||
if len(role_list) < 1024:
|
||||
fields.append(EmbedField(name="Role List", value=role_list, inline=False))
|
||||
|
||||
embed = build_embed(title="", description="", fields=fields, timestamp=guild.created_at)
|
||||
|
||||
embed.set_author(name=guild.name, icon_url=guild.icon_url)
|
||||
embed.set_thumbnail(url=guild.icon_url)
|
||||
embed.set_author(name=guild.name, icon_url=guild.icon.url)
|
||||
embed.set_thumbnail(url=guild.icon.url)
|
||||
embed.set_footer(text=f"ID: {guild.id} | Server Created")
|
||||
|
||||
await ctx.send(embed=embed)
|
||||
|
@ -258,13 +260,13 @@ class UtilCog(Scale):
|
|||
@slash_option(
|
||||
name="length",
|
||||
description="Password length (default 32)",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
)
|
||||
@slash_option(
|
||||
name="chars",
|
||||
description="Characters to include (default last option)",
|
||||
option_type=OptionTypes.INTEGER,
|
||||
opt_type=OptionTypes.INTEGER,
|
||||
required=False,
|
||||
choices=[
|
||||
SlashCommandChoice(name="A-Za-z", value=0),
|
||||
|
@ -276,7 +278,7 @@ class UtilCog(Scale):
|
|||
@cooldown(bucket=Buckets.USER, rate=1, interval=15)
|
||||
async def _pw_gen(self, ctx: InteractionContext, length: int = 32, chars: int = 3) -> None:
|
||||
if length > 256:
|
||||
await ctx.send("Please limit password to 256 characters", hidden=True)
|
||||
await ctx.send("Please limit password to 256 characters", ephemeral=True)
|
||||
return
|
||||
choices = [
|
||||
string.ascii_letters,
|
||||
|
@ -290,12 +292,12 @@ class UtilCog(Scale):
|
|||
f"Generated password:\n`{pw}`\n\n"
|
||||
'**WARNING: Once you press "Dismiss Message", '
|
||||
"*the password is lost forever***",
|
||||
hidden=True,
|
||||
ephemeral=True,
|
||||
)
|
||||
|
||||
@slash_command(name="pigpen", description="Encode a string into pigpen")
|
||||
@slash_option(
|
||||
name="text", description="Text to encode", option_type=OptionTypes.STRING, required=True
|
||||
name="text", description="Text to encode", opt_type=OptionTypes.STRING, required=True
|
||||
)
|
||||
async def _pigpen(self, ctx: InteractionContext, text: str) -> None:
|
||||
outp = "`"
|
||||
|
@ -314,4 +316,4 @@ class UtilCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add UtilCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(UtilCog(bot))
|
||||
UtilCog(bot)
|
||||
|
|
|
@ -89,4 +89,4 @@ class VerifyCog(Scale):
|
|||
|
||||
def setup(bot: Snake) -> None:
|
||||
"""Add VerifyCog to J.A.R.V.I.S."""
|
||||
bot.add_cog(VerifyCog(bot))
|
||||
VerifyCog(bot)
|
||||
|
|
Loading…
Add table
Reference in a new issue