Skip to content

Commit

Permalink
Merge pull request #387 from PyBotDevs/add-server-user-verification-s…
Browse files Browse the repository at this point in the history
…ystem

Add server user verification system to let server owners require all new members to verify before using the server
notsniped authored May 5, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 1f172b1 + 1c8c994 commit fee1936
Showing 4 changed files with 185 additions and 2 deletions.
98 changes: 98 additions & 0 deletions cogs/serverconfig.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Imports
import discord
import random
import json
from discord import option, ApplicationContext
from discord.commands import SlashCommandGroup
from discord.ext import commands
@@ -12,6 +14,10 @@
class ServerConfig(commands.Cog):
def __init__(self, bot):
self.bot = bot

# Load Verification Database
with open("database/serververification.json", 'r', encoding="utf-8") as f:
self.verification_db: dict = json.load(f)

serverconfig_cmds = SlashCommandGroup(name="serverconfig", description="Commands related to server customization and configuration.")

@@ -65,6 +71,98 @@ async def autorole(self, ctx: ApplicationContext, channel: discord.TextChannel =
)
await ctx.respond(embed=localembed)

# Server Member Verification System
@serverconfig_cmds.command(
name="enable_verification",
description="Enable new member verification for this server."
)
@option(name="verified_role", description="The role to provide to all verified members.", type=discord.Role)
async def enable_verification(self, ctx: ApplicationContext, verified_role: discord.Role):
"""Enable new user verification for this server."""
if not ctx.author.guild_permissions.administrator:
return await ctx.respond("You can't use this command! You need the `Administrator` permission to run this.", ephemeral=True)
serverconf.set_verification_role(ctx.guild.id, verified_role.id)
localembed = discord.Embed(
title=f":white_check_mark: Server Member Verification successfully enabled for **{ctx.guild.name}**!",
description=f"From now onwards, all new members will have to verify with `/verify` command, and will receive the {verified_role.mention} once verified.",
color=discord.Color.green()
)
await ctx.respond(embed=localembed)

@serverconfig_cmds.command(
name="disable_verification",
description="Disable new member verification for this server."
)
async def disable_verification(self, ctx: ApplicationContext):
"""Disable new member verification for this server."""
if not ctx.author.guild_permissions.administrator:
return await ctx.respond("You can't use this command! You need the `Administrator` permission to run this.", ephemeral=True)
serverconf.set_verification_role(ctx.guild.id, None)
localembed = discord.Embed(
title=f":white_check_mark: Server Member Verification successfully disabled for **{ctx.guild.name}**",
description=f"New members now won't have to verify in the server.",
color=discord.Color.green()
)
await ctx.respond(embed=localembed)

@commands.slash_command(
name="start_verification",
description="Start your verification process in this server."
)
@commands.guild_only()
async def start_verification(self, ctx: ApplicationContext):
"""Start your verification process in this server."""
verification_role = serverconf.fetch_verification_role(ctx.guild.id)
if verification_role is None:
return await ctx.respond(":warning: Verification system is disabled for this server!", ephemeral=True)
if ctx.author.get_role(verification_role) is not None:
return await ctx.respond(":warning: You are already verified in this server!", ephemeral=True)

# Construct verification data
verify_code = random.randint(100000, 999999)
if str(ctx.author.id) not in self.verification_db:
self.verification_db[str(ctx.author.id)] = {}

for code in self.verification_db[str(ctx.author.id)]:
if self.verification_db[str(ctx.author.id)][str(code)]["guild_id"] == ctx.guild.id:
return await ctx.respond("Your verification process is already ongoing in this server!", ephemeral=True)

self.verification_db[str(ctx.author.id)][str(verify_code)] = {"guild_id": ctx.guild.id}
with open("database/serververification.json", 'w+', encoding="utf-8") as f:
json.dump(self.verification_db, f, indent=4)

localembed = discord.Embed(
title=f"Verification for {ctx.author.name} in {ctx.guild.name} has started",
description=f"Your one-time verification code is `{verify_code}`. **DO NOT share this code with anyone!**\n\nGo to isobot's DMs, and run the `/verify` command entering your verification code.",
color=discord.Color.orange()
)
await ctx.respond(embed=localembed, ephemeral=True)

