Merge branch 'beanie' into 'main'

Beanie

See merge request stark-industries/jarvis/jarvis-core!1
This commit is contained in:
Zeva Rose 2023-09-14 02:38:20 +00:00
commit d598ec8b49
17 changed files with 1094 additions and 1020 deletions

22
.flake8
View file

@ -3,18 +3,16 @@ exclude =
tests/* tests/*
extend-ignore = extend-ignore =
Q0, E501, C812, E203, W503, # These default to arguing with Black. We might configure some of them eventually Q0, E501, C812, E203, W503,
ANN1, # Ignore self and cls annotations ANN1, ANN003,
ANN204, ANN206, # return annotations for special methods and class methods ANN204, ANN206,
D105, D107, # Missing Docstrings in magic method and __init__ D105, D107,
S311, # Standard pseudo-random generators are not suitable for security/cryptographic purposes. S311,
D401, # First line should be in imperative mood; try rephrasing D401,
D400, # First line should end with a period D400,
D101, # Missing docstring in public class D101, D102,
D106, # Missing docstring in public nested class D106,
R503,
# Plugins we don't currently include: flake8-return
R503, # missing explicit return at the end of function ableto return non-None value.
max-line-length=100 max-line-length=100

View file

@ -1,6 +1,6 @@
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0 rev: v4.4.0
hooks: hooks:
- id: check-toml - id: check-toml
- id: check-yaml - id: check-yaml
@ -9,21 +9,19 @@ repos:
- id: requirements-txt-fixer - id: requirements-txt-fixer
- id: end-of-file-fixer - id: end-of-file-fixer
- id: debug-statements - id: debug-statements
language_version: python3.10
- id: trailing-whitespace - id: trailing-whitespace
args: [--markdown-linebreak-ext=md] args: [--markdown-linebreak-ext=md]
- repo: https://github.com/pre-commit/pygrep-hooks - repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.9.0 rev: v1.10.0
hooks: hooks:
- id: python-check-blanket-noqa - id: python-check-blanket-noqa
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 22.3.0 rev: 23.7.0
hooks: hooks:
- id: black - id: black
args: [--line-length=100, --target-version=py310] args: [--line-length=100]
language_version: python3.10
- repo: https://github.com/pre-commit/mirrors-isort - repo: https://github.com/pre-commit/mirrors-isort
rev: v5.10.1 rev: v5.10.1
@ -32,7 +30,7 @@ repos:
args: ["--profile", "black"] args: ["--profile", "black"]
- repo: https://github.com/pycqa/flake8 - repo: https://github.com/pycqa/flake8
rev: 4.0.1 rev: 6.1.0
hooks: hooks:
- id: flake8 - id: flake8
additional_dependencies: additional_dependencies:
@ -46,4 +44,3 @@ repos:
- flake8-deprecated - flake8-deprecated
- flake8-print - flake8-print
- flake8-return - flake8-return
language_version: python3.10

View file

@ -1,13 +1,12 @@
"""Load global config.""" """Load global config."""
import os import os
from lib2to3.pgen2 import token
from pathlib import Path from pathlib import Path
from typing import Union from typing import Union
from dotenv import load_dotenv from dotenv import load_dotenv
from yaml import load from yaml import load
from jarvis_core.util import Singleton, find_all from jarvis_core.util import Singleton
try: try:
from yaml import CLoader as Loader from yaml import CLoader as Loader
@ -65,8 +64,7 @@ class Config(Singleton):
def load(cls) -> "Config": def load(cls) -> "Config":
if DEFAULT_ENV_PATH.exists(): if DEFAULT_ENV_PATH.exists():
return cls.from_env() return cls.from_env()
else: return cls.from_yaml()
return cls.from_yaml()
@classmethod @classmethod
def reload(cls) -> bool: def reload(cls) -> bool:

View file

@ -1,101 +1,30 @@
"""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: list[str] | str,
username: str, username: str,
password: str, password: str,
port: int = 27017, port: int = 27017,
testing: bool = False, testing: bool = False,
host: str = None, extra_models: list = [],
hosts: list[str] = None,
replicaset: str = None,
) -> None: ) -> None:
""" """
Connect to MongoDB. Connect to MongoDB.
Args: Args:
host: Hostname/IP host: Hostname/IP, or list of hosts for replica sets
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 client = AsyncIOMotorClient(host, username=username, password=password, port=port, tz_aware=True, tzinfo=utc)
db = client.jarvis_dev if testing else client.jarvis
if not replicaset: await init_beanie(database=db, document_models=all_models + extra_models)
CLIENT = AsyncIOMotorClient(
host=host, username=username, password=password, port=port, tz_aware=True, tzinfo=utc
)
else:
CLIENT = AsyncIOMotorClient(
hosts, username=username, password=password, tz_aware=True, tzinfo=utc, replicaset=replicaset
)
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,257 +1,277 @@
"""JARVIS database models.""" """JARVIS database models."""
import re
from datetime import datetime from datetime import datetime
from typing import Any, List from typing import Optional
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.fields import RawField from jarvis_core.db.models.modlog import Action, Modlog, Note
from jarvis_core.db.models.actions import * from jarvis_core.db.models.reddit import Subreddit, SubredditFollow
from jarvis_core.db.models.backups import * from jarvis_core.db.models.twitter import TwitterAccount, TwitterFollow
from jarvis_core.db.models.mastodon import * from jarvis_core.db.utils import NowField
from jarvis_core.db.models.modlog import *
from jarvis_core.db.models.reddit import * __all__ = [
from jarvis_core.db.models.twitter import * "Action",
from jarvis_core.db.utils import get_now "Autopurge",
"Autoreact",
"Ban",
"Config",
"Filter",
"Guess",
"Kick",
"Lock",
"Lockdown",
"Modlog",
"Mute",
"Note",
"Pin",
"Pinboard",
"Phishlist",
"Purge",
"Reminder",
"Rolegiver",
"Bypass",
"Roleping",
"Setting",
"Subreddit",
"SubredditFollow",
"Tag",
"Temprole",
"TwitterAccount",
"TwitterFollow",
"Unban",
"UserSetting",
"Warning",
"all_models",
]
@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.AwareDateTimeField(default=get_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.AwareDateTimeField(default=get_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
@JARVIS_INST.register
class Filter(Document): class Filter(Document):
"""Regex Filter database object.""" """Filter database object."""
def _validate_filters(value): guild: int
for v in value: name: str
try: filters: list[str] = Field(default_factory=list)
re.compile(v)
except re.error:
raise ValueError(f"Invalid regex: {v}")
guild: int = fields.IntegerField(required=True)
name: str = fields.StringField(required=True)
filters: List[str] = fields.ListField(fields.StringField(), validate=[_validate_filters])
@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.AwareDateTimeField(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.AwareDateTimeField(default=get_now) created_at: datetime = NowField()
@JARVIS_INST.register
class Event(Document):
"""Event Meetup Object."""
user: int = fields.IntegerField(required=True)
going: bool = fields.BooleanField(required=True)
travel_method: str = fields.StringField()
before_flight: str = fields.StringField()
before_arrival_time: datetime = fields.AwareDateTimeField()
before_departure_time: datetime = fields.AwareDateTimeField()
after_flight: str = fields.StringField()
after_arrival_time: datetime = fields.AwareDateTimeField()
after_departure_time: datetime = fields.AwareDateTimeField()
hotel: str = fields.StringField()
event_name: str = fields.StringField()
@JARVIS_INST.register
class Phishlist(Document):
"""Phishing safelist."""
url: str = fields.StringField(required=True)
confirmed: bool = fields.BooleanField(default=False)
valid: bool = fields.BooleanField(default=True)
created_at: datetime = fields.AwareDateTimeField(default=get_now)
@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 = Field(10, alias="count")
created_at: datetime = fields.AwareDateTimeField(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.AwareDateTimeField(required=True) remind_at: datetime
created_at: datetime = fields.AwareDateTimeField(default=get_now) created_at: datetime = NowField()
private: bool = fields.BooleanField(default=False) repeat: Optional[str] = None
timezone: str = "UTC"
total_reminders: int = 0
parent: Optional[str] = None
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]
group: Optional[str] = None
@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.AwareDateTimeField(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 | list[int | str]
@JARVIS_INST.register class Phishlist(Document):
class Star(Document): """Phishlist database object."""
"""Star database object."""
active: bool = fields.BooleanField(default=True) url: str
index: int = fields.IntegerField(required=True) confirmed: bool = False
message: int = fields.IntegerField(required=True) valid: bool = True
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.AwareDateTimeField(default=get_now)
@JARVIS_INST.register class Pinboard(Document):
class Starboard(Document): """Pinboard database object."""
"""Starboard database object."""
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.AwareDateTimeField(default=get_now) created_at: datetime = NowField()
class Pin(Document):
"""Pin database object."""
active: bool = True
index: int
message: int
channel: int
pinboard: Link[Pinboard]
guild: int
admin: int
pin: int
created_at: datetime = NowField()
@JARVIS_INST.register
class Tag(Document): class Tag(Document):
"""Tag database object.""" """Tag database object."""
creator: int = fields.IntegerField(required=True) creator: int
created_at: datetime = fields.AwareDateTimeField(default=get_now) name: str
editor: int = fields.IntegerField() content: str
edited_at: datetime = fields.AwareDateTimeField() guild: int
name: str = fields.StringField(required=True) created_at: datetime = NowField()
content: str = fields.StringField(required=True) edited_at: Optional[datetime] = None
guild: int = fields.IntegerField(required=True) editor: Optional[int] = None
@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.AwareDateTimeField(required=True) expires_at: datetime
created_at: datetime = fields.AwareDateTimeField(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) setting: str
value: Any = RawField() value: str | int | bool
class Meta:
collection_name = "usersetting" all_models = [
Autopurge,
Autoreact,
Ban,
Config,
Filter,
Guess,
Kick,
Lock,
Lockdown,
Modlog,
Mute,
Pin,
Pinboard,
Phishlist,
Purge,
Reminder,
Rolegiver,
Roleping,
Setting,
Subreddit,
SubredditFollow,
Tag,
Temprole,
TwitterAccount,
TwitterFollow,
Unban,
UserSetting,
Warning,
]

View file

@ -1,72 +1,66 @@
"""User action models.""" """User action models."""
from datetime import datetime, timezone from datetime import datetime
from typing import Optional
from umongo import Document, fields from beanie import Document
from jarvis_core.db import JARVIS_INST from jarvis_core.db.utils import NowField
from jarvis_core.db.utils import get_now
@JARVIS_INST.register
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: Optional[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.AwareDateTimeField(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.AwareDateTimeField(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.AwareDateTimeField(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: Optional[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.AwareDateTimeField(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.AwareDateTimeField(required=True) expires_at: datetime
created_at: datetime = fields.AwareDateTimeField(default=get_now) created_at: datetime = NowField()

View file

@ -1,122 +1,104 @@
from datetime import datetime from datetime import datetime
from typing import List, Optional from typing import Optional
from umongo import Document, EmbeddedDocument, fields from beanie import Document, Indexed, Link
from pydantic import BaseModel, Field
from jarvis_core import __version__ from jarvis_core import __version__
from jarvis_core.db import JARVIS_INST from jarvis_core.db.utils import NanoField, NowField
from jarvis_core.db.fields import BinaryField
from jarvis_core.db.utils import get_id, get_now
@JARVIS_INST.register
class Image(Document): class Image(Document):
discord_id: int = fields.IntegerField(unique=True) discord_id: int = Indexed(int, unique=True)
image_data: List[bytes] = BinaryField() image_data: list[bytes]
image_ext: str = fields.StringField() image_ext: str
created_at: datetime = fields.AwareDateTimeField(default=get_now) created_at: datetime = NowField()
@JARVIS_INST.register class PermissionOverwriteBackup(BaseModel):
class PermissionOverwriteBackup(EmbeddedDocument): id: int
id: int = fields.IntegerField() type: int
type: int = fields.IntegerField() allow: int
allow: int = fields.IntegerField() deny: int
deny: int = fields.IntegerField()
@JARVIS_INST.register class WebhookBackup(BaseModel):
class WebhookBackup(EmbeddedDocument): id: int
id: int = fields.IntegerField() channel_id: int
channel_id: int = fields.IntegerField() type: int
type: int = fields.IntegerField() avatar: Link[Image]
avatar: Image = fields.ReferenceField(Image) name: str
name: str = fields.StringField()
@JARVIS_INST.register class ChannelBackup(BaseModel):
class ChannelBackup(EmbeddedDocument): id: int
id: int = fields.IntegerField() name: str
name: str = fields.StringField() type: int
type: int = fields.IntegerField() position: int
position: int = fields.IntegerField() topic: Optional[str] = None
topic: Optional[str] = fields.StringField(default=None) nsfw: bool = False
nsfw: bool = fields.BooleanField(default=False) rate_limit_per_user: Optional[int] = None
rate_limit_per_user: int = fields.IntegerField(default=None) bitrate: Optional[int] = None
bitrate: Optional[int] = fields.IntegerField(default=None) user_limit: Optional[int] = None
user_limit: Optional[int] = fields.IntegerField(default=None) permission_overwrites: list[PermissionOverwriteBackup] = Field(default_factory=list)
permission_overwrites: List[PermissionOverwriteBackup] = fields.ListField( parent_id: Optional[int] = None
fields.EmbeddedField(PermissionOverwriteBackup), factory=list rtc_region: Optional[str] = None
) video_quality_mode: Optional[int] = None
parent_id: Optional[int] = fields.IntegerField(default=None) default_auto_archive_duration: Optional[int] = None
rtc_region: Optional[str] = fields.StringField(default=None) webhooks: list[WebhookBackup] = Field(default_factory=list)
video_quality_mode: Optional[int] = fields.IntegerField(default=None)
default_auto_archive_duration: Optional[int] = fields.IntegerField(default=None)
webhooks: List[WebhookBackup] = fields.ListField(
fields.EmbeddedField(WebhookBackup), factory=list
)
@JARVIS_INST.register class RoleBackup(BaseModel):
class RoleBackup(EmbeddedDocument): id: int
id: int = fields.IntegerField() name: str
name: str = fields.StringField() permissions: int
permissions: int = fields.IntegerField() color: str
color: str = fields.StringField() hoist: bool
hoist: bool = fields.BooleanField() mentionable: bool
mentionable: bool = fields.BooleanField()
@JARVIS_INST.register class EmojiBackup(BaseModel):
class EmojiBackup(EmbeddedDocument): id: int
id: int = fields.IntegerField() name: str
name: str = fields.StringField() image: Link[Image]
image: Image = fields.ReferenceField(Image)
@JARVIS_INST.register class StickerBackup(BaseModel):
class StickerBackup(EmbeddedDocument): id: int
id: int = fields.IntegerField() name: str
name: str = fields.StringField() format_type: int
format_type: int = fields.IntegerField() tags: str
tags: str = fields.StringField() type: int
type: int = fields.IntegerField() image: Link[Image]
image: Image = fields.ReferenceField(Image)
@JARVIS_INST.register class GuildBackup(BaseModel):
class GuildBackup(EmbeddedDocument): name: str
name: str = fields.StringField(required=True) description: Optional[str] = None
description: str = fields.StringField(default=None) default_message_notifications: Optional[int] = None
default_message_notifications: Optional[int] = fields.IntegerField(default=None) explicit_content_filter: Optional[int] = None
explicit_content_filter: Optional[int] = fields.IntegerField(default=None) afk_channel: Optional[int] = None
afk_channel: Optional[int] = fields.IntegerField(default=None) afk_timeout: Optional[int] = None
afk_timeout: Optional[int] = fields.IntegerField(default=None) icon: Optional[Link[Image]] = None
icon: Optional[Image] = fields.ReferenceField(Image, default=None) owner: int
owner: int = fields.IntegerField(required=True) splash: Optional[Link[Image]] = None
splash: Optional[Image] = fields.ReferenceField(Image, default=None) discovery_splash: Optional[Link[Image]] = None
discovery_splash: Optional[Image] = fields.ReferenceField(Image, default=None) banner: Optional[Link[Image]] = None
banner: Optional[Image] = fields.ReferenceField(Image, default=None) system_channel: Optional[int] = None
system_channel: Optional[int] = fields.IntegerField(default=None) system_channel_flags: Optional[int] = None
system_channel_flags: Optional[int] = fields.IntegerField(default=None) rules_channel: Optional[int] = None
rules_channel: Optional[int] = fields.IntegerField(default=None) public_updates_channel: Optional[int] = None
public_updates_channel: Optional[int] = fields.IntegerField(default=None) preferred_locale: Optional[str] = None
preferred_locale: Optional[str] = fields.StringField(default=None) features: list[str] = Field(default_factory=list)
features: List[str] = fields.ListField(fields.StringField, factory=list) channels: list[ChannelBackup] = Field(default_factory=list)
channels: List[ChannelBackup] = fields.ListField( roles: list[RoleBackup] = Field(default_factory=list)
fields.EmbeddedField(ChannelBackup), factory=list emojis: list[EmojiBackup] = Field(default_factory=list)
) stickers: list[StickerBackup] = Field(default_factory=list)
roles: List[RoleBackup] = fields.ListField(fields.EmbeddedField(RoleBackup), factory=list)
emojis: List[EmojiBackup] = fields.ListField(fields.EmbeddedField(EmojiBackup), factory=list)
stickers: List[StickerBackup] = fields.ListField(
fields.EmbeddedField(StickerBackup), factory=list
)
@JARVIS_INST.register
class Backup(Document): class Backup(Document):
created_at: datetime = fields.AwareDateTimeField(default=get_now) created_at: datetime = NowField()
guild_id: int = fields.IntegerField() guild_id: int
bkid: str = fields.StringField(default=get_id) bkid: str = NanoField()
guild: GuildBackup = fields.EmbeddedField(GuildBackup, required=True) guild: GuildBackup
version: str = fields.StringField(default=__version__) version: str = Field(default=__version__)

View file

@ -0,0 +1,12 @@
from datetime import datetime
from beanie import Document
from pydantic import Field
from jarvis_core.db.utils import get_now
class Captcha(Document):
user: int
guild: int
correct: str
created_at: datetime = Field(default_factory=get_now)

View file

@ -1,36 +1,30 @@
"""Mastodon databaes models.""" """Mastodon databaes models."""
from datetime import datetime, timezone from datetime import datetime, timezone
from umongo import Document, fields from beanie import Document
from jarvis_core.db import JARVIS_INST from jarvis_core.db import JARVIS_INST
from jarvis_core.db.utils import get_now from jarvis_core.db.utils import NowField
@JARVIS_INST.register @JARVIS_INST.register
class MastodonUser(Document): class MastodonUser(Document):
"""User object.""" """User object."""
user_id: int = fields.IntegerField(required=True) user_id: int
acct: str = fields.StringField(required=True) acct: str
username: str = fields.StringField(required=True) username: str
last_sync: datetime = fields.AwareDateTimeField(default=get_now) last_sync: datetime = NowField()
class Meta:
collection_name = "mastodonuser"
@JARVIS_INST.register @JARVIS_INST.register
class MastodonFollow(Document): class MastodonFollow(Document):
"""User Follow object.""" """User Follow object."""
active: bool = fields.BooleanField(default=True) active: bool = True
user_id: int = fields.IntegerField(required=True) user_id: int
channel: int = fields.IntegerField(required=True) channel: int
guild: int = fields.IntegerField(required=True) guild: int
reblogged: bool = fields.BooleanField(default=True) reblogged: bool = True
admin: int = fields.IntegerField(required=True) admin: int
created_at: datetime = fields.AwareDateTimeField(default=get_now) created_at: datetime = NowField()
class Meta:
collection_name = "mastodonfollow"

View file

@ -1,41 +1,36 @@
"""Modlog database models.""" """Modlog database models."""
from datetime import datetime, timezone from datetime import datetime
from typing import List
from bson import ObjectId from beanie import Document, PydanticObjectId
from umongo import Document, EmbeddedDocument, fields from pydantic import BaseModel, Field
from jarvis_core.db import JARVIS_INST from jarvis_core.db.utils import NowField, NanoField
from jarvis_core.db.utils import get_id, get_now
@JARVIS_INST.register class Action(BaseModel):
class Action(EmbeddedDocument):
"""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: PydanticObjectId
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.AwareDateTimeField(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.AwareDateTimeField(default=get_now) open: bool = True
notes: List[Note] = fields.ListField(fields.EmbeddedField(Note), factory=list) created_at: datetime = NowField

View file

@ -1,52 +1,27 @@
"""Reddit databaes models.""" """Reddit databaes models."""
from datetime import datetime, timezone from datetime import datetime
from umongo import Document, fields from beanie import Document
from jarvis_core.db import JARVIS_INST from jarvis_core.db.utils import NowField
from jarvis_core.db.utils import get_now
@JARVIS_INST.register
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.AwareDateTimeField(default=get_now) created_at: datetime = NowField()
class Meta: class Setting:
collection_name = "subredditfollow" name = "subredditfollow"
@JARVIS_INST.register
class Redditor(Document):
"""Reddit User object."""
name: str = fields.StringField(required=True)
@JARVIS_INST.register
class RedditorFollow(Document):
"""Reditor Follow object."""
active: bool = fields.BooleanField(default=True)
name: str = fields.StringField(required=True)
channel: int = fields.IntegerField(required=True)
guild: int = fields.IntegerField(required=True)
admin: int = fields.IntegerField(required=True)
created_at: datetime = fields.AwareDateTimeField(default=get_now)
class Meta:
collection_name = "redditorfollow"

View file

@ -1,36 +1,33 @@
"""Twitter database models.""" """Twitter database models."""
from datetime import datetime, timezone from datetime import datetime
from umongo import Document, fields from beanie import Document
from jarvis_core.db import JARVIS_INST from jarvis_core.db.utils import NowField
from jarvis_core.db.utils import get_now
@JARVIS_INST.register
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.AwareDateTimeField(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.AwareDateTimeField(default=get_now) created_at: datetime = NowField()
class Meta: class Setting:
collection_name = "twitterfollow" name = "twitterfollow"

View file

@ -1,6 +1,8 @@
from datetime import datetime, timezone from datetime import datetime, timezone
from functools import partial
import nanoid import nanoid
from pydantic import Field
NANOID_ALPHA = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" NANOID_ALPHA = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
@ -13,3 +15,7 @@ def get_now() -> datetime:
def get_id() -> str: def get_id() -> str:
"""Get nanoid.""" """Get nanoid."""
return nanoid.generate(NANOID_ALPHA, 12) return nanoid.generate(NANOID_ALPHA, 12)
NowField = partial(Field, default_factory=get_now)
NanoField = partial(Field, default_factory=get_id)

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]:

798
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,26 +1,29 @@
[tool.poetry] [tool.poetry]
name = "jarvis-core" name = "jarvis-core"
version = "0.16.1" version = "0.18.0"
description = "JARVIS core" description = "JARVIS core"
authors = ["Zevaryx <zevaryx@gmail.com>"] authors = ["Zevaryx <zevaryx@gmail.com>"]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.10" python = ">=3.10,<4"
orjson = "^3.6.6" orjson = { version = "^3.6.6" }
motor = "^3.1.1" motor = "^3.1.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 = "^0.21.0" python-dotenv = "^0.21.0"
beanie = "^1.17.0"
pydantic = ">=2.3.0,<3"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
pytest = "^7.1" pytest = "^7.1"
[tool.poetry.group.dev.dependencies]
black = "^23.1.0"
ipython = "^8.5.0" ipython = "^8.5.0"
rich = "^12.6.0" rich = "^12.6.0"
black = {version = "^22.10.0", allow-prereleases = true}
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.0.0"]