Files
HyperNode-AI/app/services/registry.py
T
dekun 2bbdb00a4d 初始化 HyperNode-AI 控制面。
包含节点账本、每日清算,以及 Ubuntu 交互式部署脚本。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-10 21:53:20 +08:00

75 lines
2.3 KiB
Python

"""用户与节点登记。"""
from __future__ import annotations
from decimal import Decimal
from urllib.parse import urlparse
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session
from app.clock import add_months, utcnow
from app.config import settings
from app.errors import AppError
from app.models import ComputeNode, NodeStatus, User
from app.money import money
from app.services.common import get_user_by_wallet
def register_user(session: Session, wallet_address: str) -> User:
wallet = wallet_address.strip()
if session.scalar(select(User).where(User.wallet_address == wallet)) is not None:
raise AppError("钱包地址已注册", 409)
user = User(wallet_address=wallet, created_at=utcnow())
session.add(user)
try:
session.flush()
except IntegrityError as exc:
session.rollback()
raise AppError("钱包地址已注册", 409) from exc
return user
def register_node(
session: Session,
wallet_address: str,
sn: str,
purchase_amount: Decimal,
callback_url: str | None = None,
) -> ComputeNode:
user = get_user_by_wallet(session, wallet_address.strip())
serial = sn.strip()
if session.scalar(select(ComputeNode).where(ComputeNode.sn == serial)) is not None:
raise AppError("节点序列号已存在", 409)
callback = _normalize_callback(callback_url)
started = utcnow()
node = ComputeNode(
user_id=user.id,
sn=serial,
purchase_amount=money(purchase_amount),
license_months=settings.license_months,
licensed_at=started,
license_expires_at=add_months(started, settings.license_months),
status=NodeStatus.OFFLINE,
callback_url=callback,
created_at=started,
updated_at=started,
)
session.add(node)
try:
session.flush()
except IntegrityError as exc:
session.rollback()
raise AppError("节点序列号已存在", 409) from exc
return node
def _normalize_callback(callback_url: str | None) -> str | None:
if callback_url is None or callback_url.strip() == "":
return None
parsed = urlparse(callback_url.strip())
if parsed.scheme not in {"http", "https"} or not parsed.netloc:
raise AppError("callback_url 必须是 http 或 https 地址")
return callback_url.strip()