|
@@ -3,6 +3,8 @@ from typing import Union
|
|
|
from functools import wraps
|
|
|
import inspect
|
|
|
import asyncio
|
|
|
+import dataclasses
|
|
|
+import json
|
|
|
|
|
|
from ..types import (
|
|
|
Message,
|
|
@@ -103,3 +105,48 @@ def get_command_config() -> CommandConfiguration:
|
|
|
startup=decorated_startup,
|
|
|
shutdown=decorated_shutdown,
|
|
|
)
|
|
|
+
|
|
|
+
|
|
|
+def as_data(cls):
|
|
|
+ table_name = "".join(("_" + c.lower()) if "A" <= c <= "Z" else c for c in cls.__name__).strip("_")
|
|
|
+
|
|
|
+ columns = [
|
|
|
+ "key TEXT NOT NULL PRIMARY KEY",
|
|
|
+ 'body TEXT DEFAULT ""',
|
|
|
+ ]
|
|
|
+ queries = {}
|
|
|
+
|
|
|
+ for k, v in cls.__annotations__.items():
|
|
|
+ if v == int:
|
|
|
+ t = "INT"
|
|
|
+ elif v == float:
|
|
|
+ t = "REAL"
|
|
|
+ elif v == str:
|
|
|
+ t = "TEXT"
|
|
|
+ else:
|
|
|
+ continue
|
|
|
+ columns.append(f"__{k} {t} GENERATED ALWAYS AS (json_extract(body, '$.{k}')) VIRTUAL")
|
|
|
+ queries[k] = f"SELECT body FROM {table_name} WHERE __{k} = ?"
|
|
|
+
|
|
|
+ create_query = f"CREATE TABLE IF NOT EXISTS {table_name} ({', '.join(columns)})"
|
|
|
+
|
|
|
+ @on_startup
|
|
|
+ async def create_table(context: Context):
|
|
|
+ async with context.database() as db:
|
|
|
+ await db.execute(create_query)
|
|
|
+ await db.commit()
|
|
|
+
|
|
|
+ new_class = type(
|
|
|
+ cls.__name__,
|
|
|
+ (dataclasses.dataclass(cls),),
|
|
|
+ dict(
|
|
|
+ __field_queries=queries,
|
|
|
+ __create_query=create_query,
|
|
|
+ __select_query=f"SELECT body FROM {table_name} WHERE key=:key",
|
|
|
+ __save_query=f"INSERT INTO {table_name} VALUES (:key, :body) ON CONFLICT(key) DO UPDATE SET body=:body",
|
|
|
+ __to_blob=lambda self: json.dumps(dataclasses.asdict(self)),
|
|
|
+ __from_blob=staticmethod(lambda blob: new_class(**json.loads(blob)))
|
|
|
+ ),
|
|
|
+ )
|
|
|
+
|
|
|
+ return new_class
|