fixes: #216 Squashed: Update astrbot/core/config/default.py 描述更正. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> 🎨 style: clean up 🐛 fix: 修复安全设置参数的默认值为列表
113 lines
3.7 KiB
Python
113 lines
3.7 KiB
Python
import json
|
|
import aiosqlite
|
|
import os
|
|
from typing import Any
|
|
from .plugin_storage import PluginStorage
|
|
|
|
DBPATH = "data/plugin_data/sqlite/plugin_data.db"
|
|
|
|
|
|
class SQLitePluginStorage(PluginStorage):
|
|
"""插件数据的 SQLite 存储实现类。
|
|
|
|
该类提供异步方式将插件数据存储到 SQLite 数据库中,支持数据的增删改查操作。
|
|
所有数据以 (plugin, key) 作为复合主键进行索引。
|
|
"""
|
|
|
|
_instance = None # Standalone instance of the class
|
|
_db_conn = None
|
|
db_path = None
|
|
|
|
def __new__(cls):
|
|
"""
|
|
创建或获取 SQLitePluginStorage 的单例实例。
|
|
如果实例已存在,则返回现有实例;否则创建一个新实例。
|
|
数据在 `data/plugin_data/sqlite/plugin_data.db` 下。
|
|
"""
|
|
os.makedirs(os.path.dirname(DBPATH), exist_ok=True)
|
|
if cls._instance is None:
|
|
cls._instance = super(SQLitePluginStorage, cls).__new__(cls)
|
|
cls._instance.db_path = DBPATH
|
|
return cls._instance
|
|
|
|
async def _init_db(self):
|
|
"""初始化数据库连接(只执行一次)"""
|
|
if SQLitePluginStorage._db_conn is None:
|
|
SQLitePluginStorage._db_conn = await aiosqlite.connect(self.db_path)
|
|
await self._setup_db()
|
|
|
|
async def _setup_db(self):
|
|
"""
|
|
异步初始化数据库。
|
|
|
|
创建插件数据表,如果表不存在则创建,表结构包含 plugin、key 和 value 字段,
|
|
其中 plugin 和 key 组合作为主键。
|
|
"""
|
|
await self._db_conn.execute("""
|
|
CREATE TABLE IF NOT EXISTS plugin_data (
|
|
plugin TEXT,
|
|
key TEXT,
|
|
value TEXT,
|
|
PRIMARY KEY (plugin, key)
|
|
)
|
|
""")
|
|
await self._db_conn.commit()
|
|
|
|
async def set(self, plugin: str, key: str, value: Any):
|
|
"""
|
|
异步存储数据。
|
|
|
|
将指定插件的键值对存入数据库,如果键已存在则更新值。
|
|
值会被序列化为 JSON 字符串后存储。
|
|
|
|
Args:
|
|
plugin: 插件标识符
|
|
key: 数据键名
|
|
value: 要存储的数据值(任意类型,将被 JSON 序列化)
|
|
"""
|
|
await self._init_db()
|
|
await self._db_conn.execute(
|
|
"INSERT INTO plugin_data (plugin, key, value) VALUES (?, ?, ?) "
|
|
"ON CONFLICT(plugin, key) DO UPDATE SET value = excluded.value",
|
|
(plugin, key, json.dumps(value)),
|
|
)
|
|
await self._db_conn.commit()
|
|
|
|
async def get(self, plugin: str, key: str) -> Any:
|
|
"""
|
|
异步获取数据。
|
|
|
|
从数据库中获取指定插件和键名对应的值,
|
|
返回的值会从 JSON 字符串反序列化为原始数据类型。
|
|
|
|
Args:
|
|
plugin: 插件标识符
|
|
key: 数据键名
|
|
|
|
Returns:
|
|
Any: 存储的数据值,如果未找到则返回 None
|
|
"""
|
|
await self._init_db()
|
|
async with self._db_conn.execute(
|
|
"SELECT value FROM plugin_data WHERE plugin = ? AND key = ?",
|
|
(plugin, key),
|
|
) as cursor:
|
|
row = await cursor.fetchone()
|
|
return json.loads(row[0]) if row else None
|
|
|
|
async def delete(self, plugin: str, key: str):
|
|
"""
|
|
异步删除数据。
|
|
|
|
从数据库中删除指定插件和键名对应的数据项。
|
|
|
|
Args:
|
|
plugin: 插件标识符
|
|
key: 要删除的数据键名
|
|
"""
|
|
await self._init_db()
|
|
await self._db_conn.execute(
|
|
"DELETE FROM plugin_data WHERE plugin = ? AND key = ?", (plugin, key)
|
|
)
|
|
await self._db_conn.commit()
|