137 lines
4.5 KiB
Python
137 lines
4.5 KiB
Python
# ///
|
|
# models.py
|
|
# 描述:数据库模型,使用 SQLAlchemy ORM
|
|
# 作者:AI Generated
|
|
# 创建日期:2026-04-05
|
|
# ///
|
|
|
|
from sqlalchemy import create_engine, Column, String, Boolean, Integer, DateTime, Text
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy.orm import sessionmaker
|
|
from datetime import datetime
|
|
import pytz
|
|
|
|
Base = declarative_base()
|
|
|
|
_asia_tz = pytz.timezone('Asia/Shanghai')
|
|
|
|
|
|
def now_asia():
|
|
return datetime.now(_asia_tz)
|
|
|
|
|
|
class Node(Base):
|
|
__tablename__ = "nodes"
|
|
|
|
node_id = Column(String(50), primary_key=True)
|
|
name = Column(String(100), nullable=False)
|
|
api_url = Column(String(255), nullable=False)
|
|
api_key = Column(String(255), nullable=False)
|
|
enabled = Column(Boolean, default=True)
|
|
description = Column(Text, default="")
|
|
group = Column(String(50), default="default", name="node_group")
|
|
status = Column(String(20), default="inactive")
|
|
wechat_status = Column(String(20), default="online")
|
|
is_healthy = Column(Boolean, default=False)
|
|
health_message = Column(String(255), default="")
|
|
created_at = Column(DateTime, default=now_asia)
|
|
updated_at = Column(DateTime, default=now_asia, onupdate=now_asia)
|
|
|
|
def to_dict(self):
|
|
return {
|
|
"node_id": self.node_id,
|
|
"name": self.name,
|
|
"api_url": self.api_url,
|
|
"api_key": self.api_key,
|
|
"enabled": self.enabled,
|
|
"description": self.description,
|
|
"group": self.group,
|
|
"status": self.status,
|
|
"wechat_status": self.wechat_status,
|
|
"is_healthy": self.is_healthy,
|
|
"health_message": self.health_message,
|
|
"created_at": self.created_at.isoformat() if self.created_at else None,
|
|
"updated_at": self.updated_at.isoformat() if self.updated_at else None
|
|
}
|
|
|
|
|
|
class WebhookUrl(Base):
|
|
__tablename__ = "webhook_urls"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
name = Column(String(100), nullable=False)
|
|
url = Column(String(500), nullable=False)
|
|
format = Column(String(20), default="bark")
|
|
enabled = Column(Boolean, default=True)
|
|
event_types = Column(Text, default="")
|
|
created_at = Column(DateTime, default=now_asia)
|
|
updated_at = Column(DateTime, default=now_asia, onupdate=now_asia)
|
|
|
|
def to_dict(self):
|
|
return {
|
|
"id": self.id,
|
|
"name": self.name,
|
|
"url": self.url,
|
|
"format": self.format,
|
|
"enabled": self.enabled,
|
|
"event_types": self.event_types.split(",") if self.event_types else [],
|
|
"created_at": self.created_at.isoformat() if self.created_at else None,
|
|
"updated_at": self.updated_at.isoformat() if self.updated_at else None
|
|
}
|
|
|
|
|
|
class LogEntry(Base):
|
|
__tablename__ = "logs"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
timestamp = Column(DateTime, default=now_asia)
|
|
level = Column(String(20), nullable=False)
|
|
source = Column(String(50), nullable=False)
|
|
message = Column(Text, nullable=False)
|
|
|
|
def to_dict(self):
|
|
return {
|
|
"id": self.id,
|
|
"timestamp": self.timestamp.strftime("%Y-%m-%d %H:%M:%S") if self.timestamp else None,
|
|
"level": self.level,
|
|
"source": self.source,
|
|
"message": self.message
|
|
}
|
|
|
|
|
|
class PluginConfig(Base):
|
|
__tablename__ = "plugin_configs"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
plugin_name = Column(String(100), unique=True, nullable=False)
|
|
config_json = Column(Text, default="{}")
|
|
enabled = Column(Boolean, default=False)
|
|
created_at = Column(DateTime, default=now_asia)
|
|
updated_at = Column(DateTime, default=now_asia, onupdate=now_asia)
|
|
|
|
def to_dict(self):
|
|
import json
|
|
return {
|
|
"id": self.id,
|
|
"plugin_name": self.plugin_name,
|
|
"config": json.loads(self.config_json) if self.config_json else {},
|
|
"enabled": self.enabled,
|
|
"created_at": self.created_at.isoformat() if self.created_at else None,
|
|
"updated_at": self.updated_at.isoformat() if self.updated_at else None
|
|
}
|
|
|
|
|
|
class DatabaseManager:
|
|
def __init__(self, database_url: str):
|
|
self.engine = create_engine(database_url, echo=False, pool_pre_ping=True)
|
|
self.SessionLocal = sessionmaker(bind=self.engine)
|
|
|
|
def create_tables(self):
|
|
Base.metadata.create_all(self.engine)
|
|
|
|
def get_session(self):
|
|
return self.SessionLocal()
|
|
|
|
def close(self):
|
|
self.engine.dispose()
|