378 lines
12 KiB
Python
378 lines
12 KiB
Python
from datetime import datetime, timedelta
|
|
|
|
from ButtonPaginator import Paginator
|
|
from discord import Member, Role
|
|
from discord.ext import commands
|
|
from discord_slash import SlashContext, cog_ext
|
|
from discord_slash.model import ButtonStyle
|
|
from discord_slash.utils.manage_commands import create_option
|
|
|
|
from jarvis.db.types import Roleping
|
|
from jarvis.utils import build_embed
|
|
from jarvis.utils.cachecog import CacheCog
|
|
from jarvis.utils.field import Field
|
|
from jarvis.utils.permissions import admin_or_permissions
|
|
|
|
|
|
class RolepingCog(CacheCog):
|
|
def __init__(self, bot):
|
|
super().__init__(bot)
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="roleping",
|
|
name="add",
|
|
description="Add a role to roleping",
|
|
options=[
|
|
create_option(
|
|
name="role",
|
|
description="Role to add to roleping",
|
|
option_type=8,
|
|
required=True,
|
|
)
|
|
],
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _roleping_add(self, ctx: SlashContext, role: Role):
|
|
roleping = Roleping.get(guild=ctx.guild.id, role=role.id)
|
|
if not roleping:
|
|
roleping = Roleping(
|
|
role=role.id,
|
|
guild=ctx.guild.id,
|
|
admin=ctx.author.id,
|
|
active=True,
|
|
bypass={"roles": [], "users": []},
|
|
)
|
|
|
|
else:
|
|
await ctx.send(
|
|
f"Role `{role.name}` already in roleping.", hidden=True
|
|
)
|
|
return
|
|
|
|
roleping.insert()
|
|
await ctx.send(f"Role `{role.name}` added to roleping.")
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="roleping",
|
|
name="remove",
|
|
description="Remove a role from the roleping",
|
|
options=[
|
|
create_option(
|
|
name="role",
|
|
description="Role to remove from roleping",
|
|
option_type=8,
|
|
required=True,
|
|
)
|
|
],
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _roleping_remove(self, ctx: SlashContext, role: Role):
|
|
roleping = Roleping.get(guild=ctx.guild.id, role=role.id)
|
|
if not roleping:
|
|
await ctx.send("Roleping does not exist", hidden=True)
|
|
return
|
|
|
|
roleping.delete()
|
|
await ctx.send(f"Role `{role.name}` removed from roleping.")
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="roleping",
|
|
name="list",
|
|
description="List all blocklisted roles",
|
|
)
|
|
async def _roleping_list(self, ctx: SlashContext):
|
|
exists = self.check_cache(ctx)
|
|
if exists:
|
|
await ctx.defer(hidden=True)
|
|
await ctx.send(
|
|
"Please use existing interaction: "
|
|
+ f"{exists['paginator']._message.jump_url}",
|
|
hidden=True,
|
|
)
|
|
return
|
|
|
|
rolepings = Roleping.get_many(guild=ctx.guild.id)
|
|
if not rolepings:
|
|
await ctx.send("No rolepings configured", hidden=True)
|
|
return
|
|
|
|
embeds = []
|
|
for roleping in rolepings:
|
|
role = ctx.guild.get_role(roleping.role)
|
|
bypass_roles = list(
|
|
filter(
|
|
lambda x: x.id in roleping.bypass["roles"], ctx.guild.roles
|
|
)
|
|
)
|
|
bypass_roles = [
|
|
r.mention or "||`[redacted]`||" for r in bypass_roles
|
|
]
|
|
bypass_users = [
|
|
ctx.guild.get_member(u).mention or "||`[redacted]`||"
|
|
for u in roleping.bypass["users"]
|
|
]
|
|
bypass_roles = bypass_roles or ["None"]
|
|
bypass_users = bypass_users or ["None"]
|
|
embed = build_embed(
|
|
title="Roleping",
|
|
description=role.mention,
|
|
color=str(role.color),
|
|
fields=[
|
|
Field(
|
|
name="Created At",
|
|
value=roleping.created_at.strftime(
|
|
"%a, %b %d, %Y %I:%M %p"
|
|
),
|
|
inline=False,
|
|
),
|
|
Field(name="Active", value=str(roleping.active)),
|
|
Field(
|
|
name="Bypass Users",
|
|
value="\n".join(bypass_users),
|
|
),
|
|
Field(
|
|
name="Bypass Roles",
|
|
value="\n".join(bypass_roles),
|
|
),
|
|
],
|
|
)
|
|
|
|
admin = ctx.guild.get_member(roleping.admin)
|
|
if not admin:
|
|
admin = self.bot.user
|
|
|
|
embed.set_author(
|
|
name=admin.nick or admin.name, icon_url=admin.avatar_url
|
|
)
|
|
embed.set_footer(
|
|
text=f"{admin.name}#{admin.discriminator} | {admin.id}"
|
|
)
|
|
|
|
embeds.append(embed)
|
|
|
|
paginator = Paginator(
|
|
bot=self.bot,
|
|
ctx=ctx,
|
|
embeds=embeds,
|
|
only=ctx.author,
|
|
timeout=60 * 5, # 5 minute timeout
|
|
disable_after_timeout=True,
|
|
use_extend=len(embeds) > 2,
|
|
left_button_style=ButtonStyle.grey,
|
|
right_button_style=ButtonStyle.grey,
|
|
basic_buttons=["◀", "▶"],
|
|
)
|
|
|
|
self.cache[hash(paginator)] = {
|
|
"user": ctx.author.id,
|
|
"guild": ctx.guild.id,
|
|
"timeout": datetime.utcnow() + timedelta(minutes=5),
|
|
"command": ctx.subcommand_name,
|
|
"paginator": paginator,
|
|
}
|
|
|
|
await paginator.start()
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="roleping",
|
|
subcommand_group="bypass",
|
|
name="user",
|
|
description="Add a user as a bypass to a roleping",
|
|
base_desc="Block roles from being pinged",
|
|
sub_group_desc="Allow specific users/roles to ping rolepings",
|
|
options=[
|
|
create_option(
|
|
name="user",
|
|
description="User to add",
|
|
option_type=6,
|
|
required=True,
|
|
),
|
|
create_option(
|
|
name="rping",
|
|
description="Rolepinged role",
|
|
option_type=8,
|
|
required=True,
|
|
),
|
|
],
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _roleping_bypass_user(
|
|
self, ctx: SlashContext, user: Member, rping: Role
|
|
):
|
|
roleping = Roleping.get(guild=ctx.guild.id, role=rping.id)
|
|
if not roleping:
|
|
await ctx.send(
|
|
f"Roleping not configured for {rping.mention}", hidden=True
|
|
)
|
|
return
|
|
|
|
if user.id in roleping.bypass["users"]:
|
|
await ctx.send(f"{user.mention} already in bypass", hidden=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,
|
|
)
|
|
return
|
|
|
|
matching_role = list(
|
|
filter(lambda x: x.id in roleping.bypass["roles"], user.roles)
|
|
)
|
|
|
|
if matching_role:
|
|
await ctx.send(
|
|
f"{user.mention} already has bypass "
|
|
f"via {matching_role[0].mention}",
|
|
hidden=True,
|
|
)
|
|
return
|
|
|
|
roleping.bypass["users"].append(user.id)
|
|
roleping.update()
|
|
await ctx.send(
|
|
f"{user.nick or user.name} user bypass added for `{rping.name}`"
|
|
)
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="roleping",
|
|
subcommand_group="bypass",
|
|
name="role",
|
|
description="Add a role as a bypass to a roleping",
|
|
base_desc="Block roles from being pinged",
|
|
sub_group_desc="Allow specific users/roles to ping rolepings",
|
|
options=[
|
|
create_option(
|
|
name="role",
|
|
description="Role to add",
|
|
option_type=8,
|
|
required=True,
|
|
),
|
|
create_option(
|
|
name="rping",
|
|
description="Rolepinged role",
|
|
option_type=8,
|
|
required=True,
|
|
),
|
|
],
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _roleping_bypass_role(
|
|
self, ctx: SlashContext, role: Role, rping: Role
|
|
):
|
|
roleping = Roleping.get(guild=ctx.guild.id, role=rping.id)
|
|
if not roleping:
|
|
await ctx.send(
|
|
f"Roleping not configured for {rping.mention}", hidden=True
|
|
)
|
|
return
|
|
|
|
if role.id in roleping.bypass["roles"]:
|
|
await ctx.send(f"{role.mention} already in bypass", hidden=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,
|
|
)
|
|
return
|
|
|
|
roleping.bypass["roles"].append(role.id)
|
|
roleping.update()
|
|
await ctx.send(f"{role.name} role bypass added for `{rping.name}`")
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="roleping",
|
|
subcommand_group="restore",
|
|
name="user",
|
|
description="Remove a role bypass",
|
|
base_desc="Block roles from being pinged",
|
|
sub_group_desc="Remove a bypass from a roleping (restoring it)",
|
|
options=[
|
|
create_option(
|
|
name="user",
|
|
description="User to add",
|
|
option_type=6,
|
|
required=True,
|
|
),
|
|
create_option(
|
|
name="rping",
|
|
description="Rolepinged role",
|
|
option_type=8,
|
|
required=True,
|
|
),
|
|
],
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _roleping_restore_user(
|
|
self, ctx: SlashContext, user: Member, rping: Role
|
|
):
|
|
roleping = Roleping.get(guild=ctx.guild.id, role=rping.id)
|
|
if not roleping:
|
|
await ctx.send(
|
|
f"Roleping not configured for {rping.mention}", hidden=True
|
|
)
|
|
return
|
|
|
|
if user.id not in roleping.bypass["users"]:
|
|
await ctx.send(f"{user.mention} not in bypass", hidden=True)
|
|
return
|
|
|
|
roleping.bypass["users"].delete(user.id)
|
|
roleping.update()
|
|
await ctx.send(
|
|
f"{user.nick or user.name} user bypass removed for `{rping.name}`"
|
|
)
|
|
|
|
@cog_ext.cog_subcommand(
|
|
base="roleping",
|
|
subcommand_group="restore",
|
|
name="role",
|
|
description="Remove a role bypass",
|
|
base_desc="Block roles from being pinged",
|
|
sub_group_desc="Remove a bypass from a roleping (restoring it)",
|
|
options=[
|
|
create_option(
|
|
name="role",
|
|
description="Role to add",
|
|
option_type=8,
|
|
required=True,
|
|
),
|
|
create_option(
|
|
name="rping",
|
|
description="Rolepinged role",
|
|
option_type=8,
|
|
required=True,
|
|
),
|
|
],
|
|
)
|
|
@admin_or_permissions(manage_guild=True)
|
|
async def _roleping_restore_role(
|
|
self, ctx: SlashContext, role: Role, rping: Role
|
|
):
|
|
roleping = Roleping.get(guild=ctx.guild.id, role=rping.id)
|
|
if not roleping:
|
|
await ctx.send(
|
|
f"Roleping not configured for {rping.mention}", hidden=True
|
|
)
|
|
return
|
|
|
|
if role.id in roleping.bypass["roles"]:
|
|
await ctx.send(f"{role.mention} already in bypass", hidden=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,
|
|
)
|
|
return
|
|
|
|
roleping.bypass["roles"].append(role.id)
|
|
roleping.update()
|
|
await ctx.send(f"{role.name} role bypass added for `{rping.name}`")
|