Files
crypto_okx_hub/lib/instances_lib.py
T

157 lines
4.4 KiB
Python

"""客户端实例 CRUD."""
from __future__ import annotations
from datetime import datetime
from typing import Any, Optional
from urllib.parse import urlparse
from lib.db_lib import get_db, row_to_dict
def _now() -> str:
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def normalize_base_url(url: str) -> str:
u = (url or "").strip().rstrip("/")
if not u:
return ""
if "://" not in u:
u = "https://" + u
parsed = urlparse(u)
if not parsed.netloc:
return ""
return f"{parsed.scheme}://{parsed.netloc}"
def list_instances(*, enabled_only: bool = False) -> list[dict[str, Any]]:
conn = get_db()
try:
if enabled_only:
rows = conn.execute(
"SELECT * FROM hub_instances WHERE enabled=1 ORDER BY sort_order ASC, id ASC"
).fetchall()
else:
rows = conn.execute(
"SELECT * FROM hub_instances ORDER BY sort_order ASC, id ASC"
).fetchall()
return [row_to_dict(r) for r in rows if r]
finally:
conn.close()
def get_instance(iid: int) -> Optional[dict[str, Any]]:
conn = get_db()
try:
row = conn.execute("SELECT * FROM hub_instances WHERE id=?", (int(iid),)).fetchone()
return row_to_dict(row)
finally:
conn.close()
def create_instance(
*,
name: str,
base_url: str,
bridge_token: str,
embed_path: str = "/embed",
tags: str = "",
enabled: bool = True,
sort_order: int = 0,
) -> tuple[Optional[dict[str, Any]], str]:
name = (name or "").strip()
token = (bridge_token or "").strip()
base = normalize_base_url(base_url)
path = (embed_path or "/embed").strip() or "/embed"
if not path.startswith("/"):
path = "/" + path
if not name:
return None, "名称不能为空"
if not base:
return None, "公网 URL 无效"
if not token:
return None, "Bridge Token 不能为空"
now = _now()
conn = get_db()
try:
cur = conn.execute(
"""
INSERT INTO hub_instances(
name, base_url, bridge_token, embed_path, tags, enabled, sort_order, created_at, updated_at
) VALUES (?,?,?,?,?,?,?,?,?)
""",
(
name,
base,
token,
path,
(tags or "").strip(),
1 if enabled else 0,
int(sort_order or 0),
now,
now,
),
)
conn.commit()
return get_instance(int(cur.lastrowid)), ""
finally:
conn.close()
def update_instance(iid: int, **fields: Any) -> tuple[Optional[dict[str, Any]], str]:
existing = get_instance(iid)
if not existing:
return None, "实例不存在"
name = fields.get("name", existing["name"])
base_url = fields.get("base_url", existing["base_url"])
token = fields.get("bridge_token", existing["bridge_token"])
embed_path = fields.get("embed_path", existing["embed_path"])
tags = fields.get("tags", existing.get("tags") or "")
enabled = fields.get("enabled", existing["enabled"])
sort_order = fields.get("sort_order", existing["sort_order"])
name = (name or "").strip()
token = (token or "").strip()
base = normalize_base_url(str(base_url))
path = (str(embed_path) or "/embed").strip() or "/embed"
if not path.startswith("/"):
path = "/" + path
if not name or not base or not token:
return None, "名称 / URL / Token 均必填"
conn = get_db()
try:
conn.execute(
"""
UPDATE hub_instances SET
name=?, base_url=?, bridge_token=?, embed_path=?, tags=?,
enabled=?, sort_order=?, updated_at=?
WHERE id=?
""",
(
name,
base,
token,
path,
(tags or "").strip(),
1 if bool(int(enabled)) else 0,
int(sort_order or 0),
_now(),
int(iid),
),
)
conn.commit()
return get_instance(iid), ""
finally:
conn.close()
def delete_instance(iid: int) -> bool:
conn = get_db()
try:
cur = conn.execute("DELETE FROM hub_instances WHERE id=?", (int(iid),))
conn.commit()
return cur.rowcount > 0
finally:
conn.close()