Merge branch 'main' into dev
This commit is contained in:
commit
e8a419b9e3
5 changed files with 65 additions and 63 deletions
|
@ -82,8 +82,11 @@ class MessageEventMixin:
|
||||||
"dbrand",
|
"dbrand",
|
||||||
"VtgZntXcnZ",
|
"VtgZntXcnZ",
|
||||||
"gPfYGbvTCE",
|
"gPfYGbvTCE",
|
||||||
|
"interactions",
|
||||||
|
"NTSHu97tHg"
|
||||||
]
|
]
|
||||||
if (m := match.group(1)) not in allowed and setting.value:
|
is_mod = message.author.has_permission(Permissions.MANAGE_GUILD) or message.author.has_permission(Permissions.ADMINISTRATOR)
|
||||||
|
if (m := match.group(1)) not in allowed and setting.value and not is_mod:
|
||||||
self.logger.debug(f"Removing non-allowed invite `{m}` from {message.guild.id}")
|
self.logger.debug(f"Removing non-allowed invite `{m}` from {message.guild.id}")
|
||||||
try:
|
try:
|
||||||
await message.delete()
|
await message.delete()
|
||||||
|
@ -413,11 +416,11 @@ class MessageEventMixin:
|
||||||
async def on_message(self, event: MessageCreate) -> None:
|
async def on_message(self, event: MessageCreate) -> None:
|
||||||
"""Handle on_message event. Calls other event handlers."""
|
"""Handle on_message event. Calls other event handlers."""
|
||||||
message = event.message
|
message = event.message
|
||||||
|
await self.autopurge(message)
|
||||||
if not isinstance(message.channel, DMChannel) and not message.author.bot:
|
if not isinstance(message.channel, DMChannel) and not message.author.bot:
|
||||||
await self.autoreact(message)
|
await self.autoreact(message)
|
||||||
await self.massmention(message)
|
await self.massmention(message)
|
||||||
await self.roleping(message)
|
await self.roleping(message)
|
||||||
await self.autopurge(message)
|
|
||||||
await self.checks(message)
|
await self.checks(message)
|
||||||
await self.filters(message)
|
await self.filters(message)
|
||||||
if not (phish := await self.phishing(message)):
|
if not (phish := await self.phishing(message)):
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
"""JARVIS BanCog."""
|
"""JARVIS BanCog."""
|
||||||
import re
|
import re
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
from jarvis_core.db import q
|
from jarvis_core.db import q
|
||||||
from jarvis_core.db.models import Ban, Unban
|
from jarvis_core.db.models import Ban, Unban
|
||||||
|
@ -23,6 +24,8 @@ from jarvis.utils import build_embed
|
||||||
from jarvis.utils.cogs import ModcaseCog
|
from jarvis.utils.cogs import ModcaseCog
|
||||||
from jarvis.utils.permissions import admin_or_permissions
|
from jarvis.utils.permissions import admin_or_permissions
|
||||||
|
|
||||||
|
time_pattern = re.compile(r"(\d+\.?\d+?[s|m|h|d|w]{1})\s?", re.I)
|
||||||
|
|
||||||
|
|
||||||
class BanCog(ModcaseCog):
|
class BanCog(ModcaseCog):
|
||||||
"""JARVIS BanCog."""
|
"""JARVIS BanCog."""
|
||||||
|
@ -35,9 +38,10 @@ class BanCog(ModcaseCog):
|
||||||
duration: int,
|
duration: int,
|
||||||
active: bool,
|
active: bool,
|
||||||
mtype: str,
|
mtype: str,
|
||||||
|
delete_history: int = 0,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Apply a Discord ban."""
|
"""Apply a Discord ban."""
|
||||||
await ctx.guild.ban(user, reason=reason)
|
await ctx.guild.ban(user, reason=reason, delete_message_seconds=delete_history)
|
||||||
b = Ban(
|
b = Ban(
|
||||||
user=user.id,
|
user=user.id,
|
||||||
username=user.username,
|
username=user.username,
|
||||||
|
@ -81,9 +85,7 @@ class BanCog(ModcaseCog):
|
||||||
|
|
||||||
@slash_command(name="ban", description="Ban a user")
|
@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", opt_type=OptionTypes.USER, required=True)
|
||||||
@slash_option(
|
@slash_option(name="reason", description="Ban reason", opt_type=OptionTypes.STRING, required=True)
|
||||||
name="reason", description="Ban reason", opt_type=OptionTypes.STRING, required=True
|
|
||||||
)
|
|
||||||
@slash_option(
|
@slash_option(
|
||||||
name="btype",
|
name="btype",
|
||||||
description="Ban type",
|
description="Ban type",
|
||||||
|
@ -101,6 +103,12 @@ class BanCog(ModcaseCog):
|
||||||
opt_type=OptionTypes.INTEGER,
|
opt_type=OptionTypes.INTEGER,
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
|
@slash_option(
|
||||||
|
name="delete_history",
|
||||||
|
description="Delete message history, format: 1w 3d 7h 5m 20s",
|
||||||
|
opt_type=OptionTypes.STRING,
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||||
async def _ban(
|
async def _ban(
|
||||||
self,
|
self,
|
||||||
|
@ -109,6 +117,7 @@ class BanCog(ModcaseCog):
|
||||||
reason: str,
|
reason: str,
|
||||||
btype: str = "perm",
|
btype: str = "perm",
|
||||||
duration: int = 4,
|
duration: int = 4,
|
||||||
|
delete_history: str = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
if user.id == ctx.author.id:
|
if user.id == ctx.author.id:
|
||||||
await ctx.send("You cannot ban yourself.", ephemeral=True)
|
await ctx.send("You cannot ban yourself.", ephemeral=True)
|
||||||
|
@ -122,10 +131,27 @@ class BanCog(ModcaseCog):
|
||||||
elif btype == "temp" and duration > 744:
|
elif btype == "temp" and duration > 744:
|
||||||
await ctx.send("You cannot set a temp ban to > 1 month", ephemeral=True)
|
await ctx.send("You cannot set a temp ban to > 1 month", ephemeral=True)
|
||||||
return
|
return
|
||||||
|
if not time_pattern.match(delete_history):
|
||||||
|
await ctx.send("Invalid time string, please follow example: 1w 3d 7h 5m 20s", ephemeral=True)
|
||||||
|
return
|
||||||
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
|
||||||
|
|
||||||
|
if delete_history:
|
||||||
|
units = {"w": "weeks", "d": "days", "h": "hours", "m": "minutes", "s": "seconds"}
|
||||||
|
delta = {"weeks": 0, "days": 0, "hours": 0, "minutes": 0, "seconds": 0}
|
||||||
|
delete_history = delete_history.strip().lower()
|
||||||
|
if delete_history:
|
||||||
|
if times := time_pattern.findall(delete_history):
|
||||||
|
for t in times:
|
||||||
|
delta[units[t[-1]]] += float(t[:-1])
|
||||||
|
delete_history = int(timedelta(**delta).total_seconds)
|
||||||
|
|
||||||
|
if delete_history > 604800:
|
||||||
|
await ctx.send("Delete history cannot be greater than 7 days (604800 seconds)", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
await ctx.defer()
|
await ctx.defer()
|
||||||
|
|
||||||
mtype = btype
|
mtype = btype
|
||||||
|
@ -152,7 +178,7 @@ class BanCog(ModcaseCog):
|
||||||
except Exception:
|
except Exception:
|
||||||
self.logger.warn(f"Failed to send ban embed to {user.id}")
|
self.logger.warn(f"Failed to send ban embed to {user.id}")
|
||||||
try:
|
try:
|
||||||
await ctx.guild.ban(user, reason=reason)
|
await self.discord_apply_ban(ctx, reason, user, duration, active, mtype, delete_history or 0)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await ctx.send(f"Failed to ban user:\n```\n{e}\n```", ephemeral=True)
|
await ctx.send(f"Failed to ban user:\n```\n{e}\n```", ephemeral=True)
|
||||||
return
|
return
|
||||||
|
@ -166,15 +192,9 @@ class BanCog(ModcaseCog):
|
||||||
if btype == "soft":
|
if btype == "soft":
|
||||||
active = False
|
active = False
|
||||||
|
|
||||||
await self.discord_apply_ban(ctx, reason, user, duration, active, mtype)
|
|
||||||
|
|
||||||
@slash_command(name="unban", description="Unban a user")
|
@slash_command(name="unban", description="Unban a user")
|
||||||
@slash_option(
|
@slash_option(name="user", description="User to unban", opt_type=OptionTypes.STRING, required=True)
|
||||||
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
|
|
||||||
)
|
|
||||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||||
async def _unban(
|
async def _unban(
|
||||||
self,
|
self,
|
||||||
|
@ -212,14 +232,9 @@ class BanCog(ModcaseCog):
|
||||||
if len(results) > 1:
|
if len(results) > 1:
|
||||||
active_bans = []
|
active_bans = []
|
||||||
for ban in bans:
|
for ban in bans:
|
||||||
active_bans.append(
|
active_bans.append("{0} ({1}): {2}".format(ban.user.username, ban.user.id, ban.reason))
|
||||||
"{0} ({1}): {2}".format(ban.user.username, ban.user.id, ban.reason)
|
|
||||||
)
|
|
||||||
ab_message = "\n".join(active_bans)
|
ab_message = "\n".join(active_bans)
|
||||||
message = (
|
message = "More than one result. " f"Please use one of the following IDs:\n```{ab_message}\n```"
|
||||||
"More than one result. "
|
|
||||||
f"Please use one of the following IDs:\n```{ab_message}\n```"
|
|
||||||
)
|
|
||||||
await ctx.send(message)
|
await ctx.send(message)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
@ -230,9 +245,7 @@ class BanCog(ModcaseCog):
|
||||||
# We take advantage of the previous checks to save CPU cycles
|
# We take advantage of the previous checks to save CPU cycles
|
||||||
if not discord_ban_info:
|
if not discord_ban_info:
|
||||||
if isinstance(user, User):
|
if isinstance(user, User):
|
||||||
database_ban_info = await Ban.find_one(
|
database_ban_info = await Ban.find_one(q(guild=ctx.guild.id, user=user.id, active=True))
|
||||||
q(guild=ctx.guild.id, user=user.id, active=True)
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
search = {
|
search = {
|
||||||
"guild": ctx.guild.id,
|
"guild": ctx.guild.id,
|
||||||
|
@ -288,9 +301,7 @@ class BanCog(ModcaseCog):
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
@check(admin_or_permissions(Permissions.BAN_MEMBERS))
|
||||||
async def _bans_list(
|
async def _bans_list(self, ctx: InteractionContext, btype: int = 0, active: bool = True) -> None:
|
||||||
self, ctx: InteractionContext, btype: int = 0, active: bool = True
|
|
||||||
) -> None:
|
|
||||||
types = [0, "perm", "temp", "soft"]
|
types = [0, "perm", "temp", "soft"]
|
||||||
search = {"guild": ctx.guild.id}
|
search = {"guild": ctx.guild.id}
|
||||||
if active:
|
if active:
|
||||||
|
|
|
@ -145,7 +145,7 @@ class DbrandCog(Extension):
|
||||||
title="Contact Support",
|
title="Contact Support",
|
||||||
description="",
|
description="",
|
||||||
fields=fields,
|
fields=fields,
|
||||||
url="https://dbrand.com/support",
|
url="https://dbrand.com/contact",
|
||||||
color=color,
|
color=color,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,8 @@ class RemindmeCog(Extension):
|
||||||
) -> None:
|
) -> None:
|
||||||
if private is None and ctx.guild:
|
if private is None and ctx.guild:
|
||||||
private = ctx.guild.member_count >= 5000
|
private = ctx.guild.member_count >= 5000
|
||||||
|
elif private is None and not ctx.guild:
|
||||||
|
private = False
|
||||||
modal = Modal(
|
modal = Modal(
|
||||||
title="Set your reminder!",
|
title="Set your reminder!",
|
||||||
components=[
|
components=[
|
||||||
|
@ -94,9 +96,7 @@ class RemindmeCog(Extension):
|
||||||
await response.send("Hey, you should probably make this readable", ephemeral=True)
|
await response.send("Hey, you should probably make this readable", ephemeral=True)
|
||||||
return
|
return
|
||||||
elif len(message) == 0:
|
elif len(message) == 0:
|
||||||
await response.send(
|
await response.send("Hey, you should probably add content to your reminder", ephemeral=True)
|
||||||
"Hey, you should probably add content to your reminder", ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
base_settings = {
|
base_settings = {
|
||||||
|
@ -105,9 +105,7 @@ class RemindmeCog(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_remind_at = parse(delay, settings=rt_settings)
|
rt_remind_at = parse(delay, settings=rt_settings)
|
||||||
|
|
||||||
|
@ -121,15 +119,11 @@ class RemindmeCog(Extension):
|
||||||
remind_at = at_remind_at
|
remind_at = at_remind_at
|
||||||
else:
|
else:
|
||||||
self.logger.debug(f"Failed to parse delay: {delay}")
|
self.logger.debug(f"Failed to parse delay: {delay}")
|
||||||
await response.send(
|
await response.send(f"`{delay}` is not a parsable date, please try again", ephemeral=True)
|
||||||
f"`{delay}` is not a parsable date, please try again", ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if remind_at < datetime.now(tz=timezone.utc):
|
if remind_at < datetime.now(tz=timezone.utc):
|
||||||
await response.send(
|
await response.send(f"`{delay}` is in the past. Past reminders aren't allowed", ephemeral=True)
|
||||||
f"`{delay}` is in the past. Past reminders aren't allowed", ephemeral=True
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
elif remind_at < datetime.now(tz=timezone.utc):
|
elif remind_at < datetime.now(tz=timezone.utc):
|
||||||
|
@ -165,18 +159,16 @@ class RemindmeCog(Extension):
|
||||||
icon_url=ctx.author.display_avatar.url,
|
icon_url=ctx.author.display_avatar.url,
|
||||||
)
|
)
|
||||||
embed.set_thumbnail(url=ctx.author.display_avatar.url)
|
embed.set_thumbnail(url=ctx.author.display_avatar.url)
|
||||||
|
delete_button = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}")
|
||||||
delete_button = Button(
|
components = [delete_button]
|
||||||
style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}"
|
if not r.guild == ctx.author.id:
|
||||||
)
|
|
||||||
copy_button = Button(style=ButtonStyles.GREEN, emoji="📋", custom_id=f"copy|rme|{r.id}")
|
copy_button = Button(style=ButtonStyles.GREEN, emoji="📋", custom_id=f"copy|rme|{r.id}")
|
||||||
components = [ActionRow(delete_button, copy_button)]
|
components.append(copy_button)
|
||||||
private = private if private is not None else False
|
private = private if private is not None else False
|
||||||
|
components = [ActionRow(*components)]
|
||||||
await response.send(embeds=embed, components=components, ephemeral=private)
|
await response.send(embeds=embed, components=components, ephemeral=private)
|
||||||
|
|
||||||
async def get_reminders_embed(
|
async def get_reminders_embed(self, ctx: InteractionContext, reminders: List[Reminder]) -> Embed:
|
||||||
self, ctx: InteractionContext, reminders: List[Reminder]
|
|
||||||
) -> Embed:
|
|
||||||
"""Build embed for paginator."""
|
"""Build embed for paginator."""
|
||||||
fields = []
|
fields = []
|
||||||
for reminder in reminders:
|
for reminder in reminders:
|
||||||
|
@ -219,9 +211,7 @@ class RemindmeCog(Extension):
|
||||||
return
|
return
|
||||||
|
|
||||||
embed = await self.get_reminders_embed(ctx, reminders)
|
embed = await self.get_reminders_embed(ctx, reminders)
|
||||||
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)
|
||||||
|
|
||||||
@reminders.subcommand(sub_cmd_name="delete", sub_cmd_description="Delete a reminder")
|
@reminders.subcommand(sub_cmd_name="delete", sub_cmd_description="Delete a reminder")
|
||||||
|
@ -254,9 +244,7 @@ class RemindmeCog(Extension):
|
||||||
)
|
)
|
||||||
embed.set_thumbnail(url=ctx.author.display_avatar.url)
|
embed.set_thumbnail(url=ctx.author.display_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}"
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
await reminder.delete()
|
await reminder.delete()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -288,18 +276,14 @@ class RemindmeCog(Extension):
|
||||||
EmbedField(name="Created At", value=f"<t:{cts}:F> (<t:{cts}:R>)"),
|
EmbedField(name="Created At", value=f"<t:{cts}:F> (<t:{cts}:R>)"),
|
||||||
]
|
]
|
||||||
|
|
||||||
embed = build_embed(
|
embed = build_embed(title="You have a reminder!", description=reminder.message, fields=fields)
|
||||||
title="You have a reminder!", description=reminder.message, fields=fields
|
|
||||||
)
|
|
||||||
embed.set_author(
|
embed.set_author(
|
||||||
name=ctx.author.display_name + "#" + ctx.author.discriminator,
|
name=ctx.author.display_name + "#" + ctx.author.discriminator,
|
||||||
icon_url=ctx.author.display_avatar.url,
|
icon_url=ctx.author.display_avatar.url,
|
||||||
)
|
)
|
||||||
|
|
||||||
embed.set_thumbnail(url=ctx.author.display_avatar.url)
|
embed.set_thumbnail(url=ctx.author.display_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, ephemeral=reminder.private, components=components)
|
await ctx.send(embeds=embed, ephemeral=reminder.private, components=components)
|
||||||
if reminder.remind_at <= datetime.now(tz=timezone.utc) and not reminder.active:
|
if reminder.remind_at <= datetime.now(tz=timezone.utc) and not reminder.active:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -56,6 +56,10 @@ class UtilCog(Extension):
|
||||||
async def _sex(self, ctx: InteractionContext) -> None:
|
async def _sex(self, ctx: InteractionContext) -> None:
|
||||||
if ctx.author.id == 264072583987593217:
|
if ctx.author.id == 264072583987593217:
|
||||||
await ctx.send("Oh fuck no, go fuck yourself")
|
await ctx.send("Oh fuck no, go fuck yourself")
|
||||||
|
elif ctx.author.id == 840031256201003008:
|
||||||
|
await ctx.send("https://tenor.com/view/fluffy-gabriel-iglesias-you-need-jesus-thats-what-you-need-pointing-up-gif-16385108")
|
||||||
|
elif ctx.author.id == 215564028615852033:
|
||||||
|
await ctx.send("As flattered as I am, I'm not into bestiality")
|
||||||
else:
|
else:
|
||||||
await ctx.send("Not at this time, thank you for offering")
|
await ctx.send("Not at this time, thank you for offering")
|
||||||
|
|
||||||
|
@ -223,7 +227,7 @@ class UtilCog(Extension):
|
||||||
)
|
)
|
||||||
@cooldown(bucket=Buckets.USER, rate=1, interval=5)
|
@cooldown(bucket=Buckets.USER, rate=1, interval=5)
|
||||||
async def _avatar_slash(self, ctx: InteractionContext, user: User = None) -> None:
|
async def _avatar_slash(self, ctx: InteractionContext, user: User = None) -> None:
|
||||||
await self._userinfo(ctx, user)
|
await self._avatar(ctx, user)
|
||||||
|
|
||||||
@context_menu(name="Avatar", context_type=CommandTypes.USER)
|
@context_menu(name="Avatar", context_type=CommandTypes.USER)
|
||||||
async def _avatar_menu(self, ctx: InteractionContext) -> None:
|
async def _avatar_menu(self, ctx: InteractionContext) -> None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue