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

42
.flake8
View file

@ -1,22 +1,20 @@
[flake8] [flake8]
exclude = 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 per-file-ignores =
jarvis_core/db/models/__init__.py:F401
per-file-ignores =
jarvis_core/db/models/__init__.py:F401

View file

@ -1,49 +1,46 @@
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
args: [--unsafe] args: [--unsafe]
- id: check-merge-conflict - id: check-merge-conflict
- 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.10.0
rev: v1.9.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: 23.7.0
rev: 22.3.0 hooks:
hooks: - id: black
- id: black args: [--line-length=100]
args: [--line-length=100, --target-version=py310]
language_version: python3.10 - repo: https://github.com/pre-commit/mirrors-isort
rev: v5.10.1
- repo: https://github.com/pre-commit/mirrors-isort hooks:
rev: v5.10.1 - id: isort
hooks: args: ["--profile", "black"]
- id: isort
args: ["--profile", "black"] - repo: https://github.com/pycqa/flake8
rev: 6.1.0
- repo: https://github.com/pycqa/flake8 hooks:
rev: 4.0.1 - id: flake8
hooks: additional_dependencies:
- id: flake8 - flake8-annotations~=2.0
additional_dependencies: #- flake8-bandit # Uncomment once works again
- flake8-annotations~=2.0 - flake8-docstrings~=1.5
#- flake8-bandit # Uncomment once works again - flake8-bugbear
- flake8-docstrings~=1.5 - flake8-comprehensions
- flake8-bugbear - flake8-quotes
- flake8-comprehensions - flake8-raise
- flake8-quotes - flake8-deprecated
- flake8-raise - flake8-print
- flake8-deprecated - flake8-return
- flake8-print
- flake8-return
language_version: python3.10

View file

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

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 Optional
from typing import Any, List
from beanie import Document, Link
import marshmallow as ma from pydantic import BaseModel, Field
from umongo import Document, EmbeddedDocument, fields
from jarvis_core.db.models.actions import Ban, Kick, Mute, Unban, Warning
from jarvis_core.db import CTC2_INST, JARVIS_INST from jarvis_core.db.models.modlog import Action, Modlog, Note
from jarvis_core.db.fields import RawField from jarvis_core.db.models.reddit import Subreddit, SubredditFollow
from jarvis_core.db.models.actions import * from jarvis_core.db.models.twitter import TwitterAccount, TwitterFollow
from jarvis_core.db.models.backups import * from jarvis_core.db.utils import NowField
from jarvis_core.db.models.mastodon import *
from jarvis_core.db.models.modlog import * __all__ = [
from jarvis_core.db.models.reddit import * "Action",
from jarvis_core.db.models.twitter import * "Autopurge",
from jarvis_core.db.utils import get_now "Autoreact",
"Ban",
"Config",
@JARVIS_INST.register "Filter",
class Autopurge(Document): "Guess",
guild: int = fields.IntegerField(required=True) "Kick",
channel: int = fields.IntegerField(required=True) "Lock",
delay: int = fields.IntegerField(default=30) "Lockdown",
admin: int = fields.IntegerField(required=True) "Modlog",
created_at: datetime = fields.AwareDateTimeField(default=get_now) "Mute",
"Note",
"Pin",
@JARVIS_INST.register "Pinboard",
class Autoreact(Document): "Phishlist",
guild: int = fields.IntegerField(required=True) "Purge",
channel: int = fields.IntegerField(required=True) "Reminder",
reactions: List[str] = fields.ListField(fields.StringField()) "Rolegiver",
admin: int = fields.IntegerField(required=True) "Bypass",
thread: bool = fields.BooleanField(default=True) "Roleping",
created_at: datetime = fields.AwareDateTimeField(default=get_now) "Setting",
"Subreddit",
"SubredditFollow",
@JARVIS_INST.register "Tag",
class Config(Document): "Temprole",
"""Config database object.""" "TwitterAccount",
"TwitterFollow",
key: str = fields.StringField(required=True) "Unban",
value: Any = RawField(required=True) "UserSetting",
"Warning",
"all_models",
@JARVIS_INST.register ]
class Filter(Document):
"""Regex Filter database object."""
class Autopurge(Document):
def _validate_filters(value): guild: int
for v in value: channel: int
try: delay: int = 30
re.compile(v) admin: int
except re.error: created_at: datetime = NowField()
raise ValueError(f"Invalid regex: {v}")
guild: int = fields.IntegerField(required=True) class Autoreact(Document):
name: str = fields.StringField(required=True) guild: int
filters: List[str] = fields.ListField(fields.StringField(), validate=[_validate_filters]) channel: int
reactions: list[str] = Field(default_factory=list)
admin: int
@CTC2_INST.register thread: bool
class Guess(Document): created_at: datetime = NowField()
"""Guess database object."""
correct: bool = fields.BooleanField(default=False) class Config(Document):
guess: str = fields.StringField(required=True) """Config database object."""
user: int = fields.IntegerField(required=True)
key: str
value: str | int | bool
@JARVIS_INST.register
class Permission(EmbeddedDocument):
"""Embedded Permissions document.""" class Filter(Document):
"""Filter database object."""
id: int = fields.IntegerField(required=True)
allow: int = fields.IntegerField(default=0) guild: int
deny: int = fields.IntegerField(default=0) name: str
filters: list[str] = Field(default_factory=list)
@JARVIS_INST.register
class Lock(Document): class Guess(Document):
"""Lock database object.""" """Guess database object."""
active: bool = fields.BooleanField(default=True) correct: bool
admin: int = fields.IntegerField(required=True) guess: str
channel: int = fields.IntegerField(required=True) user: int
duration: int = fields.IntegerField(default=10)
guild: int = fields.IntegerField(required=True)
reason: str = fields.StringField(required=True) class Permission(BaseModel):
original_perms: Permission = fields.EmbeddedField(Permission, required=False) """Embedded Permissions document."""
created_at: datetime = fields.AwareDateTimeField(default=get_now)
id: int
allow: int = 0
@JARVIS_INST.register deny: int = 0
class Lockdown(Document):
"""Lockdown database object."""
class Lock(Document):
active: bool = fields.BooleanField(default=True) """Lock database object."""
admin: int = fields.IntegerField(required=True)
duration: int = fields.IntegerField(default=10) active: bool = True
guild: int = fields.IntegerField(required=True) admin: int
reason: str = fields.StringField(required=True) channel: int
original_perms: int = fields.IntegerField(required=True) duration: int = 10
created_at: datetime = fields.AwareDateTimeField(default=get_now) reason: str
original_perms: Permission
created_at: datetime = NowField()
@JARVIS_INST.register
class Event(Document):
"""Event Meetup Object.""" class Lockdown(Document):
"""Lockdown database object."""
user: int = fields.IntegerField(required=True)
going: bool = fields.BooleanField(required=True) active: bool = True
travel_method: str = fields.StringField() admin: int
before_flight: str = fields.StringField() duration: int = 10
before_arrival_time: datetime = fields.AwareDateTimeField() guild: int
before_departure_time: datetime = fields.AwareDateTimeField() reason: str
after_flight: str = fields.StringField() original_perms: int
after_arrival_time: datetime = fields.AwareDateTimeField() created_at: datetime = NowField()
after_departure_time: datetime = fields.AwareDateTimeField()
hotel: str = fields.StringField()
event_name: str = fields.StringField() class Purge(Document):
"""Purge database object."""
@JARVIS_INST.register admin: int
class Phishlist(Document): channel: int
"""Phishing safelist.""" guild: int
count_: int = Field(10, alias="count")
url: str = fields.StringField(required=True) created_at: datetime = NowField()
confirmed: bool = fields.BooleanField(default=False)
valid: bool = fields.BooleanField(default=True)
created_at: datetime = fields.AwareDateTimeField(default=get_now) class Reminder(Document):
"""Reminder database object."""
@JARVIS_INST.register active: bool = True
class Purge(Document): user: int
"""Purge database object.""" guild: int
channel: int
admin: int = fields.IntegerField(required=True) message: str
channel: int = fields.IntegerField(required=True) remind_at: datetime
guild: int = fields.IntegerField(required=True) created_at: datetime = NowField()
count: int = fields.IntegerField(default=10) repeat: Optional[str] = None
created_at: datetime = fields.AwareDateTimeField(default=get_now) timezone: str = "UTC"
total_reminders: int = 0
parent: Optional[str] = None
@JARVIS_INST.register private: bool = False
class Reminder(Document):
"""Reminder database object."""
class Rolegiver(Document):
active: bool = fields.BooleanField(default=True) """Rolegiver database object."""
user: int = fields.IntegerField(required=True)
guild: int = fields.IntegerField(required=True) guild: int
channel: int = fields.IntegerField(required=True) roles: list[int]
message: str = fields.StringField(required=True) group: Optional[str] = None
remind_at: datetime = fields.AwareDateTimeField(required=True)
created_at: datetime = fields.AwareDateTimeField(default=get_now)
private: bool = fields.BooleanField(default=False) class Bypass(BaseModel):
"""Roleping bypass embedded object."""
@JARVIS_INST.register users: list[int]
class Rolegiver(Document): roles: list[int]
"""Rolegiver database object."""
guild: int = fields.IntegerField(required=True) class Roleping(Document):
roles: List[int] = fields.ListField(fields.IntegerField()) """Roleping database object."""
active: bool = True
@JARVIS_INST.register role: int
class Bypass(EmbeddedDocument): guild: int
"""Roleping bypass embedded object.""" admin: int
bypass: Bypass
users: List[int] = fields.ListField(fields.IntegerField()) created_at: datetime = NowField()
roles: List[int] = fields.ListField(fields.IntegerField())
class Setting(Document):
@JARVIS_INST.register """Setting database object."""
class Roleping(Document):
"""Roleping database object.""" guild: int
setting: str
active: bool = fields.BooleanField(default=True) value: str | int | bool | list[int | str]
role: int = fields.IntegerField(required=True)
guild: int = fields.IntegerField(required=True)
admin: int = fields.IntegerField(required=True) class Phishlist(Document):
bypass: Bypass = fields.EmbeddedField(Bypass) """Phishlist database object."""
created_at: datetime = fields.AwareDateTimeField(default=get_now)
url: str
confirmed: bool = False
@JARVIS_INST.register valid: bool = True
class Setting(Document): created_at: datetime = NowField()
"""Setting database object."""
guild: int = fields.IntegerField(required=True) class Pinboard(Document):
setting: str = fields.StringField(required=True) """Pinboard database object."""
value: Any = RawField()
channel: int
guild: int
@JARVIS_INST.register admin: int
class Star(Document): created_at: datetime = NowField()
"""Star database object."""
active: bool = fields.BooleanField(default=True) class Pin(Document):
index: int = fields.IntegerField(required=True) """Pin database object."""
message: int = fields.IntegerField(required=True)
channel: int = fields.IntegerField(required=True) active: bool = True
starboard: int = fields.IntegerField(required=True) index: int
guild: int = fields.IntegerField(required=True) message: int
admin: int = fields.IntegerField(required=True) channel: int
star: int = fields.IntegerField(required=True) pinboard: Link[Pinboard]
created_at: datetime = fields.AwareDateTimeField(default=get_now) guild: int
admin: int
pin: int
@JARVIS_INST.register created_at: datetime = NowField()
class Starboard(Document):
"""Starboard database object."""
class Tag(Document):
channel: int = fields.IntegerField(required=True) """Tag database object."""
guild: int = fields.IntegerField(required=True)
admin: int = fields.IntegerField(required=True) creator: int
created_at: datetime = fields.AwareDateTimeField(default=get_now) name: str
content: str
guild: int
@JARVIS_INST.register created_at: datetime = NowField()
class Tag(Document): edited_at: Optional[datetime] = None
"""Tag database object.""" editor: Optional[int] = None
creator: int = fields.IntegerField(required=True)
created_at: datetime = fields.AwareDateTimeField(default=get_now) class Temprole(Document):
editor: int = fields.IntegerField() """Temporary role object."""
edited_at: datetime = fields.AwareDateTimeField()
name: str = fields.StringField(required=True) guild: int
content: str = fields.StringField(required=True) user: int
guild: int = fields.IntegerField(required=True) role: int
admin: int
expires_at: datetime
@JARVIS_INST.register reapply_on_rejoin: bool = True
class Temprole(Document): created_at: datetime = NowField()
"""Temporary role object."""
guild: int = fields.IntegerField(required=True) class UserSetting(Document):
user: int = fields.IntegerField(required=True) """User Setting object."""
role: int = fields.IntegerField(required=True)
admin: int = fields.IntegerField(required=True) user: int
expires_at: datetime = fields.AwareDateTimeField(required=True) type: str
created_at: datetime = fields.AwareDateTimeField(default=get_now) setting: str
value: str | int | bool
@JARVIS_INST.register
class UserSetting(Document): all_models = [
"""User Setting object.""" Autopurge,
Autoreact,
user: int = fields.IntegerField(required=True) Ban,
type: str = fields.StringField(required=True) Config,
setting: str = fields.StringField(required=True) Filter,
value: Any = RawField() Guess,
Kick,
class Meta: Lock,
collection_name = "usersetting" 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"
@ -12,4 +14,8 @@ 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,27 +1,30 @@
[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]
pytest = "^7.1" [tool.poetry.dev-dependencies]
ipython = "^8.5.0" pytest = "^7.1"
rich = "^12.6.0"
black = {version = "^22.10.0", allow-prereleases = true} [tool.poetry.group.dev.dependencies]
black = "^23.1.0"
[build-system] ipython = "^8.5.0"
requires = ["poetry-core>=1.0.0"] rich = "^12.6.0"
build-backend = "poetry.core.masonry.api"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"