mirror of
https://github.com/infinition/Bjorn.git
synced 2026-03-19 10:10:24 +00:00
feat: Add login page with dynamic RGB effects and password toggle functionality
feat: Implement package management utilities with JSON endpoints for listing and uninstalling packages feat: Create plugin management utilities with endpoints for listing, configuring, and installing plugins feat: Develop schedule and trigger management utilities with CRUD operations for schedules and triggers
This commit is contained in:
137
db_utils/plugins.py
Normal file
137
db_utils/plugins.py
Normal file
@@ -0,0 +1,137 @@
|
||||
"""plugins.py - Plugin configuration and hook tracking operations."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from logger import Logger
|
||||
|
||||
logger = Logger(name="db_utils.plugins", level=logging.DEBUG)
|
||||
|
||||
|
||||
class PluginOps:
|
||||
"""Plugin configuration and hook registration operations."""
|
||||
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
|
||||
def create_tables(self):
|
||||
"""Create plugin_configs and plugin_hooks tables."""
|
||||
|
||||
self.base.execute("""
|
||||
CREATE TABLE IF NOT EXISTS plugin_configs (
|
||||
plugin_id TEXT PRIMARY KEY,
|
||||
enabled INTEGER DEFAULT 1,
|
||||
config_json TEXT DEFAULT '{}',
|
||||
meta_json TEXT DEFAULT '{}',
|
||||
installed_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TEXT DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
""")
|
||||
|
||||
self.base.execute("""
|
||||
CREATE TABLE IF NOT EXISTS plugin_hooks (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
plugin_id TEXT NOT NULL,
|
||||
hook_name TEXT NOT NULL,
|
||||
UNIQUE(plugin_id, hook_name),
|
||||
FOREIGN KEY (plugin_id) REFERENCES plugin_configs(plugin_id)
|
||||
ON DELETE CASCADE
|
||||
);
|
||||
""")
|
||||
|
||||
self.base.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_plugin_hooks_hook "
|
||||
"ON plugin_hooks(hook_name);"
|
||||
)
|
||||
|
||||
logger.debug("Plugin tables created/verified")
|
||||
|
||||
# ── Config CRUD ──────────────────────────────────────────────────
|
||||
|
||||
def get_plugin_config(self, plugin_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get plugin config row. Returns dict with parsed config_json and meta."""
|
||||
row = self.base.query_one(
|
||||
"SELECT * FROM plugin_configs WHERE plugin_id=?;", (plugin_id,)
|
||||
)
|
||||
if row:
|
||||
try:
|
||||
row["config"] = json.loads(row.get("config_json") or "{}")
|
||||
except Exception:
|
||||
row["config"] = {}
|
||||
try:
|
||||
row["meta"] = json.loads(row.get("meta_json") or "{}")
|
||||
except Exception:
|
||||
row["meta"] = {}
|
||||
return row
|
||||
|
||||
def save_plugin_config(self, plugin_id: str, config: dict) -> None:
|
||||
"""Update config_json for a plugin."""
|
||||
self.base.execute("""
|
||||
UPDATE plugin_configs
|
||||
SET config_json = ?, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE plugin_id = ?;
|
||||
""", (json.dumps(config, ensure_ascii=False), plugin_id))
|
||||
|
||||
def upsert_plugin(self, plugin_id: str, enabled: int, config: dict, meta: dict) -> None:
|
||||
"""Insert or update a plugin record."""
|
||||
self.base.execute("""
|
||||
INSERT INTO plugin_configs (plugin_id, enabled, config_json, meta_json)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(plugin_id) DO UPDATE SET
|
||||
enabled = excluded.enabled,
|
||||
meta_json = excluded.meta_json,
|
||||
updated_at = CURRENT_TIMESTAMP;
|
||||
""", (plugin_id, enabled, json.dumps(config, ensure_ascii=False),
|
||||
json.dumps(meta, ensure_ascii=False)))
|
||||
|
||||
def delete_plugin(self, plugin_id: str) -> None:
|
||||
"""Delete plugin and its hooks (CASCADE)."""
|
||||
self.base.execute("DELETE FROM plugin_configs WHERE plugin_id=?;", (plugin_id,))
|
||||
|
||||
def list_plugins(self) -> List[Dict[str, Any]]:
|
||||
"""List all registered plugins."""
|
||||
rows = self.base.query("SELECT * FROM plugin_configs ORDER BY plugin_id;")
|
||||
for r in rows:
|
||||
try:
|
||||
r["config"] = json.loads(r.get("config_json") or "{}")
|
||||
except Exception:
|
||||
r["config"] = {}
|
||||
try:
|
||||
r["meta"] = json.loads(r.get("meta_json") or "{}")
|
||||
except Exception:
|
||||
r["meta"] = {}
|
||||
return rows
|
||||
|
||||
def set_plugin_enabled(self, plugin_id: str, enabled: bool) -> None:
|
||||
"""Toggle plugin enabled state."""
|
||||
self.base.execute(
|
||||
"UPDATE plugin_configs SET enabled=?, updated_at=CURRENT_TIMESTAMP WHERE plugin_id=?;",
|
||||
(1 if enabled else 0, plugin_id)
|
||||
)
|
||||
|
||||
# ── Hook CRUD ────────────────────────────────────────────────────
|
||||
|
||||
def set_plugin_hooks(self, plugin_id: str, hooks: List[str]) -> None:
|
||||
"""Replace all hooks for a plugin."""
|
||||
with self.base.transaction():
|
||||
self.base.execute("DELETE FROM plugin_hooks WHERE plugin_id=?;", (plugin_id,))
|
||||
for h in hooks:
|
||||
self.base.execute(
|
||||
"INSERT OR IGNORE INTO plugin_hooks(plugin_id, hook_name) VALUES(?,?);",
|
||||
(plugin_id, h)
|
||||
)
|
||||
|
||||
def get_hooks_for_event(self, hook_name: str) -> List[str]:
|
||||
"""Get all plugin_ids subscribed to a given hook."""
|
||||
rows = self.base.query(
|
||||
"SELECT plugin_id FROM plugin_hooks WHERE hook_name=?;", (hook_name,)
|
||||
)
|
||||
return [r["plugin_id"] for r in rows]
|
||||
|
||||
def get_hooks_for_plugin(self, plugin_id: str) -> List[str]:
|
||||
"""Get all hooks a plugin subscribes to."""
|
||||
rows = self.base.query(
|
||||
"SELECT hook_name FROM plugin_hooks WHERE plugin_id=?;", (plugin_id,)
|
||||
)
|
||||
return [r["hook_name"] for r in rows]
|
||||
Reference in New Issue
Block a user