@commands.slash_command(
name="verify",
description="Enter your one-time verification code to verify membership in a server. (DM-ONLY)"
)
@commands.dm_only()
@option(name="verification_code", description="Your one-time verification code. (6-digit number)", type=int)
async def verify(self, ctx: ApplicationContext, verification_code: int):
"""Enter your one-time verification code to verify membership in a server."""
if str(ctx.author.id) not in self.verification_db.keys():
return await ctx.respond("You are not pending verification in any servers.", ephemeral=True)
if str(verification_code) not in self.verification_db[str(ctx.author.id)].keys():
return await ctx.respond(":x: This verification code is invalid. Please double-check and try a different code!", ephemeral=True)

verification_role_id = serverconf.fetch_verification_role(self.verification_db[str(ctx.author.id)][str(verification_code)]["guild_id"])
vcode_guild: discord.Guild = self.bot.get_guild(self.verification_db[str(ctx.author.id)][str(verification_code)]["guild_id"])
verification_role = discord.Guild.get_role(vcode_guild, verification_role_id)
server_context_user: discord.Member = vcode_guild.get_member(ctx.author.id)
await server_context_user.add_roles(verification_role, reason="Member has been successfully verified in server.")

del self.verification_db[str(ctx.author.id)][str(verification_code)]
with open("database/serververification.json", 'w+', encoding="utf-8") as f:
json.dump(self.verification_db, f, indent=4)

return await ctx.respond(f"You have been successfully verified in **{vcode_guild.name}**!")

def setup(bot):
bot.add_cog(ServerConfig(bot))

70 changes: 70 additions & 0 deletions config/commands.json
Original file line number Diff line number Diff line change
@@ -848,5 +848,75 @@
"usable_by": "everyone",
"disabled": false,
"bugged": false
},
"howgay": {
"name": "Gay Rating",
"description": "See the gay percentage of a person!",
"type": "fun",
"cooldown": null,
"args": null,
"usable_by": "everyone",
"disabled": false,
"bugged": false
},
"serverconfig autorole": {
"name": "ServerConfig Autorole",
"description": "Set a role to provide to all newly-joined members of the server.",
"type": "serverconfig",
"cooldown": null,
"args": ["role (leave blank to disable)"],
"usable_by": "moderators with `manage guild` permissions",
"disabled": false,
"bugged": false
},
"serverconfig levelup_override_channel": {
"name": "ServerConfig Level-up Override Channel",
"description": "Set a server channel to send level-up messages to, instead of DMs.",
"type": "serverconfig",
"cooldown": null,
"args": ["channel (leave blank to disable)"],
"usable_by": "moderators with `manage guild` permissions",
"disabled": false,
"bugged": false
},
"serverconfig enable_verification": {
"name": "ServerConfig Enable Verification",
"description": "Enable new member verification for this server.",
"type": "serverconfig",
"cooldown": null,
"args": ["verified_role"],
"usable_by": "server admins",
"disabled": false,
"bugged": false
},
"serverconfig disable_verification": {
"name": "ServerConfig Disable Verification",
"description": "Disable new member verification for this server.",
"type": "serverconfig",
"cooldown": null,
"args": null,
"usable_by": "server admins",
"disabled": false,
"bugged": false
},
"start_verification": {
"name": "Start Verification",
"description": "Start your verification process in the server. (SERVER-ONLY)",
"type": "general utilities",
"cooldown": null,
"args": null,
"usable_by": "everyone",
"disabled": false,
"bugged": false
},
"verify": {
"name": "Verify",
"description": "Enter your one-time verification code to verify membership in a server. (DM-ONLY)",
"type": "general utilities",
"cooldown": null,
"args": null,
"usable_by": "everyone (in DMs)",
"disabled": false,
"bugged": false
}
}
13 changes: 12 additions & 1 deletion framework/isobot/db/serverconfig.py
Original file line number Diff line number Diff line change
@@ -33,7 +33,8 @@ def generate(self, server_id: int) -> int:
"channel": None,
"message": None
},
"level_up_override_channel": None
"level_up_override_channel": None,
"verification_role": None
}
self.save(serverconf)
return 0
@@ -58,6 +59,10 @@ def fetch_goodbye_message(self, server_id: int) -> dict:
def fetch_levelup_override_channel(self, server_id: int) -> str:
"""Fetches the level-up override channel for the specified guild. Returns `None` if not set."""
return self.fetch_raw(server_id)["level_up_override_channel"]

