mirror of
https://github.com/nexy7574/LCC-bot.git
synced 2024-09-19 10:03:40 +01:00
Add student ID moderation
This commit is contained in:
parent
1aa2f4c510
commit
89daf7c762
6 changed files with 125 additions and 5 deletions
|
@ -4,7 +4,7 @@
|
|||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.10 (the-hi5-group)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
63
cogs/mod.py
Normal file
63
cogs/mod.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from utils import Student, get_or_none, BannedStudentID
|
||||
import orm
|
||||
|
||||
|
||||
class Mod(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.user_command(name="Ban Account's B Number")
|
||||
@discord.default_permissions(ban_members=True)
|
||||
async def ban_student_id(self, ctx: discord.ApplicationContext, member: discord.Member):
|
||||
"""Bans a student ID from registering. Also bans an account associated with it."""
|
||||
await ctx.defer(ephemeral=True)
|
||||
student_id = await get_or_none(Student, user_id=member.id)
|
||||
if student_id is None:
|
||||
return await ctx.respond("\N{cross mark} Unknown B number (is the user verified yet?)", ephemeral=True)
|
||||
|
||||
ban = await get_or_none(BannedStudentID, student_id=student_id.id)
|
||||
if ban is None:
|
||||
ban = await BannedStudentID.objects.create(
|
||||
student_id=student_id.id,
|
||||
associated_account=member.id,
|
||||
)
|
||||
|
||||
await member.ban(reason=f"Banned ID {ban.student_id} by {ctx.author}")
|
||||
return await ctx.respond(
|
||||
f"\N{white heavy check mark} Banned {ban.student_id} (and {member.mention})",
|
||||
ephemeral=True
|
||||
)
|
||||
|
||||
@commands.slash_command(name="unban-student-number")
|
||||
@discord.default_permissions(ban_members=True)
|
||||
async def unban_student_id(self, ctx: discord.ApplicationContext, student_id: str):
|
||||
"""Unbans a student ID and the account associated with it."""
|
||||
student_id = student_id.upper()
|
||||
ban = await get_or_none(BannedStudentID, student_id=student_id)
|
||||
if not ban:
|
||||
return await ctx.respond("\N{cross mark} That student ID isn't banned.")
|
||||
await ctx.defer()
|
||||
user_id = ban.associated_account
|
||||
await ban.delete()
|
||||
if not user_id:
|
||||
return await ctx.respond(f"\N{white heavy checkmark} Unbanned {student_id}. No user to unban.")
|
||||
else:
|
||||
try:
|
||||
await ctx.guild.unban(
|
||||
discord.Object(user_id),
|
||||
reason=f"Unbanned by {ctx.author}"
|
||||
)
|
||||
except discord.HTTPException as e:
|
||||
return await ctx.respond(
|
||||
f"\N{white heavy check mark} Unbanned {student_id}. Failed to unban {user_id} - HTTP {e.status}."
|
||||
)
|
||||
else:
|
||||
return await ctx.respond(
|
||||
f"\N{white heavy check mark} Unbanned {student_id}. Unbanned {user_id}."
|
||||
)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Mod(bot))
|
|
@ -2,7 +2,7 @@ import discord
|
|||
import orm
|
||||
import re
|
||||
from discord.ext import commands
|
||||
from utils import send_verification_code, VerifyCode, Student, console
|
||||
from utils import send_verification_code, VerifyCode, Student, console, get_or_none, BannedStudentID
|
||||
import config
|
||||
|
||||
|
||||
|
@ -45,7 +45,17 @@ class VerifyCog(commands.Cog):
|
|||
return
|
||||
|
||||
if not re.match(r"^B\d{6}$", st):
|
||||
return await interaction.response.send_message("\N{cross mark} Invalid student ID.")
|
||||
return await interaction.response.send_message(
|
||||
"\N{cross mark} Invalid student ID.",
|
||||
delete_after=60
|
||||
)
|
||||
|
||||
ex = await get_or_none(Student, id=st)
|
||||
if ex:
|
||||
return await interaction.response.send_message(
|
||||
"\N{cross mark} Student ID is already associated.",
|
||||
delete_after=60
|
||||
)
|
||||
|
||||
_code = await send_verification_code(ctx.author, st)
|
||||
console.log(f"Sending verification email to {ctx.author} ({ctx.author.id}/{st})...")
|
||||
|
@ -74,6 +84,12 @@ class VerifyCog(commands.Cog):
|
|||
"\N{cross mark} Invalid or unknown verification code. Try again!", ephemeral=True
|
||||
)
|
||||
else:
|
||||
ban = await get_or_none(BannedStudentID, student_id=existing.student_id)
|
||||
if ban is not None:
|
||||
return await ctx.author.ban(
|
||||
reason=f"Attempted to verify with banned student ID {ban.student_id}"
|
||||
f" (originally associated with account {ban.associated_account})"
|
||||
)
|
||||
await Student.objects.create(id=existing.student_id, user_id=ctx.author.id)
|
||||
await existing.delete()
|
||||
role = discord.utils.find(lambda r: r.name.lower() == "verified", guild.roles)
|
||||
|
|
1
main.py
1
main.py
|
@ -9,6 +9,7 @@ bot = commands.Bot(
|
|||
)
|
||||
bot.load_extension("jishaku")
|
||||
bot.load_extension("cogs.verify")
|
||||
bot.load_extension("cogs.mod")
|
||||
bot.loop.run_until_complete(registry.create_all())
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
py-cord==2.1.3
|
||||
py-cord==2.2.0
|
||||
aiosmtplib==1.1.7
|
||||
orm[sqlite]==0.3.1
|
||||
httpx==0.23.0
|
||||
|
|
42
utils/db.py
42
utils/db.py
|
@ -1,5 +1,6 @@
|
|||
import datetime
|
||||
import uuid
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional, TypeVar
|
||||
|
||||
import orm
|
||||
from databases import Database
|
||||
|
@ -9,9 +10,32 @@ from pathlib import Path
|
|||
os.chdir(Path(__file__).parent.parent)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"registry",
|
||||
"get_or_none"
|
||||
]
|
||||
_models = [
|
||||
"VerifyCode",
|
||||
"Student",
|
||||
"BannedStudentID"
|
||||
]
|
||||
__all__ += _models
|
||||
|
||||
T = TypeVar('T')
|
||||
T_co = TypeVar("T_co", covariant=True)
|
||||
|
||||
|
||||
registry = orm.ModelRegistry(Database("sqlite:///main.db"))
|
||||
|
||||
|
||||
async def get_or_none(model: T, **kw) -> Optional[T_co]:
|
||||
"""Returns none or the required thing."""
|
||||
try:
|
||||
return await model.objects.get(**kw)
|
||||
except orm.NoMatch:
|
||||
return
|
||||
|
||||
|
||||
class VerifyCode(orm.Model):
|
||||
registry = registry
|
||||
tablename = "codes"
|
||||
|
@ -40,3 +64,19 @@ class Student(orm.Model):
|
|||
entry_id: uuid.UUID
|
||||
id: str
|
||||
user_id: int
|
||||
|
||||
|
||||
class BannedStudentID(orm.Model):
|
||||
registry = registry
|
||||
tablename = "banned"
|
||||
fields = {
|
||||
"entry_id": orm.UUID(primary_key=True, default=uuid.uuid4),
|
||||
"student_id": orm.String(min_length=7, max_length=7, unique=True),
|
||||
"associated_account": orm.BigInteger(default=None),
|
||||
"banned_at_timestamp": orm.Float(default=lambda: datetime.datetime.utcnow().timestamp())
|
||||
}
|
||||
if TYPE_CHECKING:
|
||||
entry_id: uuid.UUID
|
||||
student_id: str
|
||||
associated_account: Optional[int]
|
||||
banned_at_timestamp: float
|
||||
|
|
Loading…
Reference in a new issue