2022-10-04 16:20:01 +01:00
|
|
|
import datetime
|
2023-03-20 16:59:46 +00:00
|
|
|
import sys
|
2023-05-16 16:50:14 +01:00
|
|
|
import discord
|
2022-09-13 20:50:02 +01:00
|
|
|
import uuid
|
2022-10-04 16:20:01 +01:00
|
|
|
from typing import TYPE_CHECKING, Optional, TypeVar
|
2022-10-09 19:27:02 +01:00
|
|
|
from enum import IntEnum, auto
|
2022-09-13 20:50:02 +01:00
|
|
|
|
|
|
|
import orm
|
|
|
|
from databases import Database
|
2022-09-13 21:27:14 +01:00
|
|
|
import os
|
|
|
|
from pathlib import Path
|
|
|
|
|
2022-10-09 19:27:02 +01:00
|
|
|
|
|
|
|
class Tutors(IntEnum):
|
|
|
|
JAY = auto()
|
|
|
|
ZACH = auto()
|
|
|
|
IAN = auto()
|
|
|
|
REBECCA = auto()
|
|
|
|
LUPUPA = auto()
|
|
|
|
OTHER = -1 # not auto() because if we add more it could mess things up.
|
|
|
|
|
|
|
|
|
2022-09-13 21:27:25 +01:00
|
|
|
os.chdir(Path(__file__).parent.parent)
|
2022-09-13 20:50:02 +01:00
|
|
|
|
|
|
|
|
2023-01-18 20:54:48 +00:00
|
|
|
__all__ = [
|
|
|
|
"registry",
|
|
|
|
"get_or_none",
|
|
|
|
"VerifyCode",
|
|
|
|
"Student",
|
|
|
|
"BannedStudentID",
|
|
|
|
"Assignments",
|
|
|
|
"Tutors",
|
|
|
|
"UptimeEntry",
|
2023-02-09 13:44:49 +00:00
|
|
|
"JimmyBans",
|
2023-01-18 20:54:48 +00:00
|
|
|
]
|
2022-10-30 16:31:38 +00:00
|
|
|
|
|
|
|
T = TypeVar("T")
|
2022-10-04 16:20:01 +01:00
|
|
|
T_co = TypeVar("T_co", covariant=True)
|
|
|
|
|
2023-03-20 15:41:20 +00:00
|
|
|
if Path("/data").exists():
|
|
|
|
_pth = "/data/main.db"
|
2023-03-20 18:04:38 +00:00
|
|
|
try:
|
|
|
|
Path(_pth).touch()
|
|
|
|
except PermissionError as e:
|
|
|
|
print("Failed to create database:", e, file=sys.stderr)
|
|
|
|
sys.exit(1)
|
2023-03-20 18:01:44 +00:00
|
|
|
else:
|
2023-03-20 18:04:38 +00:00
|
|
|
_pth = "/main.db"
|
2023-03-20 16:59:46 +00:00
|
|
|
|
2023-03-20 18:04:38 +00:00
|
|
|
registry = orm.ModelRegistry(Database("sqlite://" + _pth))
|
2022-09-13 20:50:02 +01:00
|
|
|
|
|
|
|
|
2022-10-04 16:20:01 +01:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2022-09-13 20:50:02 +01:00
|
|
|
class VerifyCode(orm.Model):
|
|
|
|
registry = registry
|
|
|
|
tablename = "codes"
|
|
|
|
fields = {
|
|
|
|
"id": orm.Integer(primary_key=True),
|
|
|
|
"code": orm.String(min_length=8, max_length=64, unique=True),
|
|
|
|
"bind": orm.BigInteger(),
|
2022-09-13 21:27:14 +01:00
|
|
|
"student_id": orm.String(min_length=7, max_length=7),
|
2022-11-23 14:34:58 +00:00
|
|
|
"name": orm.String(min_length=2, max_length=32),
|
2022-09-13 20:50:02 +01:00
|
|
|
}
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
id: int
|
|
|
|
code: str
|
|
|
|
bind: int
|
|
|
|
student_id: str
|
2022-11-23 14:34:58 +00:00
|
|
|
name: str
|
2022-09-13 20:50:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
class Student(orm.Model):
|
|
|
|
registry = registry
|
|
|
|
tablename = "students"
|
|
|
|
fields = {
|
|
|
|
"entry_id": orm.UUID(primary_key=True, default=uuid.uuid4),
|
|
|
|
"id": orm.String(min_length=7, max_length=7, unique=True),
|
|
|
|
"user_id": orm.BigInteger(unique=True),
|
2022-11-23 14:34:58 +00:00
|
|
|
"name": orm.String(min_length=2, max_length=32),
|
2023-02-22 01:33:30 +00:00
|
|
|
"access_token": orm.String(min_length=6, max_length=128, default=None, allow_null=True),
|
|
|
|
"ip_info": orm.JSON(default=None, allow_null=True),
|
|
|
|
"access_token_hash": orm.String(min_length=128, max_length=128, default=None, allow_null=True),
|
2022-09-13 20:50:02 +01:00
|
|
|
}
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
entry_id: uuid.UUID
|
|
|
|
id: str
|
|
|
|
user_id: int
|
2022-11-23 14:34:58 +00:00
|
|
|
name: str
|
2023-02-22 15:17:53 +00:00
|
|
|
access_token: str | None
|
|
|
|
ip_info: dict | None
|
|
|
|
access_token_hash: str | None
|
2022-10-04 16:20:01 +01:00
|
|
|
|
|
|
|
|
|
|
|
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),
|
2022-10-30 16:31:38 +00:00
|
|
|
"banned_at_timestamp": orm.Float(default=lambda: datetime.datetime.utcnow().timestamp()),
|
2022-10-04 16:20:01 +01:00
|
|
|
}
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
entry_id: uuid.UUID
|
|
|
|
student_id: str
|
|
|
|
associated_account: Optional[int]
|
|
|
|
banned_at_timestamp: float
|
2022-10-09 19:27:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
class Assignments(orm.Model):
|
|
|
|
registry = registry
|
|
|
|
fields = {
|
|
|
|
"entry_id": orm.Integer(primary_key=True, default=None),
|
|
|
|
"created_by": orm.ForeignKey(Student, allow_null=True),
|
|
|
|
"title": orm.String(min_length=2, max_length=2000),
|
|
|
|
"classroom": orm.URL(allow_null=True, default=None, max_length=4096),
|
|
|
|
"shared_doc": orm.URL(allow_null=True, default=None, max_length=4096),
|
|
|
|
"created_at": orm.Float(default=lambda: datetime.datetime.now().timestamp()),
|
|
|
|
"due_by": orm.Float(),
|
|
|
|
"tutor": orm.Enum(Tutors),
|
|
|
|
"reminders": orm.JSON(default=[]),
|
|
|
|
"finished": orm.Boolean(default=False),
|
2022-10-30 16:31:38 +00:00
|
|
|
"submitted": orm.Boolean(default=False),
|
2022-11-07 11:20:48 +00:00
|
|
|
"assignees": orm.JSON(default=[]),
|
2022-11-30 20:55:59 +00:00
|
|
|
# "description": orm.Text(min_length=2, max_length=2000, allow_null=True, default=None),
|
2022-10-09 19:27:02 +01:00
|
|
|
}
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
entry_id: int
|
|
|
|
created_by: Student
|
|
|
|
title: str
|
|
|
|
classroom: Optional[str]
|
|
|
|
shared_doc: Optional[str]
|
|
|
|
created_at: float
|
|
|
|
due_by: float
|
|
|
|
tutor: Tutors
|
|
|
|
reminders: list[str]
|
|
|
|
finished: bool
|
|
|
|
submitted: bool
|
2022-11-07 11:20:48 +00:00
|
|
|
assignees: list[int]
|
2022-11-30 20:55:59 +00:00
|
|
|
# description: Optional[str]
|
2022-11-30 21:01:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
class StarBoardMessage(orm.Model):
|
|
|
|
tablename = "starboard"
|
|
|
|
registry = registry
|
|
|
|
fields = {
|
|
|
|
"entry_id": orm.UUID(primary_key=True, default=uuid.uuid4),
|
|
|
|
"id": orm.BigInteger(unique=True),
|
|
|
|
"channel": orm.BigInteger(),
|
|
|
|
"starboard_message": orm.BigInteger(default=None, allow_null=True),
|
|
|
|
}
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
entry_id: uuid.UUID
|
|
|
|
id: int
|
|
|
|
channel: int
|
|
|
|
starboard_message: int | None
|
2023-01-18 15:28:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
class UptimeEntry(orm.Model):
|
|
|
|
tablename = "uptime"
|
|
|
|
registry = registry
|
|
|
|
fields = {
|
|
|
|
"entry_id": orm.UUID(primary_key=True, default=uuid.uuid4),
|
|
|
|
"target_id": orm.String(min_length=2, max_length=128),
|
|
|
|
"target": orm.String(min_length=2, max_length=128),
|
|
|
|
"is_up": orm.Boolean(),
|
|
|
|
"timestamp": orm.Float(default=lambda: datetime.datetime.utcnow().timestamp()),
|
|
|
|
"response_time": orm.Integer(allow_null=True),
|
|
|
|
"notes": orm.Text(allow_null=True, default=None),
|
|
|
|
}
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
entry_id: uuid.UUID
|
|
|
|
target_id: str
|
|
|
|
target: str
|
|
|
|
is_up: bool
|
|
|
|
timestamp: float
|
|
|
|
response_time: int | None
|
|
|
|
notes: str | None
|
2023-01-19 14:04:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
class JimmyBans(orm.Model):
|
|
|
|
tablename = "jimmy_bans"
|
|
|
|
registry = registry
|
|
|
|
fields = {
|
|
|
|
"entry_id": orm.UUID(primary_key=True, default=uuid.uuid4),
|
|
|
|
"user_id": orm.BigInteger(),
|
|
|
|
"reason": orm.Text(allow_null=True, default=None),
|
|
|
|
"timestamp": orm.Float(default=lambda: datetime.datetime.utcnow().timestamp()),
|
|
|
|
"until": orm.Float(),
|
|
|
|
}
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
entry_id: uuid.UUID
|
|
|
|
user_id: int
|
|
|
|
reason: str | None
|
|
|
|
timestamp: float
|
|
|
|
until: float | None
|
2023-05-16 15:12:59 +01:00
|
|
|
|
|
|
|
|
2023-05-16 15:14:17 +01:00
|
|
|
class AccessTokens(orm.Model):
|
2023-05-16 15:12:59 +01:00
|
|
|
tablename = "access_tokens"
|
|
|
|
registry = registry
|
|
|
|
fields = {
|
|
|
|
"entry_id": orm.UUID(primary_key=True, default=uuid.uuid4),
|
|
|
|
"user_id": orm.BigInteger(unique=True),
|
|
|
|
"access_token": orm.String(min_length=6, max_length=128),
|
2023-05-16 16:50:14 +01:00
|
|
|
"expires": orm.Float(default=lambad: discord.utils.utcnow().timestamp() + 604800),
|
2023-05-16 15:12:59 +01:00
|
|
|
"ip_info": orm.JSON(default=None, allow_null=True),
|
|
|
|
}
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
entry_id: uuid.UUID
|
|
|
|
user_id: int
|
|
|
|
access_token: str
|
|
|
|
ip_info: dict | None
|