def fetch_verification_role(self, server_id: int) -> str:
"""Fetches the verified member role for the specified guild. Returns `None` if server verification system is disabled."""
return self.fetch_raw(server_id)["verification_role"]

def set_autorole(self, server_id: int, role_id: int) -> int:
"""Sets a role id to use as autorole for the specified guild. Returns `0` if successful."""
@@ -84,3 +89,9 @@ def set_levelup_override_channel(self, server_id: int, channel_id: int) -> int:
serverconf = self.load()
serverconf[str(server_id)]["level_up_override_channel"] = channel_id
self.save(serverconf)

def set_verification_role(self, server_id: int, role_id: int) -> int:
"""Sets a verified member role id for the specified guild for the specified guild, and enables server member verification. Returns `0` if successful."""
serverconf = self.load()
serverconf[str(server_id)]["verification_role"] = role_id
self.save(serverconf)
6 changes: 5 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@ def initial_setup():
"items",
"levels",
"serverconfig",
"serververification",
"warnings",
"presence",
"user_data",
@@ -285,6 +286,7 @@ async def on_application_command_error(ctx: ApplicationContext, error: discord.D
elif isinstance(error, commands.BotMissingPermissions): await ctx.respond(":x: I don\'t have the required permissions to use this.\nIf you think this is a mistake, please go to server settings and fix isobot's role permissions.")
elif isinstance(error, commands.BadBoolArgument): await ctx.respond(":x: Invalid true/false argument.", ephemeral=True)
elif isinstance(error, commands.NoPrivateMessage): await ctx.respond(":x: You can only use this command in a server!", ephemeral=True)
elif isinstance(error, commands.PrivateMessageOnly): await ctx.respond(":x: You can only use this command in isobot's DMs!", ephemeral=True)
else:
logger.error(f"Command failure: An uncaught error occured while running the command.\n >>> {error}", module="main/Client")
await ctx.respond(f"An uncaught error occured while running the command. (don't worry, developers will fix this soon)\n```\n{error}\n```")
@@ -320,6 +322,7 @@ async def help_list(ctx: ApplicationContext, search: str = None):
reddit_commands = str()
afk_commands = str()
automod_moderation_commands = str()
serverconfig_commands = str()
maths_commands = str()
other_commands = str()
for _command in commandsdb:
@@ -332,10 +335,11 @@ async def help_list(ctx: ApplicationContext, search: str = None):
elif command_type == "reddit media": reddit_commands += f"`/{_command}` "
elif command_type == "AFK system": afk_commands += f"`/{_command}` "
elif command_type == "automod" or command_type == "moderation": automod_moderation_commands += f"`/{_command}` "
elif command_type == "serverconfig": serverconfig_commands += f"`/{_command}` "
elif command_type == "maths": maths_commands += f"`/{_command}` "
else: other_commands += f"`/{_command}` "

commands_list = f"**:money_with_wings: Economy System:**\n{economy_commands}\n\n**:arrow_up: Levelling System:**\n{levelling_commands}\n\n**:toolbox: Utilities:**\n{utility_commands}\n\n**:joy: Fun Commands:**\n{fun_commands}\n\n**:crescent_moon: AFK System**\n{afk_commands}\n\n**:tools: Moderation and Automod:**\n{automod_moderation_commands}\n\n**:1234: Maths Commands:**\n{maths_commands}\n\n**:frame_photo: Reddit Media Commands:**\n{reddit_commands}\n\n**:sparkles: Miscellaneous:**\n{other_commands}"
commands_list = f"**:money_with_wings: Economy System:**\n{economy_commands}\n\n**:arrow_up: Levelling System:**\n{levelling_commands}\n\n**:toolbox: Utilities:**\n{utility_commands}\n\n**:joy: Fun Commands:**\n{fun_commands}\n\n**:crescent_moon: AFK System**\n{afk_commands}\n\n**:tools: Moderation and Automod:**\n{automod_moderation_commands}\n\n**:gear: Server Configuration:**\n{serverconfig_commands}\n\n**:1234: Maths Commands:**\n{maths_commands}\n\n**:frame_photo: Reddit Media Commands:**\n{reddit_commands}\n\n**:sparkles: Miscellaneous:**\n{other_commands}"
localembed = discord.Embed(title="Isobot Command Help", description=commands_list, color=color)
localembed.set_footer(text="Run \"/help info\" to get more information on a command.")
await ctx.respond(embed=localembed)

0 comments on commit fee1936

Please sign in to comment.