Migrate to beanie
This commit is contained in:
parent
7bb9b25f63
commit
eb36cf7413
11 changed files with 970 additions and 737 deletions
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"python.formatting.provider": "black"
|
||||||
|
}
|
|
@ -1,10 +1,14 @@
|
||||||
"""Load global config."""
|
"""Load global config."""
|
||||||
|
import ast
|
||||||
|
from os import environ
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Union
|
from typing import Any, Dict, List, Optional, Type
|
||||||
|
|
||||||
from yaml import load
|
import orjson as json
|
||||||
|
import yaml
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from jarvis_core.util import Singleton
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from yaml import CLoader as Loader
|
from yaml import CLoader as Loader
|
||||||
|
@ -12,15 +16,88 @@ except ImportError:
|
||||||
from yaml import Loader
|
from yaml import Loader
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_PATH = Path("config.yaml")
|
DEFAULT_YAML = Path("config.yaml")
|
||||||
|
DEFAULT_JSON = Path("config.json")
|
||||||
|
|
||||||
|
|
||||||
class Config(Singleton):
|
class Config:
|
||||||
REQUIRED = []
|
REQUIRED: Dict[str, Type] = {}
|
||||||
OPTIONAL = {}
|
OPTIONAL: Dict[str, Dict[str, Any]] = {}
|
||||||
|
|
||||||
|
def __new__(cls, *args: list, **kwargs: dict):
|
||||||
|
"""Create a new Config object."""
|
||||||
|
|
||||||
|
for arg, flags in cls.OPTIONAL.items():
|
||||||
|
kwargs[arg] = kwargs.get(arg, flags["default"])
|
||||||
|
|
||||||
|
inst = super().__new__(cls, *args, **kwargs)
|
||||||
|
inst._validate()
|
||||||
|
|
||||||
|
return inst
|
||||||
|
|
||||||
|
def _validate(self) -> None:
|
||||||
|
for key in self.REQUIRED.keys():
|
||||||
|
if getattr(self, key, None) is None:
|
||||||
|
raise ValueError(f"Missing required key: {key}")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_yaml(cls, filepath: Union[Path, str] = DEFAULT_PATH) -> "Config":
|
def from_env(cls) -> "Config":
|
||||||
|
"""Load the .env config file."""
|
||||||
|
load_dotenv()
|
||||||
|
data = {}
|
||||||
|
for k, t in cls.REQUIRED.items():
|
||||||
|
value = environ.get(k.upper(), None)
|
||||||
|
if value and not isinstance(value, t):
|
||||||
|
if t is dict:
|
||||||
|
try:
|
||||||
|
value = ast.literal_eval(value)
|
||||||
|
except Exception:
|
||||||
|
raise ValueError(f"{k} is a dict but is not formatted properly")
|
||||||
|
elif t is bool:
|
||||||
|
value = value.lower() in ["true", "yes", "t", "y", "1"]
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
value = t(value)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
data[k] = value
|
||||||
|
for k, flags in cls.OPTIONAL.items():
|
||||||
|
t = flags["type"]
|
||||||
|
value = environ.get(k.upper(), flags["default"])
|
||||||
|
if value and not isinstance(value, t):
|
||||||
|
if t is dict:
|
||||||
|
try:
|
||||||
|
value = ast.literal_eval(value)
|
||||||
|
except Exception:
|
||||||
|
raise ValueError(f"{k} is a dict but is not formatted properly")
|
||||||
|
elif t is bool:
|
||||||
|
value = value.lower() in ["true", "yes", "t", "y", "1"]
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
value = t(value)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
data[k] = value
|
||||||
|
|
||||||
|
return cls(**data)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_json(cls, filepath: Path | str = DEFAULT_JSON) -> "Config":
|
||||||
|
"""Load the json config file."""
|
||||||
|
if inst := cls.__dict__.get("inst"):
|
||||||
|
return inst
|
||||||
|
|
||||||
|
if isinstance(filepath, str):
|
||||||
|
filepath = Path(filepath)
|
||||||
|
|
||||||
|
with filepath.open() as f:
|
||||||
|
raw = f.read()
|
||||||
|
|
||||||
|
j = json.loads(raw)
|
||||||
|
return cls(**j)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_yaml(cls, filepath: Path | str = DEFAULT_YAML) -> "Config":
|
||||||
"""Load the yaml config file."""
|
"""Load the yaml config file."""
|
||||||
if inst := cls.__dict__.get("inst"):
|
if inst := cls.__dict__.get("inst"):
|
||||||
return inst
|
return inst
|
||||||
|
@ -31,9 +108,33 @@ class Config(Singleton):
|
||||||
with filepath.open() as f:
|
with filepath.open() as f:
|
||||||
raw = f.read()
|
raw = f.read()
|
||||||
|
|
||||||
y = load(raw, Loader=Loader)
|
y = yaml.load(raw, Loader=Loader)
|
||||||
return cls(**y)
|
return cls(**y)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load(cls, method: Optional[str] = None) -> "Config":
|
||||||
|
"""
|
||||||
|
Load the config in a somewhat generic way.
|
||||||
|
|
||||||
|
Default load order is: yaml, json, env
|
||||||
|
|
||||||
|
Args:
|
||||||
|
method: Load method, one of: yaml, json, env
|
||||||
|
"""
|
||||||
|
methods = ["yaml", "json", "env"]
|
||||||
|
if method and method in methods:
|
||||||
|
methods.remove(method)
|
||||||
|
methods.insert(0, method)
|
||||||
|
for method in methods:
|
||||||
|
try:
|
||||||
|
m = cls.__dict__.get(f"from_{method}", None)
|
||||||
|
if m:
|
||||||
|
return m()
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
|
||||||
|
raise ValueError("Unable to load configuration, please create one of: config.yaml, config.json, .env")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reload(cls) -> bool:
|
def reload(cls) -> bool:
|
||||||
"""Reload the config."""
|
"""Reload the config."""
|
||||||
|
|
|
@ -1,20 +1,13 @@
|
||||||
"""JARVIS database models and utilities."""
|
"""JARVIS database models and utilities."""
|
||||||
from bson import ObjectId
|
|
||||||
from motor.motor_asyncio import AsyncIOMotorClient
|
from motor.motor_asyncio import AsyncIOMotorClient
|
||||||
from pytz import utc
|
from pytz import utc
|
||||||
from umongo.frameworks import MotorAsyncIOInstance
|
from beanie import init_beanie
|
||||||
|
|
||||||
from jarvis_core.util import find
|
from jarvis_core.db.models import all_models
|
||||||
|
|
||||||
CLIENT = None
|
|
||||||
JARVISDB = None
|
|
||||||
CTC2DB = None
|
|
||||||
JARVIS_INST = MotorAsyncIOInstance()
|
|
||||||
CTC2_INST = MotorAsyncIOInstance()
|
|
||||||
|
|
||||||
|
|
||||||
def connect(
|
async def connect(
|
||||||
host: str, username: str, password: str, port: int = 27017, testing: bool = False
|
host: str, username: str, password: str, port: int = 27017, testing: bool = False, extra_models: list = []
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Connect to MongoDB.
|
Connect to MongoDB.
|
||||||
|
@ -24,66 +17,10 @@ def connect(
|
||||||
username: Username
|
username: Username
|
||||||
password: Password
|
password: Password
|
||||||
port: Port
|
port: Port
|
||||||
|
testing: Whether or not to use jarvis_dev
|
||||||
|
extra_models: Extra beanie models to register
|
||||||
"""
|
"""
|
||||||
global CLIENT, JARVISDB, CTC2DB, JARVIS_INST, CTC2_INST
|
global CLIENT, JARVISDB, CTC2DB, JARVIS_INST, CTC2_INST
|
||||||
CLIENT = AsyncIOMotorClient(
|
client = AsyncIOMotorClient(host=host, username=username, password=password, port=port, tz_aware=True, tzinfo=utc)
|
||||||
host=host, username=username, password=password, port=port, tz_aware=True, tzinfo=utc
|
db = client.jarvis_dev if testing else client.jarvis
|
||||||
)
|
await init_beanie(database=db, document_models=all_models + extra_models)
|
||||||
JARVISDB = CLIENT.narvis if testing else CLIENT.jarvis
|
|
||||||
CTC2DB = CLIENT.ctc2
|
|
||||||
|
|
||||||
JARVIS_INST.set_db(JARVISDB)
|
|
||||||
CTC2_INST.set_db(CTC2DB)
|
|
||||||
|
|
||||||
|
|
||||||
QUERY_OPS = ["ne", "lt", "lte", "gt", "gte", "not", "in", "nin", "mod", "all", "size"]
|
|
||||||
STRING_OPS = [
|
|
||||||
"exact",
|
|
||||||
"iexact",
|
|
||||||
"contains",
|
|
||||||
"icontains",
|
|
||||||
"startswith",
|
|
||||||
"istartswith",
|
|
||||||
"endswith",
|
|
||||||
"iendswith",
|
|
||||||
"wholeword",
|
|
||||||
"iwholeword",
|
|
||||||
"regex",
|
|
||||||
"iregex" "match",
|
|
||||||
]
|
|
||||||
GEO_OPS = [
|
|
||||||
"get_within",
|
|
||||||
"geo_within_box",
|
|
||||||
"geo_within_polygon",
|
|
||||||
"geo_within_center",
|
|
||||||
"geo_within_sphere",
|
|
||||||
"geo_intersects",
|
|
||||||
"near",
|
|
||||||
"within_distance",
|
|
||||||
"within_spherical_distance",
|
|
||||||
"near_sphere",
|
|
||||||
"within_box",
|
|
||||||
"within_polygon",
|
|
||||||
"max_distance",
|
|
||||||
"min_distance",
|
|
||||||
]
|
|
||||||
|
|
||||||
ALL_OPS = QUERY_OPS + STRING_OPS + GEO_OPS
|
|
||||||
|
|
||||||
|
|
||||||
def q(**kwargs: dict) -> dict:
|
|
||||||
"""uMongo query wrapper.""" # noqa: D403
|
|
||||||
query = {}
|
|
||||||
for key, value in kwargs.items():
|
|
||||||
if key == "_id":
|
|
||||||
value = ObjectId(value)
|
|
||||||
elif "__" in key:
|
|
||||||
args = key.split("__")
|
|
||||||
if not any(x in ALL_OPS for x in args):
|
|
||||||
key = ".".join(args)
|
|
||||||
else:
|
|
||||||
idx = args.index(find(lambda x: x in ALL_OPS, args))
|
|
||||||
key = ".".join(args[:idx])
|
|
||||||
value = {f"${args[idx]}": value}
|
|
||||||
query[key] = value
|
|
||||||
return query
|
|
||||||
|
|
|
@ -1,205 +1,248 @@
|
||||||
"""JARVIS database models."""
|
"""JARVIS database models."""
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import Any, List
|
from functools import partial
|
||||||
|
|
||||||
import marshmallow as ma
|
from beanie import Document, Link
|
||||||
from umongo import Document, EmbeddedDocument, fields
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
from jarvis_core.db import CTC2_INST, JARVIS_INST
|
|
||||||
from jarvis_core.db.models.actions import Ban, Kick, Mute, Unban, Warning
|
from jarvis_core.db.models.actions import Ban, Kick, Mute, Unban, Warning
|
||||||
from jarvis_core.db.models.modlog import Action, Modlog, Note
|
from jarvis_core.db.models.modlog import Action, Modlog, Note
|
||||||
from jarvis_core.db.models.reddit import Subreddit, SubredditFollow
|
from jarvis_core.db.models.reddit import Subreddit, SubredditFollow
|
||||||
from jarvis_core.db.models.twitter import TwitterAccount, TwitterFollow
|
from jarvis_core.db.models.twitter import TwitterAccount, TwitterFollow
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Action",
|
||||||
|
"Autopurge",
|
||||||
|
"Autoreact",
|
||||||
|
"Ban",
|
||||||
|
"Config",
|
||||||
|
"Guess",
|
||||||
|
"Kick",
|
||||||
|
"Lock",
|
||||||
|
"Lockdown",
|
||||||
|
"Modlog",
|
||||||
|
"Mute",
|
||||||
|
"Note",
|
||||||
|
"Pin",
|
||||||
|
"Pinboard",
|
||||||
|
"Purge",
|
||||||
|
"Reminder",
|
||||||
|
"Rolegiver",
|
||||||
|
"Roleping",
|
||||||
|
"Setting",
|
||||||
|
"Subreddit",
|
||||||
|
"SubredditFollow",
|
||||||
|
"Temprole",
|
||||||
|
"TwitterAccount",
|
||||||
|
"TwitterFollow",
|
||||||
|
"Unban",
|
||||||
|
"UserSetting",
|
||||||
|
"Warning",
|
||||||
|
"all_models",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_now() -> datetime:
|
def get_now() -> datetime:
|
||||||
"""Get proper timestamp."""
|
"""Get proper timestamp."""
|
||||||
return datetime.now(tz=timezone.utc)
|
return datetime.now(tz=timezone.utc)
|
||||||
|
|
||||||
|
|
||||||
class RawField(fields.BaseField, ma.fields.Raw):
|
NowField = partial(Field, default_factory=get_now)
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Autopurge(Document):
|
class Autopurge(Document):
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
channel: int = fields.IntegerField(required=True)
|
channel: int
|
||||||
delay: int = fields.IntegerField(default=30)
|
delay: int = 30
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
created_at: datetime = fields.DateTimeField(default=datetime.now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Autoreact(Document):
|
class Autoreact(Document):
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
channel: int = fields.IntegerField(required=True)
|
channel: int
|
||||||
reactions: List[str] = fields.ListField(fields.StringField())
|
reactions: list[str] = Field(default_factory=list)
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
thread: bool = fields.BooleanField(default=True)
|
thread: bool
|
||||||
created_at: datetime = fields.DateTimeField(default=datetime.now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Config(Document):
|
class Config(Document):
|
||||||
"""Config database object."""
|
"""Config database object."""
|
||||||
|
|
||||||
key: str = fields.StringField(required=True)
|
key: str
|
||||||
value: Any = RawField(required=True)
|
value: str | int | bool
|
||||||
|
|
||||||
|
|
||||||
@CTC2_INST.register
|
|
||||||
class Guess(Document):
|
class Guess(Document):
|
||||||
"""Guess database object."""
|
"""Guess database object."""
|
||||||
|
|
||||||
correct: bool = fields.BooleanField(default=False)
|
correct: bool
|
||||||
guess: str = fields.StringField(required=True)
|
guess: str
|
||||||
user: int = fields.IntegerField(required=True)
|
user: int
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
class Permission(BaseModel):
|
||||||
class Permission(EmbeddedDocument):
|
|
||||||
"""Embedded Permissions document."""
|
"""Embedded Permissions document."""
|
||||||
|
|
||||||
id: int = fields.IntegerField(required=True)
|
id: int
|
||||||
allow: int = fields.IntegerField(default=0)
|
allow: int = 0
|
||||||
deny: int = fields.IntegerField(default=0)
|
deny: int = 0
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Lock(Document):
|
class Lock(Document):
|
||||||
"""Lock database object."""
|
"""Lock database object."""
|
||||||
|
|
||||||
active: bool = fields.BooleanField(default=True)
|
active: bool = True
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
channel: int = fields.IntegerField(required=True)
|
channel: int
|
||||||
duration: int = fields.IntegerField(default=10)
|
duration: int = 10
|
||||||
guild: int = fields.IntegerField(required=True)
|
reason: str
|
||||||
reason: str = fields.StringField(required=True)
|
original_perms: Permission
|
||||||
original_perms: Permission = fields.EmbeddedField(Permission, required=False)
|
created_at: datetime = NowField()
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Lockdown(Document):
|
class Lockdown(Document):
|
||||||
"""Lockdown database object."""
|
"""Lockdown database object."""
|
||||||
|
|
||||||
active: bool = fields.BooleanField(default=True)
|
active: bool = True
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
duration: int = fields.IntegerField(default=10)
|
duration: int = 10
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
reason: str = fields.StringField(required=True)
|
reason: str
|
||||||
original_perms: int = fields.IntegerField(required=True)
|
original_perms: int
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Purge(Document):
|
class Purge(Document):
|
||||||
"""Purge database object."""
|
"""Purge database object."""
|
||||||
|
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
channel: int = fields.IntegerField(required=True)
|
channel: int
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
count: int = fields.IntegerField(default=10)
|
count: int = 10
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Reminder(Document):
|
class Reminder(Document):
|
||||||
"""Reminder database object."""
|
"""Reminder database object."""
|
||||||
|
|
||||||
active: bool = fields.BooleanField(default=True)
|
active: bool = True
|
||||||
user: int = fields.IntegerField(required=True)
|
user: int
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
channel: int = fields.IntegerField(required=True)
|
channel: int
|
||||||
message: str = fields.StringField(required=True)
|
message: str
|
||||||
remind_at: datetime = fields.DateTimeField(required=True)
|
remind_at: datetime
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
private: bool = fields.BooleanField(default=False)
|
private: bool = False
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Rolegiver(Document):
|
class Rolegiver(Document):
|
||||||
"""Rolegiver database object."""
|
"""Rolegiver database object."""
|
||||||
|
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
roles: List[int] = fields.ListField(fields.IntegerField())
|
roles: list[int]
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
class Bypass(BaseModel):
|
||||||
class Bypass(EmbeddedDocument):
|
|
||||||
"""Roleping bypass embedded object."""
|
"""Roleping bypass embedded object."""
|
||||||
|
|
||||||
users: List[int] = fields.ListField(fields.IntegerField())
|
users: list[int]
|
||||||
roles: List[int] = fields.ListField(fields.IntegerField())
|
roles: list[int]
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Roleping(Document):
|
class Roleping(Document):
|
||||||
"""Roleping database object."""
|
"""Roleping database object."""
|
||||||
|
|
||||||
active: bool = fields.BooleanField(default=True)
|
active: bool = True
|
||||||
role: int = fields.IntegerField(required=True)
|
role: int
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
bypass: Bypass = fields.EmbeddedField(Bypass)
|
bypass: Bypass
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Setting(Document):
|
class Setting(Document):
|
||||||
"""Setting database object."""
|
"""Setting database object."""
|
||||||
|
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
setting: str = fields.StringField(required=True)
|
setting: str
|
||||||
value: Any = RawField()
|
value: str | int | bool
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
class Pinboard(Document):
|
||||||
class Star(Document):
|
"""Pinboard database object."""
|
||||||
"""Star database object."""
|
|
||||||
|
|
||||||
active: bool = fields.BooleanField(default=True)
|
channel: int
|
||||||
index: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
message: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
channel: int = fields.IntegerField(required=True)
|
created_at: datetime = NowField()
|
||||||
starboard: int = fields.IntegerField(required=True)
|
|
||||||
guild: int = fields.IntegerField(required=True)
|
|
||||||
admin: int = fields.IntegerField(required=True)
|
|
||||||
star: int = fields.IntegerField(required=True)
|
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
class Pin(Document):
|
||||||
class Starboard(Document):
|
"""Pin database object."""
|
||||||
"""Starboard database object."""
|
|
||||||
|
|
||||||
channel: int = fields.IntegerField(required=True)
|
active: bool = True
|
||||||
guild: int = fields.IntegerField(required=True)
|
index: int
|
||||||
admin: int = fields.IntegerField(required=True)
|
message: int
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
channel: int
|
||||||
|
pinboard: Link[Pinboard]
|
||||||
|
guild: int
|
||||||
|
admin: int
|
||||||
|
star: int
|
||||||
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Temprole(Document):
|
class Temprole(Document):
|
||||||
"""Temporary role object."""
|
"""Temporary role object."""
|
||||||
|
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
user: int = fields.IntegerField(required=True)
|
user: int
|
||||||
role: int = fields.IntegerField(required=True)
|
role: int
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
expires_at: datetime = fields.DateTimeField(required=True)
|
expires_at: datetime
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
reapply_on_rejoin: bool = True
|
||||||
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class UserSetting(Document):
|
class UserSetting(Document):
|
||||||
"""User Setting object."""
|
"""User Setting object."""
|
||||||
|
|
||||||
user: int = fields.IntegerField(required=True)
|
user: int
|
||||||
type: str = fields.StringField(required=True)
|
type: str
|
||||||
setting: str = fields.StringField(required=True)
|
settings: str
|
||||||
value: Any = RawField()
|
value: str | int | bool
|
||||||
|
|
||||||
class Meta:
|
class Setting:
|
||||||
collection_name = "usersetting"
|
name = "usersetting"
|
||||||
|
|
||||||
|
|
||||||
|
all_models = [
|
||||||
|
Action,
|
||||||
|
Autopurge,
|
||||||
|
Autoreact,
|
||||||
|
Ban,
|
||||||
|
Config,
|
||||||
|
Guess,
|
||||||
|
Kick,
|
||||||
|
Lock,
|
||||||
|
Lockdown,
|
||||||
|
Modlog,
|
||||||
|
Mute,
|
||||||
|
Note,
|
||||||
|
Pin,
|
||||||
|
Pinboard,
|
||||||
|
Purge,
|
||||||
|
Reminder,
|
||||||
|
Rolegiver,
|
||||||
|
Roleping,
|
||||||
|
Setting,
|
||||||
|
Subreddit,
|
||||||
|
SubredditFollow,
|
||||||
|
Temprole,
|
||||||
|
TwitterAccount,
|
||||||
|
TwitterFollow,
|
||||||
|
Unban,
|
||||||
|
UserSetting,
|
||||||
|
Warning,
|
||||||
|
]
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
"""User action models."""
|
"""User action models."""
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
from functools import partial
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from umongo import Document, fields
|
from beanie import Document, Field
|
||||||
|
|
||||||
from jarvis_core.db import JARVIS_INST
|
|
||||||
|
|
||||||
|
|
||||||
def get_now() -> datetime:
|
def get_now() -> datetime:
|
||||||
|
@ -11,66 +11,63 @@ def get_now() -> datetime:
|
||||||
return datetime.now(tz=timezone.utc)
|
return datetime.now(tz=timezone.utc)
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
NowField = partial(Field, default_factory=get_now)
|
||||||
|
|
||||||
|
|
||||||
class Ban(Document):
|
class Ban(Document):
|
||||||
active: bool = fields.BooleanField(default=True)
|
active: bool = True
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
user: int = fields.IntegerField(required=True)
|
user: int
|
||||||
username: str = fields.StringField(required=True)
|
username: str
|
||||||
discrim: int = fields.IntegerField(required=True)
|
discrim: int
|
||||||
duration: int = fields.IntegerField(required=False, default=None)
|
duration: Optional[int]
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
type: str = fields.StringField(default="perm")
|
type: str = "perm"
|
||||||
reason: str = fields.StringField(required=True)
|
reason: str
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Kick(Document):
|
class Kick(Document):
|
||||||
"""Kick database object."""
|
"""Kick database object."""
|
||||||
|
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
reason: str = fields.StringField(required=True)
|
reason: str
|
||||||
user: int = fields.IntegerField(required=True)
|
user: int
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Mute(Document):
|
class Mute(Document):
|
||||||
"""Mute database object."""
|
"""Mute database object."""
|
||||||
|
|
||||||
active: bool = fields.BooleanField(default=True)
|
active: bool = True
|
||||||
user: int = fields.IntegerField(required=True)
|
user: int
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
duration: int = fields.IntegerField(default=10)
|
duration: int = 10
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
reason: str = fields.StringField(required=True)
|
reason: str
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Unban(Document):
|
class Unban(Document):
|
||||||
"""Unban database object."""
|
"""Unban database object."""
|
||||||
|
|
||||||
user: int = fields.IntegerField(required=True)
|
user: int
|
||||||
username: str = fields.StringField(required=True)
|
username: str
|
||||||
discrim: int = fields.IntegerField(required=True)
|
discrim: str
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
admin: int = fields.IntegerField(required=True)
|
reason: str
|
||||||
reason: str = fields.StringField(required=True)
|
created_at: datetime = NowField()
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Warning(Document):
|
class Warning(Document):
|
||||||
"""Warning database object."""
|
"""Warning database object."""
|
||||||
|
|
||||||
active: bool = fields.BooleanField(default=True)
|
active: bool = True
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
user: int = fields.IntegerField(required=True)
|
user: int
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
duration: int = fields.IntegerField(default=24)
|
duration: int = 24
|
||||||
reason: str = fields.StringField(required=True)
|
reason: str
|
||||||
expires_at: datetime = fields.DateTimeField(required=True)
|
expires_at: datetime
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
"""Modlog database models."""
|
"""Modlog database models."""
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import List
|
from functools import partial
|
||||||
|
|
||||||
import nanoid
|
import nanoid
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
from umongo import Document, EmbeddedDocument, fields
|
from beanie import Document
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
from jarvis_core.db import JARVIS_INST
|
|
||||||
|
|
||||||
NANOID_ALPHA = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
NANOID_ALPHA = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
@ -21,33 +20,34 @@ def get_id() -> str:
|
||||||
return nanoid.generate(NANOID_ALPHA, 12)
|
return nanoid.generate(NANOID_ALPHA, 12)
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
NanoField = partial(Field, default_factory=get_id)
|
||||||
class Action(EmbeddedDocument):
|
NowField = partial(Field, default_factory=get_now)
|
||||||
|
|
||||||
|
|
||||||
|
class Action(BaseModel):
|
||||||
"""Modlog embedded action document."""
|
"""Modlog embedded action document."""
|
||||||
|
|
||||||
action_type: str = fields.StringField(required=True)
|
action_type: str
|
||||||
parent: ObjectId = fields.ObjectIdField(required=True)
|
parent: ObjectId
|
||||||
orphaned: bool = fields.BoolField(default=False)
|
orphaned: bool = False
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
class Note(BaseModel):
|
||||||
class Note(EmbeddedDocument):
|
|
||||||
"""Modlog embedded note document."""
|
"""Modlog embedded note document."""
|
||||||
|
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
content: str = fields.StrField(required=True)
|
content: str
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class Modlog(Document):
|
class Modlog(Document):
|
||||||
"""Modlog database object."""
|
"""Modlog database object."""
|
||||||
|
|
||||||
user: int = fields.IntegerField(required=True)
|
user: int
|
||||||
nanoid: str = fields.StringField(default=get_id)
|
nanoid: str = NanoField()
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
actions: List[Action] = fields.ListField(fields.EmbeddedField(Action), factory=list)
|
actions: list[Action] = Field(default_factory=list)
|
||||||
open: bool = fields.BoolField(default=True)
|
notes: list[Note] = Field(default_factory=list)
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
open: bool = True
|
||||||
notes: List[Note] = fields.ListField(fields.EmbeddedField(Note), factory=list)
|
created_at: datetime = NowField
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
"""Reddit databaes models."""
|
"""Reddit databaes models."""
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from umongo import Document, fields
|
from beanie import Document, Field
|
||||||
|
|
||||||
from jarvis_core.db import JARVIS_INST
|
|
||||||
|
|
||||||
|
|
||||||
def get_now() -> datetime:
|
def get_now() -> datetime:
|
||||||
|
@ -11,24 +10,25 @@ def get_now() -> datetime:
|
||||||
return datetime.now(tz=timezone.utc)
|
return datetime.now(tz=timezone.utc)
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
NowField = partial(Field, default_factory=get_now)
|
||||||
|
|
||||||
|
|
||||||
class Subreddit(Document):
|
class Subreddit(Document):
|
||||||
"""Subreddit object."""
|
"""Subreddit object."""
|
||||||
|
|
||||||
display_name: str = fields.StringField(required=True)
|
display_name: str
|
||||||
over18: bool = fields.BooleanField(default=False)
|
over18: bool = False
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class SubredditFollow(Document):
|
class SubredditFollow(Document):
|
||||||
"""Subreddit Follow object."""
|
"""Subreddit Follow object."""
|
||||||
|
|
||||||
active: bool = fields.BooleanField(default=True)
|
active: bool = True
|
||||||
display_name: str = fields.StringField(required=True)
|
display_name: str
|
||||||
channel: int = fields.IntegerField(required=True)
|
channel: int
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
class Meta:
|
class Setting:
|
||||||
collection_name = "subredditfollow"
|
name = "subredditfollow"
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
"""Twitter database models."""
|
"""Twitter database models."""
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from umongo import Document, fields
|
from beanie import Document, Field
|
||||||
|
|
||||||
from jarvis_core.db import JARVIS_INST
|
|
||||||
|
|
||||||
|
|
||||||
def get_now() -> datetime:
|
def get_now() -> datetime:
|
||||||
|
@ -11,30 +10,31 @@ def get_now() -> datetime:
|
||||||
return datetime.now(tz=timezone.utc)
|
return datetime.now(tz=timezone.utc)
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
NowField = partial(Field, default_factory=get_now)
|
||||||
|
|
||||||
|
|
||||||
class TwitterAccount(Document):
|
class TwitterAccount(Document):
|
||||||
"""Twitter Account object."""
|
"""Twitter Account object."""
|
||||||
|
|
||||||
handle: str = fields.StringField(required=True)
|
handle: str
|
||||||
twitter_id: int = fields.IntegerField(required=True)
|
twitter_id: int
|
||||||
last_tweet: int = fields.IntegerField(required=True)
|
last_tweet: int
|
||||||
last_sync: datetime = fields.DateTimeField(default=get_now)
|
last_sync: datetime = NowField()
|
||||||
|
|
||||||
class Meta:
|
class Setting:
|
||||||
collection_name = "twitteraccount"
|
name = "twitteraccount"
|
||||||
|
|
||||||
|
|
||||||
@JARVIS_INST.register
|
|
||||||
class TwitterFollow(Document):
|
class TwitterFollow(Document):
|
||||||
"""Twitter Follow object."""
|
"""Twitter Follow object."""
|
||||||
|
|
||||||
active: bool = fields.BooleanField(default=True)
|
active: bool = True
|
||||||
twitter_id: int = fields.IntegerField(required=True)
|
twitter_id: int
|
||||||
channel: int = fields.IntegerField(required=True)
|
channel: int
|
||||||
guild: int = fields.IntegerField(required=True)
|
guild: int
|
||||||
retweets: bool = fields.BooleanField(default=True)
|
retweets: bool = True
|
||||||
admin: int = fields.IntegerField(required=True)
|
admin: int
|
||||||
created_at: datetime = fields.DateTimeField(default=get_now)
|
created_at: datetime = NowField()
|
||||||
|
|
||||||
class Meta:
|
class Setting:
|
||||||
collection_name = "twitterfollow"
|
name = "twitterfollow"
|
||||||
|
|
|
@ -9,38 +9,6 @@ from jarvis_core.filters import url
|
||||||
DEFAULT_BLOCKSIZE = 8 * 1024 * 1024
|
DEFAULT_BLOCKSIZE = 8 * 1024 * 1024
|
||||||
|
|
||||||
|
|
||||||
class Singleton(object):
|
|
||||||
REQUIRED = []
|
|
||||||
OPTIONAL = {}
|
|
||||||
|
|
||||||
def __new__(cls, *args: list, **kwargs: dict):
|
|
||||||
"""Create a new singleton."""
|
|
||||||
inst = cls.__dict__.get("inst")
|
|
||||||
if inst is not None:
|
|
||||||
return inst
|
|
||||||
|
|
||||||
inst = object.__new__(cls)
|
|
||||||
inst.init(*args, **kwargs)
|
|
||||||
inst._validate()
|
|
||||||
cls.__inst__ = inst
|
|
||||||
|
|
||||||
return inst
|
|
||||||
|
|
||||||
def _validate(self) -> None:
|
|
||||||
for key in self.REQUIRED:
|
|
||||||
if not getattr(self, key, None):
|
|
||||||
raise ValueError(f"Missing required key: {key}")
|
|
||||||
|
|
||||||
def init(self, **kwargs: dict) -> None:
|
|
||||||
"""Initialize the object."""
|
|
||||||
for key, value in kwargs.items():
|
|
||||||
setattr(self, key, value)
|
|
||||||
|
|
||||||
for key, value in self.OPTIONAL.items():
|
|
||||||
if not getattr(self, key, None):
|
|
||||||
setattr(self, key, value)
|
|
||||||
|
|
||||||
|
|
||||||
async def hash(
|
async def hash(
|
||||||
data: str, method: Union[Callable, str] = hashlib.sha256, size: int = DEFAULT_BLOCKSIZE
|
data: str, method: Union[Callable, str] = hashlib.sha256, size: int = DEFAULT_BLOCKSIZE
|
||||||
) -> Tuple[str, int, str]:
|
) -> Tuple[str, int, str]:
|
||||||
|
|
987
poetry.lock
generated
987
poetry.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -6,18 +6,23 @@ authors = ["Zevaryx <zevaryx@gmail.com>"]
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.10"
|
python = "^3.10"
|
||||||
orjson = "^3.6.6"
|
orjson = {version = "^3.6.6"}
|
||||||
motor = "^2.5.1"
|
motor = "^2.5.1"
|
||||||
umongo = "^3.1.0"
|
PyYAML = {version = "^6.0"}
|
||||||
PyYAML = "^6.0"
|
|
||||||
pytz = "^2022.1"
|
pytz = "^2022.1"
|
||||||
aiohttp = "^3.8.1"
|
aiohttp = "^3.8.1"
|
||||||
rich = "^12.3.0"
|
rich = "^12.3.0"
|
||||||
nanoid = "^2.0.0"
|
nanoid = "^2.0.0"
|
||||||
|
python-dotenv = {version = "^0.20.0"}
|
||||||
|
beanie = "^1.17.0"
|
||||||
|
pydantic = "^1.10.7"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
pytest = "^7.1"
|
pytest = "^7.1"
|
||||||
|
|
||||||
|
[tool.poetry.group.dev.dependencies]
|
||||||
|
black = "^23.1.0"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|
Loading…
Add table
Reference in a new issue