mirror of
https://github.com/nexy7574/LCC-bot.git
synced 2024-09-19 18:16:34 +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$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="jdk" jdkName="Python 3.10 (the-hi5-group)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</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 orm
|
||||||
import re
|
import re
|
||||||
from discord.ext import commands
|
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
|
import config
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,7 +45,17 @@ class VerifyCog(commands.Cog):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not re.match(r"^B\d{6}$", st):
|
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)
|
_code = await send_verification_code(ctx.author, st)
|
||||||
console.log(f"Sending verification email to {ctx.author} ({ctx.author.id}/{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
|
"\N{cross mark} Invalid or unknown verification code. Try again!", ephemeral=True
|
||||||
)
|
)
|
||||||
else:
|
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 Student.objects.create(id=existing.student_id, user_id=ctx.author.id)
|
||||||
await existing.delete()
|
await existing.delete()
|
||||||
role = discord.utils.find(lambda r: r.name.lower() == "verified", guild.roles)
|
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("jishaku")
|
||||||
bot.load_extension("cogs.verify")
|
bot.load_extension("cogs.verify")
|
||||||
|
bot.load_extension("cogs.mod")
|
||||||
bot.loop.run_until_complete(registry.create_all())
|
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
|
aiosmtplib==1.1.7
|
||||||
orm[sqlite]==0.3.1
|
orm[sqlite]==0.3.1
|
||||||
httpx==0.23.0
|
httpx==0.23.0
|
||||||
|
|
42
utils/db.py
42
utils/db.py
|
@ -1,5 +1,6 @@
|
||||||
|
import datetime
|
||||||
import uuid
|
import uuid
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING, Optional, TypeVar
|
||||||
|
|
||||||
import orm
|
import orm
|
||||||
from databases import Database
|
from databases import Database
|
||||||
|
@ -9,9 +10,32 @@ from pathlib import Path
|
||||||
os.chdir(Path(__file__).parent.parent)
|
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"))
|
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):
|
class VerifyCode(orm.Model):
|
||||||
registry = registry
|
registry = registry
|
||||||
tablename = "codes"
|
tablename = "codes"
|
||||||
|
@ -40,3 +64,19 @@ class Student(orm.Model):
|
||||||
entry_id: uuid.UUID
|
entry_id: uuid.UUID
|
||||||
id: str
|
id: str
|
||||||
user_id: int
|
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