174 lines
6.3 KiB
Python
174 lines
6.3 KiB
Python
import logging
|
|
from typing import Literal
|
|
|
|
import discord
|
|
from redbot import VersionInfo, version_info
|
|
from redbot.core import Config, checks, commands
|
|
from redbot.core.i18n import Translator, cog_i18n
|
|
|
|
_ = Translator("StickyRoles", __file__)
|
|
log = logging.getLogger("red.trusty-cogs.stickyroles")
|
|
|
|
|
|
@cog_i18n(_)
|
|
class StickyRoles(commands.Cog):
|
|
"""
|
|
Reapplies specific roles on join. Rewritten for V3 from
|
|
|
|
https://github.com/Twentysix26/26-Cogs/blob/master/stickyroles/stickyroles.py
|
|
"""
|
|
|
|
__author__ = ["Twentysix", "TrustyJAID"]
|
|
__version__ = "2.0.1"
|
|
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
self.config = Config.get_conf(self, 1358454876)
|
|
self.config.register_guild(sticky_roles=[], to_reapply={})
|
|
|
|
def format_help_for_context(self, ctx: commands.Context) -> str:
|
|
"""
|
|
Thanks Sinbad!
|
|
"""
|
|
pre_processed = super().format_help_for_context(ctx)
|
|
return f"{pre_processed}\n\nCog Version: {self.__version__}"
|
|
|
|
async def red_delete_data_for_user(
|
|
self,
|
|
*,
|
|
requester: Literal["discord_deleted_user", "owner", "user", "user_strict"],
|
|
user_id: int,
|
|
):
|
|
"""
|
|
Method for finding users data inside the cog and deleting it.
|
|
"""
|
|
all_guilds = await self.config.all_guilds()
|
|
for guild_id, data in all_guilds.items():
|
|
if str(user_id) in data["to_reapply"]:
|
|
del data["to_reapply"][str(user_id)]
|
|
await self.config.guild_from_id(guild_id).to_reapply.set(data["to_reapply"])
|
|
|
|
@commands.group(aliases=["stickyrole"])
|
|
@checks.admin()
|
|
async def stickyroles(self, ctx: commands.Context) -> None:
|
|
"""Adds / removes roles to be reapplied on join"""
|
|
pass
|
|
|
|
@stickyroles.command()
|
|
async def add(self, ctx: commands.Context, *, role: discord.Role) -> None:
|
|
"""Adds role to be reapplied on join"""
|
|
guild = ctx.message.guild
|
|
sticky_roles = await self.config.guild(guild).sticky_roles()
|
|
if not guild.me.top_role.position > role.position:
|
|
msg = _(
|
|
"I don't have enough permissions to add that "
|
|
"role. Remember to take role hierarchy in "
|
|
"consideration."
|
|
)
|
|
await ctx.send(msg)
|
|
return
|
|
if role.id in sticky_roles:
|
|
await ctx.send(role.name + _(" is already in the sticky roles."))
|
|
return
|
|
sticky_roles.append(role.id)
|
|
await self.config.guild(guild).sticky_roles.set(sticky_roles)
|
|
await ctx.send(_("That role will now be reapplied on join."))
|
|
|
|
@stickyroles.command()
|
|
async def remove(self, ctx: commands.Context, *, role: discord.Role) -> None:
|
|
"""Removes role to be reapplied on join"""
|
|
guild = ctx.message.guild
|
|
sticky_roles = await self.config.guild(guild).sticky_roles()
|
|
if role.id not in sticky_roles:
|
|
await ctx.send(_("That role was never added in the first place."))
|
|
return
|
|
sticky_roles.remove(role.id)
|
|
await self.config.guild(guild).sticky_roles.set(sticky_roles)
|
|
await ctx.send(_("That role won't be reapplied on join."))
|
|
|
|
@stickyroles.command()
|
|
async def clear(self, ctx: commands.Context) -> None:
|
|
"""Removes all sticky roles"""
|
|
guild = ctx.message.guild
|
|
await self.config.guild(guild).sticky_roles.clear()
|
|
await self.config.guild(guild).to_reapply.clear()
|
|
await ctx.send(_("All sticky roles have been removed."))
|
|
|
|
@stickyroles.command(name="list")
|
|
async def _list(self, ctx: commands.Context):
|
|
"""Lists sticky roles"""
|
|
guild = ctx.message.guild
|
|
roles = await self.config.guild(guild).sticky_roles()
|
|
roles = [guild.get_role(r) for r in await self.config.guild(guild).sticky_roles()]
|
|
roles = [r.name for r in roles if r is not None]
|
|
if roles:
|
|
await ctx.send(_("Sticky roles:\n\n") + ", ".join(roles))
|
|
else:
|
|
msg = _("No sticky roles. Add some with ") + "`{}stickyroles add`".format(ctx.prefix)
|
|
await ctx.send(msg)
|
|
|
|
@commands.Cog.listener()
|
|
async def on_member_remove(self, member: discord.Member):
|
|
guild = member.guild
|
|
if version_info >= VersionInfo.from_str("3.4.0"):
|
|
if await self.bot.cog_disabled_in_guild(self, guild):
|
|
return
|
|
sticky_roles = await self.config.guild(guild).sticky_roles()
|
|
to_reapply = await self.config.guild(guild).to_reapply()
|
|
if sticky_roles is None:
|
|
return
|
|
|
|
save = False
|
|
|
|
for role in member.roles:
|
|
if role.id in sticky_roles:
|
|
if str(member.id) not in to_reapply:
|
|
to_reapply[str(member.id)] = []
|
|
to_reapply[str(member.id)].append(role.id)
|
|
save = True
|
|
|
|
if save:
|
|
await self.config.guild(guild).to_reapply.set(to_reapply)
|
|
|
|
@commands.Cog.listener()
|
|
async def on_member_join(self, member: discord.Member):
|
|
guild = member.guild
|
|
if version_info >= VersionInfo.from_str("3.4.0"):
|
|
if await self.bot.cog_disabled_in_guild(self, guild):
|
|
return
|
|
sticky_roles = await self.config.guild(guild).sticky_roles()
|
|
to_reapply = await self.config.guild(guild).to_reapply()
|
|
if to_reapply is None:
|
|
return
|
|
|
|
if str(member.id) not in to_reapply:
|
|
return
|
|
|
|
to_add = []
|
|
|
|
for role_id in to_reapply[str(member.id)]:
|
|
if role_id not in sticky_roles:
|
|
continue
|
|
role = discord.utils.get(guild.roles, id=role_id)
|
|
if role:
|
|
to_add.append(role)
|
|
|
|
del to_reapply[str(member.id)]
|
|
|
|
if to_add:
|
|
try:
|
|
await member.add_roles(*to_add, reason="Sticky roles")
|
|
except discord.Forbidden:
|
|
log.info(
|
|
_("Failed to add roles")
|
|
+ _("I lack permissions to do that.")
|
|
+ "{} ({})\n{}\n".format(member, member.id, to_add)
|
|
)
|
|
except discord.HTTPException:
|
|
msg = _("Failed to add roles to ") + "{} ({})\n{}".format(
|
|
member, member.id, to_add
|
|
)
|
|
log.exception(msg)
|
|
|
|
await self.config.guild(guild).to_reapply.set(to_reapply)
|