Migrate to beanie

This commit is contained in:
Zeva Rose 2023-03-23 21:56:54 -06:00
parent 7bb9b25f63
commit eb36cf7413
11 changed files with 970 additions and 737 deletions

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"python.formatting.provider": "black"
}

View file

@ -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."""

View file

@ -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

View file

@ -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,
]

View file

@ -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()

View file

@ -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

View file

@ -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"

View file

@ -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"

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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"