Delete modules/reaction_role/reaction_role.py
This commit is contained in:
parent
5b2aa79b9f
commit
c88edf1fdd
@ -1,219 +0,0 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from modules.common.emoji_accept import is_accept
|
||||
|
||||
CHECKMARK = '✅'
|
||||
|
||||
class ReactionRoleCog(commands.Cog):
|
||||
"""
|
||||
Records agreements and manages Full Access.
|
||||
Nickname flow:
|
||||
• Add accept on nickname message -> mark agreed + pending (idempotent) and open ONE review
|
||||
• Remove accept on nickname message -> clear only if user has no accept reactions left
|
||||
Full Access: granted when Rules ✅ + RoE ✅ + Nickname *claimed* (pending or verified).
|
||||
Revoked when any of the three is missing.
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
cfg = bot.config['DEFAULT']
|
||||
|
||||
def _i(key):
|
||||
try:
|
||||
v = cfg.get(key)
|
||||
return int(v) if v else 0
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
self.rules_msg_id = _i('rules_message_id')
|
||||
self.engage_msg_id = _i('engagement_message_id')
|
||||
self.nick_msg_id = _i('nickname_message_id')
|
||||
self.rules_role = _i('rules_role_id')
|
||||
self.engage_role = _i('engagement_role_id')
|
||||
self.full_access_role = _i('full_access_role_id')
|
||||
|
||||
# ---- helpers ----
|
||||
def _has_rules(self, member_id: int) -> bool:
|
||||
return member_id in self.bot.data_manager.get('agreed_rules')
|
||||
|
||||
def _has_engage(self, member_id: int) -> bool:
|
||||
return member_id in self.bot.data_manager.get('agreed_engagement')
|
||||
|
||||
def _has_nick_claim(self, member_id: int) -> bool:
|
||||
"""Claimed = agreed_nickname; pending/verified tracked separately."""
|
||||
return member_id in self.bot.data_manager.get('agreed_nickname')
|
||||
|
||||
async def maybe_apply_full_access(self, member: discord.Member):
|
||||
"""Grant when Rules+RoE+Nickname *claimed*; revoke when any missing."""
|
||||
guild = member.guild
|
||||
role = guild.get_role(self.full_access_role) if self.full_access_role else None
|
||||
if not role:
|
||||
return
|
||||
|
||||
has_all = self._has_rules(member.id) and self._has_engage(member.id) and self._has_nick_claim(member.id)
|
||||
try:
|
||||
if has_all and role not in member.roles:
|
||||
await member.add_roles(role, reason="All agreements completed (nickname may be pending)")
|
||||
elif not has_all and role in member.roles:
|
||||
await member.remove_roles(role, reason="Agreements incomplete or nickname unclaimed")
|
||||
except discord.Forbidden:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Best-effort: refresh user card
|
||||
cards = self.bot.get_cog('UserCardsCog')
|
||||
if cards:
|
||||
try:
|
||||
await cards.refresh_card(member)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
async def _get_member(self, guild: discord.Guild, user_id: int):
|
||||
if not guild:
|
||||
return None
|
||||
m = guild.get_member(user_id)
|
||||
if m is None:
|
||||
try:
|
||||
m = await guild.fetch_member(user_id)
|
||||
except Exception:
|
||||
return None
|
||||
return m
|
||||
|
||||
async def _user_has_any_accept(self, guild: discord.Guild, channel_id: int, message_id: int, user_id: int) -> bool:
|
||||
"""Return True if the user still has at least one 'accept' reaction on the message."""
|
||||
try:
|
||||
ch = guild.get_channel(channel_id)
|
||||
if not ch:
|
||||
return False
|
||||
msg = await ch.fetch_message(message_id)
|
||||
for rxn in msg.reactions:
|
||||
if is_accept(rxn.emoji):
|
||||
async for u in rxn.users(limit=None):
|
||||
if u.id == user_id:
|
||||
return True
|
||||
return False
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
# ---- commands (hybrid = prefix + slash) ----
|
||||
@commands.hybrid_command(name='nick_same', description='Claim that your global display name matches your in-game name (triggers mod review)')
|
||||
async def nick_same(self, ctx: commands.Context):
|
||||
member = ctx.author if isinstance(ctx.author, discord.Member) else None
|
||||
if not member or not ctx.guild:
|
||||
return await ctx.reply("Use this in a server.", ephemeral=True)
|
||||
|
||||
dm = self.bot.data_manager
|
||||
if member.id not in dm.get('agreed_nickname'):
|
||||
dm.add('agreed_nickname', int(member.id))
|
||||
# Mark pending (clear verified if present)
|
||||
dm.remove('nick_verified', lambda x: x == member.id)
|
||||
newly_pending = False
|
||||
if member.id not in dm.get('nick_claim_pending'):
|
||||
dm.add('nick_claim_pending', int(member.id))
|
||||
newly_pending = True
|
||||
|
||||
# Open/refresh a review with NickNudge (only on first transition to pending)
|
||||
if newly_pending:
|
||||
nn = self.bot.get_cog('NickNudgeCog')
|
||||
if nn and hasattr(nn, 'start_nick_review'):
|
||||
try:
|
||||
await nn.start_nick_review(ctx.guild, member, source="nick_same")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
await self.maybe_apply_full_access(member)
|
||||
await ctx.reply("Thanks — your nickname claim was sent for moderator review.", ephemeral=True)
|
||||
|
||||
# ---- listeners ----
|
||||
@commands.Cog.listener()
|
||||
async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent):
|
||||
if not payload.guild_id or not is_accept(payload.emoji):
|
||||
return
|
||||
guild = self.bot.get_guild(payload.guild_id)
|
||||
member = await self._get_member(guild, payload.user_id)
|
||||
if not member or member.bot:
|
||||
return
|
||||
|
||||
dm = self.bot.data_manager
|
||||
try:
|
||||
if payload.message_id == self.rules_msg_id:
|
||||
role = guild.get_role(self.rules_role)
|
||||
if role:
|
||||
await member.add_roles(role, reason="Agreed to rules")
|
||||
if member.id not in dm.get('agreed_rules'):
|
||||
dm.add('agreed_rules', int(member.id))
|
||||
|
||||
elif payload.message_id == self.engage_msg_id:
|
||||
role = guild.get_role(self.engage_role)
|
||||
if role:
|
||||
await member.add_roles(role, reason="Agreed to engagement")
|
||||
if member.id not in dm.get('agreed_engagement'):
|
||||
dm.add('agreed_engagement', int(member.id))
|
||||
|
||||
elif payload.message_id == self.nick_msg_id:
|
||||
# Claim nickname via reaction -> mark agreed + pending (idempotent)
|
||||
newly_pending = False
|
||||
if member.id not in dm.get('agreed_nickname'):
|
||||
dm.add('agreed_nickname', int(member.id))
|
||||
dm.remove('nick_verified', lambda x: x == member.id)
|
||||
if member.id not in dm.get('nick_claim_pending'):
|
||||
dm.add('nick_claim_pending', int(member.id))
|
||||
newly_pending = True
|
||||
|
||||
# Only open a review when we just transitioned to pending
|
||||
if newly_pending:
|
||||
nn = self.bot.get_cog('NickNudgeCog')
|
||||
if nn and hasattr(nn, 'start_nick_review'):
|
||||
try:
|
||||
await nn.start_nick_review(guild, member, source="claim")
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
await self.maybe_apply_full_access(member)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_raw_reaction_remove(self, payload: discord.RawReactionActionEvent):
|
||||
if not payload.guild_id or not is_accept(payload.emoji):
|
||||
return
|
||||
guild = self.bot.get_guild(payload.guild_id)
|
||||
member = await self._get_member(guild, payload.user_id)
|
||||
if not member or member.bot:
|
||||
return
|
||||
|
||||
dm = self.bot.data_manager
|
||||
try:
|
||||
if payload.message_id == self.rules_msg_id:
|
||||
dm.remove('agreed_rules', lambda x: x == member.id)
|
||||
role = guild.get_role(self.rules_role)
|
||||
if role:
|
||||
await member.remove_roles(role, reason="Rules un-ticked")
|
||||
|
||||
elif payload.message_id == self.engage_msg_id:
|
||||
dm.remove('agreed_engagement', lambda x: x == member.id)
|
||||
role = guild.get_role(self.engage_role)
|
||||
if role:
|
||||
await member.remove_roles(role, reason="Engagement un-ticked")
|
||||
|
||||
elif payload.message_id == self.nick_msg_id:
|
||||
# Clear only if the user has NO accept reactions left on the message
|
||||
still_has_accept = await self._user_has_any_accept(
|
||||
guild, payload.channel_id, payload.message_id, member.id
|
||||
)
|
||||
if not still_has_accept:
|
||||
dm.remove('agreed_nickname', lambda x: x == member.id)
|
||||
dm.remove('nick_claim_pending', lambda x: x == member.id)
|
||||
dm.remove('nick_verified', lambda x: x == member.id)
|
||||
else:
|
||||
return
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
await self.maybe_apply_full_access(member)
|
||||
|
||||
async def setup(bot):
|
||||
await bot.add_cog(ReactionRoleCog(bot))
|
Loading…
Reference in New Issue
Block a user