路由与数据表优化
This commit is contained in:
352
models/model.py
352
models/model.py
@@ -1,215 +1,251 @@
|
|||||||
from datetime import datetime
|
from sqlalchemy import (
|
||||||
from sqlalchemy import Column, Integer, String, Text, BigInteger, Boolean, DateTime, ForeignKey
|
Column, Integer, String, Text, BigInteger, Boolean, DateTime,
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
ForeignKey, func, text, UniqueConstraint
|
||||||
|
)
|
||||||
|
from sqlalchemy.orm import declarative_base
|
||||||
|
|
||||||
Base = declarative_base()
|
Base = declarative_base()
|
||||||
|
|
||||||
class BaseModel(Base):
|
class BaseModel(Base):
|
||||||
__abstract__ = True
|
__abstract__ = True
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, comment="主键ID")
|
||||||
created_at = Column(DateTime, default=datetime.now)
|
|
||||||
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
created_at = Column(
|
||||||
deleted_at = Column(DateTime, nullable=True)
|
DateTime,
|
||||||
|
server_default=func.now(),
|
||||||
|
comment="创建时间"
|
||||||
|
)
|
||||||
|
|
||||||
|
updated_at = Column(
|
||||||
|
DateTime,
|
||||||
|
server_default=func.now(),
|
||||||
|
onupdate=func.now(),
|
||||||
|
server_onupdate=func.now(),
|
||||||
|
comment="更新时间"
|
||||||
|
)
|
||||||
|
|
||||||
|
deleted_at = Column(DateTime, nullable=True, comment="软删除时间")
|
||||||
|
|
||||||
class Download(BaseModel):
|
class Download(BaseModel):
|
||||||
__tablename__ = 'downloads'
|
__tablename__ = 'downloads'
|
||||||
|
|
||||||
status = Column(Integer, nullable=True)
|
status = Column(Integer, nullable=False, server_default='0', comment="下载状态: 0=进行中, 1=完成, 2=错误")
|
||||||
type = Column(Integer, nullable=True)
|
type = Column(Integer, nullable=False, server_default='0', comment="任务类型")
|
||||||
source = Column(Text, nullable=True)
|
source = Column(Text, nullable=False, comment="来源URL或标识")
|
||||||
total_size = Column(BigInteger, nullable=True)
|
total_size = Column(BigInteger, nullable=False, server_default='0', comment="总大小(字节)")
|
||||||
downloaded_size = Column(BigInteger, nullable=True)
|
downloaded_size = Column(BigInteger, nullable=False, server_default='0', comment="已下载大小(字节)")
|
||||||
g_id = Column(Text, nullable=True)
|
g_id = Column(Text, index=True, comment="Aria2 GID") # GID经常用于查询,建议索引
|
||||||
speed = Column(Integer, nullable=True)
|
speed = Column(Integer, nullable=False, server_default='0', comment="下载速度 (bytes/s)")
|
||||||
parent = Column(Text, nullable=True)
|
parent = Column(Text, comment="父任务标识")
|
||||||
attrs = Column(Text, nullable=True)
|
attrs = Column(Text, comment="额外属性 (JSON格式)")
|
||||||
error = Column(Text, nullable=True)
|
error = Column(Text, comment="错误信息")
|
||||||
dst = Column(Text, nullable=True)
|
dst = Column(Text, nullable=False, comment="目标存储路径")
|
||||||
user_id = Column(Integer, nullable=True)
|
|
||||||
task_id = Column(Integer, nullable=True)
|
user_id = Column(Integer, ForeignKey('users.id'), nullable=False, index=True, comment="所属用户ID")
|
||||||
node_id = Column(Integer, nullable=True)
|
task_id = Column(Integer, ForeignKey('tasks.id'), nullable=True, index=True, comment="关联的任务ID")
|
||||||
|
node_id = Column(Integer, ForeignKey('nodes.id'), nullable=False, index=True, comment="执行下载的节点ID")
|
||||||
|
|
||||||
class File(BaseModel):
|
class File(BaseModel):
|
||||||
__tablename__ = 'files'
|
__tablename__ = 'files'
|
||||||
|
|
||||||
name = Column(String(255), nullable=True)
|
name = Column(String(255), nullable=False, comment="文件名")
|
||||||
source_name = Column(Text, nullable=True)
|
source_name = Column(Text, comment="源文件名")
|
||||||
user_id = Column(Integer, nullable=True)
|
size = Column(BigInteger, nullable=False, server_default='0', comment="文件大小(字节)")
|
||||||
size = Column(BigInteger, nullable=True)
|
pic_info = Column(String(255), comment="图片信息(如尺寸)")
|
||||||
pic_info = Column(String(255), nullable=True)
|
upload_session_id = Column(String(255), unique=True, index=True, comment="分块上传会话ID")
|
||||||
folder_id = Column(Integer, nullable=True)
|
metadata = Column(Text, comment="文件元数据 (JSON格式)")
|
||||||
policy_id = Column(Integer, nullable=True)
|
|
||||||
upload_session_id = Column(String(255), nullable=True, unique=True)
|
user_id = Column(Integer, ForeignKey('users.id'), nullable=False, index=True, comment="所属用户ID")
|
||||||
metadata = Column(Text, nullable=True)
|
folder_id = Column(Integer, ForeignKey('folders.id'), nullable=False, index=True, comment="所在目录ID")
|
||||||
|
policy_id = Column(Integer, ForeignKey('policies.id'), nullable=False, index=True, comment="所属存储策略ID")
|
||||||
|
|
||||||
class Folder(BaseModel):
|
class Folder(BaseModel):
|
||||||
__tablename__ = 'folders'
|
__tablename__ = 'folders'
|
||||||
|
|
||||||
name = Column(String(255), nullable=True)
|
name = Column(String(255), nullable=False, comment="目录名")
|
||||||
parent_id = Column(Integer, nullable=True, index=True)
|
|
||||||
owner_id = Column(Integer, nullable=True, index=True)
|
|
||||||
policy_id = Column(Integer, nullable=True)
|
|
||||||
|
|
||||||
__table_args__ = {'uniqueConstraints': [('name', 'parent_id')]}
|
parent_id = Column(Integer, ForeignKey('folders.id'), nullable=True, index=True, comment="父目录ID")
|
||||||
|
owner_id = Column(Integer, ForeignKey('users.id'), nullable=False, index=True, comment="所有者用户ID")
|
||||||
|
policy_id = Column(Integer, ForeignKey('policies.id'), nullable=False, index=True, comment="所属存储策略ID")
|
||||||
|
|
||||||
|
__table_args__ = (
|
||||||
|
UniqueConstraint('name', 'parent_id', name='uq_folder_name_parent'),
|
||||||
|
)
|
||||||
|
|
||||||
class Group(BaseModel):
|
class Group(BaseModel):
|
||||||
__tablename__ = 'groups'
|
__tablename__ = 'groups'
|
||||||
|
|
||||||
name = Column(String(255), nullable=True)
|
name = Column(String(255), nullable=False, unique=True, comment="用户组名")
|
||||||
policies = Column(String(255), nullable=True)
|
policies = Column(String(255), comment="允许的策略ID列表,逗号分隔")
|
||||||
max_storage = Column(BigInteger, nullable=True)
|
max_storage = Column(BigInteger, nullable=False, server_default='0', comment="最大存储空间(字节)")
|
||||||
share_enabled = Column(Boolean, nullable=True)
|
|
||||||
web_dav_enabled = Column(Boolean, nullable=True)
|
share_enabled = Column(Boolean, nullable=False, server_default=text('false'), comment="是否允许创建分享")
|
||||||
speed_limit = Column(Integer, nullable=True)
|
web_dav_enabled = Column(Boolean, nullable=False, server_default=text('false'), comment="是否允许使用WebDAV")
|
||||||
options = Column(String(255), nullable=True)
|
|
||||||
|
speed_limit = Column(Integer, nullable=False, server_default='0', comment="速度限制 (KB/s), 0为不限制")
|
||||||
|
options = Column(Text, comment="其他选项 (JSON格式)")
|
||||||
|
|
||||||
class Node(BaseModel):
|
class Node(BaseModel):
|
||||||
__tablename__ = 'nodes'
|
__tablename__ = 'nodes'
|
||||||
|
|
||||||
status = Column(Integer, nullable=True)
|
status = Column(Integer, nullable=False, server_default='0', comment="节点状态: 0=正常, 1=离线")
|
||||||
name = Column(String(255), nullable=True)
|
name = Column(String(255), nullable=False, unique=True, comment="节点名称")
|
||||||
type = Column(Integer, nullable=True)
|
type = Column(Integer, nullable=False, server_default='0', comment="节点类型")
|
||||||
server = Column(String(255), nullable=True)
|
server = Column(String(255), nullable=False, comment="节点地址(IP或域名)")
|
||||||
slave_key = Column(Text, nullable=True)
|
slave_key = Column(Text, comment="从机通讯密钥")
|
||||||
master_key = Column(Text, nullable=True)
|
master_key = Column(Text, comment="主机通讯密钥")
|
||||||
aria2_enabled = Column(Boolean, nullable=True)
|
aria2_enabled = Column(Boolean, nullable=False, server_default=text('false'), comment="是否启用Aria2")
|
||||||
aria2_options = Column(Text, nullable=True)
|
aria2_options = Column(Text, comment="Aria2配置 (JSON格式)")
|
||||||
rank = Column(Integer, nullable=True)
|
rank = Column(Integer, nullable=False, server_default='0', comment="节点排序权重")
|
||||||
|
|
||||||
class Order(BaseModel):
|
class Order(BaseModel):
|
||||||
__tablename__ = 'orders'
|
__tablename__ = 'orders'
|
||||||
|
|
||||||
user_id = Column(Integer, nullable=True)
|
order_no = Column(String(255), nullable=False, unique=True, index=True, comment="订单号,唯一")
|
||||||
order_no = Column(String(255), nullable=True, index=True)
|
type = Column(Integer, nullable=False, comment="订单类型")
|
||||||
type = Column(Integer, nullable=True)
|
method = Column(String(255), comment="支付方式")
|
||||||
method = Column(String(255), nullable=True)
|
product_id = Column(BigInteger, comment="商品ID")
|
||||||
product_id = Column(BigInteger, nullable=True)
|
num = Column(Integer, nullable=False, server_default='1', comment="购买数量")
|
||||||
num = Column(Integer, nullable=True)
|
name = Column(String(255), nullable=False, comment="商品名称")
|
||||||
name = Column(String(255), nullable=True)
|
price = Column(Integer, nullable=False, server_default='0', comment="订单价格(分)")
|
||||||
price = Column(Integer, nullable=True)
|
status = Column(Integer, nullable=False, server_default='0', comment="订单状态: 0=待支付, 1=已完成, 2=已取消")
|
||||||
status = Column(Integer, nullable=True)
|
|
||||||
|
user_id = Column(Integer, ForeignKey('users.id'), nullable=False, index=True, comment="所属用户ID")
|
||||||
|
|
||||||
class Policy(BaseModel):
|
class Policy(BaseModel):
|
||||||
__tablename__ = 'policies'
|
__tablename__ = 'policies'
|
||||||
|
|
||||||
name = Column(String(255), nullable=True)
|
name = Column(String(255), nullable=False, unique=True, comment="策略名称")
|
||||||
type = Column(String(255), nullable=True)
|
type = Column(String(255), nullable=False, comment="存储类型 (e.g. 'local', 's3')")
|
||||||
server = Column(String(255), nullable=True)
|
server = Column(String(255), comment="服务器地址(本地策略为路径)")
|
||||||
bucket_name = Column(String(255), nullable=True)
|
bucket_name = Column(String(255), comment="存储桶名称")
|
||||||
is_private = Column(Boolean, nullable=True)
|
is_private = Column(Boolean, nullable=False, server_default=text('true'), comment="是否为私有空间")
|
||||||
base_url = Column(String(255), nullable=True)
|
base_url = Column(String(255), comment="访问文件的基础URL")
|
||||||
access_key = Column(Text, nullable=True)
|
access_key = Column(Text, comment="Access Key")
|
||||||
secret_key = Column(Text, nullable=True)
|
secret_key = Column(Text, comment="Secret Key")
|
||||||
max_size = Column(BigInteger, nullable=True)
|
max_size = Column(BigInteger, nullable=False, server_default='0', comment="允许上传的最大文件尺寸(字节)")
|
||||||
auto_rename = Column(Boolean, nullable=True)
|
auto_rename = Column(Boolean, nullable=False, server_default=text('false'), comment="是否自动重命名")
|
||||||
dir_name_rule = Column(String(255), nullable=True)
|
dir_name_rule = Column(String(255), comment="目录命名规则")
|
||||||
file_name_rule = Column(String(255), nullable=True)
|
file_name_rule = Column(String(255), comment="文件命名规则")
|
||||||
is_origin_link_enable = Column(Boolean, nullable=True)
|
is_origin_link_enable = Column(Boolean, nullable=False, server_default=text('false'), comment="是否开启源链接访问")
|
||||||
options = Column(Text, nullable=True)
|
options = Column(Text, comment="其他选项 (JSON格式)")
|
||||||
|
|
||||||
class Redeem(BaseModel):
|
|
||||||
__tablename__ = 'redeems'
|
|
||||||
|
|
||||||
type = Column(Integer, nullable=True)
|
|
||||||
product_id = Column(BigInteger, nullable=True)
|
|
||||||
num = Column(Integer, nullable=True)
|
|
||||||
code = Column(Text, nullable=True)
|
|
||||||
used = Column(Boolean, nullable=True)
|
|
||||||
|
|
||||||
class Report(BaseModel):
|
|
||||||
__tablename__ = 'reports'
|
|
||||||
|
|
||||||
share_id = Column(Integer, nullable=True, index=True)
|
|
||||||
reason = Column(Integer, nullable=True)
|
|
||||||
description = Column(String(255), nullable=True)
|
|
||||||
|
|
||||||
class Setting(BaseModel):
|
class Setting(BaseModel):
|
||||||
__tablename__ = 'settings'
|
__tablename__ = 'settings'
|
||||||
|
|
||||||
type = Column(String(255), nullable=False)
|
# 优化点: type和name的组合应该是唯一的
|
||||||
name = Column(String(255), nullable=False, unique=True, index=True)
|
type = Column(String(255), nullable=False, comment="设置类型/分组")
|
||||||
value = Column(Text, nullable=True)
|
name = Column(String(255), nullable=False, comment="设置项名称")
|
||||||
|
value = Column(Text, comment="设置值")
|
||||||
|
|
||||||
|
__table_args__ = (
|
||||||
|
UniqueConstraint('type', 'name', name='uq_setting_type_name'),
|
||||||
|
)
|
||||||
|
|
||||||
class Share(BaseModel):
|
class Share(BaseModel):
|
||||||
__tablename__ = 'shares'
|
__tablename__ = 'shares'
|
||||||
|
|
||||||
password = Column(String(255), nullable=True)
|
password = Column(String(255), comment="分享密码(加密后)")
|
||||||
is_dir = Column(Boolean, nullable=True)
|
is_dir = Column(Boolean, nullable=False, server_default=text('false'), comment="是否为目录分享")
|
||||||
user_id = Column(Integer, nullable=True)
|
source_id = Column(Integer, nullable=False, comment="源文件或目录的ID")
|
||||||
source_id = Column(Integer, nullable=True)
|
views = Column(Integer, nullable=False, server_default='0', comment="浏览次数")
|
||||||
views = Column(Integer, nullable=True)
|
downloads = Column(Integer, nullable=False, server_default='0', comment="下载次数")
|
||||||
downloads = Column(Integer, nullable=True)
|
remain_downloads = Column(Integer, comment="剩余下载次数 (NULL为不限制)")
|
||||||
remain_downloads = Column(Integer, nullable=True)
|
expires = Column(DateTime, comment="过期时间 (NULL为永不过期)")
|
||||||
expires = Column(DateTime, nullable=True)
|
preview_enabled = Column(Boolean, nullable=False, server_default=text('true'), comment="是否允许预览")
|
||||||
preview_enabled = Column(Boolean, nullable=True)
|
source_name = Column(String(255), index=True, comment="源名称(冗余字段,便于展示)")
|
||||||
source_name = Column(String(255), nullable=True, index=True)
|
score = Column(Integer, nullable=False, server_default='0', comment="分享评分/权重")
|
||||||
score = Column(Integer, nullable=True)
|
|
||||||
|
|
||||||
class SourceLink(BaseModel):
|
user_id = Column(Integer, ForeignKey('users.id'), nullable=False, index=True, comment="创建分享的用户ID")
|
||||||
__tablename__ = 'source_links'
|
|
||||||
|
|
||||||
file_id = Column(Integer, nullable=True)
|
|
||||||
name = Column(String(255), nullable=True)
|
|
||||||
downloads = Column(Integer, nullable=True)
|
|
||||||
|
|
||||||
class StoragePack(BaseModel):
|
|
||||||
__tablename__ = 'storage_packs'
|
|
||||||
|
|
||||||
name = Column(String(255), nullable=True)
|
|
||||||
user_id = Column(Integer, nullable=True)
|
|
||||||
active_time = Column(DateTime, nullable=True)
|
|
||||||
expired_time = Column(DateTime, nullable=True, index=True)
|
|
||||||
size = Column(BigInteger, nullable=True)
|
|
||||||
|
|
||||||
class Tag(BaseModel):
|
|
||||||
__tablename__ = 'tags'
|
|
||||||
|
|
||||||
name = Column(String(255), nullable=True)
|
|
||||||
icon = Column(String(255), nullable=True)
|
|
||||||
color = Column(String(255), nullable=True)
|
|
||||||
type = Column(Integer, nullable=True)
|
|
||||||
expression = Column(Text, nullable=True)
|
|
||||||
user_id = Column(Integer, nullable=True)
|
|
||||||
|
|
||||||
class Task(BaseModel):
|
class Task(BaseModel):
|
||||||
__tablename__ = 'tasks'
|
__tablename__ = 'tasks'
|
||||||
|
|
||||||
status = Column(Integer, nullable=True)
|
status = Column(Integer, nullable=False, server_default='0', comment="任务状态: 0=排队中, 1=处理中, 2=完成, 3=错误")
|
||||||
type = Column(Integer, nullable=True)
|
type = Column(Integer, nullable=False, comment="任务类型")
|
||||||
user_id = Column(Integer, nullable=True)
|
progress = Column(Integer, nullable=False, server_default='0', comment="任务进度 (0-100)")
|
||||||
progress = Column(Integer, nullable=True)
|
error = Column(Text, comment="错误信息")
|
||||||
error = Column(Text, nullable=True)
|
props = Column(Text, comment="任务属性 (JSON格式)")
|
||||||
props = Column(Text, nullable=True)
|
|
||||||
|
user_id = Column(Integer, ForeignKey('users.id'), nullable=False, index=True, comment="所属用户ID")
|
||||||
|
|
||||||
class User(BaseModel):
|
class User(BaseModel):
|
||||||
__tablename__ = 'users'
|
__tablename__ = 'users'
|
||||||
|
|
||||||
email = Column(String(100), nullable=True, unique=True)
|
email = Column(String(100), nullable=False, unique=True, index=True, comment="用户邮箱,唯一")
|
||||||
nick = Column(String(50), nullable=True)
|
nick = Column(String(50), comment="用户昵称")
|
||||||
password = Column(String(255), nullable=True)
|
password = Column(String(255), nullable=False, comment="用户密码(加密后)")
|
||||||
status = Column(Integer, nullable=True)
|
status = Column(Integer, nullable=False, server_default='0', comment="用户状态: 0=正常, 1=未激活, 2=封禁")
|
||||||
group_id = Column(Integer, nullable=True)
|
storage = Column(BigInteger, nullable=False, server_default='0', comment="已用存储空间(字节)")
|
||||||
storage = Column(BigInteger, nullable=True)
|
two_factor = Column(String(255), comment="两步验证密钥")
|
||||||
two_factor = Column(String(255), nullable=True)
|
avatar = Column(String(255), comment="头像地址")
|
||||||
avatar = Column(String(255), nullable=True)
|
options = Column(Text, comment="用户个人设置 (JSON格式)")
|
||||||
options = Column(Text, nullable=True)
|
authn = Column(Text, comment="WebAuthn 凭证")
|
||||||
authn = Column(Text, nullable=True)
|
open_id = Column(String(255), unique=True, index=True, nullable=True, comment="第三方登录OpenID")
|
||||||
open_id = Column(String(255), nullable=True)
|
score = Column(Integer, nullable=False, server_default='0', comment="用户积分")
|
||||||
score = Column(Integer, nullable=True)
|
group_expires = Column(DateTime, comment="当前用户组过期时间")
|
||||||
previous_group_id = Column(Integer, nullable=True)
|
phone = Column(String(255), unique=True, nullable=True, index=True, comment="手机号")
|
||||||
group_expires = Column(DateTime, nullable=True)
|
|
||||||
notify_date = Column(DateTime, nullable=True)
|
group_id = Column(Integer, ForeignKey('groups.id'), nullable=False, index=True, comment="所属用户组ID")
|
||||||
phone = Column(String(255), nullable=True)
|
previous_group_id = Column(Integer, ForeignKey('groups.id'), nullable=True, comment="之前的用户组ID(用于过期后恢复)")
|
||||||
|
|
||||||
|
class Redeem(BaseModel):
|
||||||
|
__tablename__ = 'redeems'
|
||||||
|
|
||||||
|
type = Column(Integer, nullable=False, comment="兑换码类型")
|
||||||
|
product_id = Column(BigInteger, comment="关联的商品/权益ID")
|
||||||
|
num = Column(Integer, nullable=False, server_default='1', comment="可兑换数量/时长等")
|
||||||
|
code = Column(Text, nullable=False, unique=True, index=True, comment="兑换码,唯一")
|
||||||
|
used = Column(Boolean, nullable=False, server_default=text('false'), comment="是否已使用")
|
||||||
|
|
||||||
|
class Report(BaseModel):
|
||||||
|
__tablename__ = 'reports'
|
||||||
|
|
||||||
|
share_id = Column(Integer, ForeignKey('shares.id'), index=True, nullable=False, comment="被举报的分享ID")
|
||||||
|
reason = Column(Integer, nullable=False, comment="举报原因代码")
|
||||||
|
description = Column(String(255), comment="补充描述")
|
||||||
|
|
||||||
|
class SourceLink(BaseModel):
|
||||||
|
__tablename__ = 'source_links'
|
||||||
|
|
||||||
|
file_id = Column(Integer, ForeignKey('files.id'), nullable=False, index=True, comment="关联的文件ID")
|
||||||
|
name = Column(String(255), nullable=False, comment="链接名称")
|
||||||
|
downloads = Column(Integer, nullable=False, server_default='0', comment="通过此链接的下载次数")
|
||||||
|
|
||||||
|
class StoragePack(BaseModel):
|
||||||
|
__tablename__ = 'storage_packs'
|
||||||
|
|
||||||
|
name = Column(String(255), nullable=False, comment="容量包名称")
|
||||||
|
active_time = Column(DateTime, comment="激活时间")
|
||||||
|
expired_time = Column(DateTime, index=True, comment="过期时间")
|
||||||
|
size = Column(BigInteger, nullable=False, comment="容量包大小(字节)")
|
||||||
|
user_id = Column(Integer, ForeignKey('users.id'), nullable=False, index=True, comment="所属用户ID")
|
||||||
|
|
||||||
|
class Tag(BaseModel):
|
||||||
|
__tablename__ = 'tags'
|
||||||
|
|
||||||
|
name = Column(String(255), nullable=False, comment="标签名称")
|
||||||
|
icon = Column(String(255), comment="标签图标")
|
||||||
|
color = Column(String(255), comment="标签颜色")
|
||||||
|
type = Column(Integer, nullable=False, server_default='0', comment="标签类型: 0=手动, 1=自动")
|
||||||
|
expression = Column(Text, comment="自动标签的匹配表达式")
|
||||||
|
user_id = Column(Integer, ForeignKey('users.id'), nullable=False, index=True, comment="所属用户ID")
|
||||||
|
|
||||||
|
__table_args__ = (
|
||||||
|
UniqueConstraint('name', 'user_id', name='uq_tag_name_user'),
|
||||||
|
)
|
||||||
|
|
||||||
class WebDAV(BaseModel):
|
class WebDAV(BaseModel):
|
||||||
__tablename__ = 'webdavs'
|
__tablename__ = 'webdavs'
|
||||||
|
|
||||||
name = Column(String(255), nullable=True)
|
name = Column(String(255), nullable=False, comment="WebDAV账户名")
|
||||||
password = Column(String(255), nullable=True)
|
password = Column(String(255), nullable=False, comment="WebDAV密码(加密后)")
|
||||||
user_id = Column(Integer, nullable=True)
|
root = Column(Text, nullable=False, server_default="'/'", comment="根目录路径")
|
||||||
root = Column(Text, nullable=True)
|
readonly = Column(Boolean, nullable=False, server_default=text('false'), comment="是否只读")
|
||||||
readonly = Column(Boolean, nullable=True)
|
use_proxy = Column(Boolean, nullable=False, server_default=text('false'), comment="是否使用代理下载")
|
||||||
use_proxy = Column(Boolean, nullable=True)
|
user_id = Column(Integer, ForeignKey('users.id'), nullable=False, index=True, comment="所属用户ID")
|
||||||
|
|
||||||
__table_args__ = {'uniqueConstraints': [('password', 'user_id')]}
|
__table_args__ = (
|
||||||
|
UniqueConstraint('name', 'user_id', name='uq_webdav_name_user'),
|
||||||
|
)
|
||||||
225
routers/controllers/slave.py
Normal file
225
routers/controllers/slave.py
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
from fastapi import APIRouter, Depends
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
|
from middleware.auth import SignRequired
|
||||||
|
from models.response import ResponseModel
|
||||||
|
|
||||||
|
slave_router = APIRouter(
|
||||||
|
prefix="/slave",
|
||||||
|
tags=["slave"],
|
||||||
|
)
|
||||||
|
|
||||||
|
slave_aria2_router = APIRouter(
|
||||||
|
prefix="/aria2",
|
||||||
|
tags=["slave_aria2"],
|
||||||
|
)
|
||||||
|
|
||||||
|
@slave_router.get(
|
||||||
|
path='/ping',
|
||||||
|
summary='测试用路由',
|
||||||
|
description='Test route for checking connectivity.',
|
||||||
|
)
|
||||||
|
def router_slave_ping() -> ResponseModel:
|
||||||
|
"""
|
||||||
|
Test route for checking connectivity.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ResponseModel: A response model indicating success.
|
||||||
|
"""
|
||||||
|
from pkg.conf.appmeta import BackendVersion
|
||||||
|
return ResponseModel(data=BackendVersion)
|
||||||
|
|
||||||
|
@slave_router.post(
|
||||||
|
path='/post',
|
||||||
|
summary='上传',
|
||||||
|
description='Upload data to the server.',
|
||||||
|
dependencies=[Depends(SignRequired)],
|
||||||
|
)
|
||||||
|
def router_slave_post(data: str) -> ResponseModel:
|
||||||
|
"""
|
||||||
|
Upload data to the server.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (str): The data to be uploaded.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ResponseModel: A response model indicating success.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@slave_router.get(
|
||||||
|
path='/get/{speed}/{path}/{name}',
|
||||||
|
summary='获取下载',
|
||||||
|
)
|
||||||
|
def router_slave_download(speed: int, path: str, name: str) -> ResponseModel:
|
||||||
|
"""
|
||||||
|
Get download information.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
speed (int): The speed of the download.
|
||||||
|
path (str): The path where the file is located.
|
||||||
|
name (str): The name of the file to be downloaded.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ResponseModel: A response model containing download information.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@slave_router.get(
|
||||||
|
path='/download/{sign}',
|
||||||
|
summary='根据签名下载文件',
|
||||||
|
description='Download a file based on its signature.',
|
||||||
|
dependencies=[Depends(SignRequired)],
|
||||||
|
)
|
||||||
|
def router_slave_download_by_sign(sign: str) -> FileResponse:
|
||||||
|
"""
|
||||||
|
Download a file based on its signature.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sign (str): The signature of the file to be downloaded.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
FileResponse: A response containing the file to be downloaded.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@slave_router.get(
|
||||||
|
path='/source/{speed}/{path}/{name}',
|
||||||
|
summary='获取文件外链',
|
||||||
|
description='Get the external link for a file based on its signature.',
|
||||||
|
dependencies=[Depends(SignRequired)],
|
||||||
|
)
|
||||||
|
def router_slave_source(speed: int, path: str, name: str) -> ResponseModel:
|
||||||
|
"""
|
||||||
|
Get the external link for a file based on its signature.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
speed (int): The speed of the download.
|
||||||
|
path (str): The path where the file is located.
|
||||||
|
name (str): The name of the file to be linked.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ResponseModel: A response model containing the external link for the file.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@slave_router.get(
|
||||||
|
path='/source/{sign}',
|
||||||
|
summary='根据签名获取文件',
|
||||||
|
description='Get a file based on its signature.',
|
||||||
|
dependencies=[Depends(SignRequired)],
|
||||||
|
)
|
||||||
|
def router_slave_source_by_sign(sign: str) -> FileResponse:
|
||||||
|
"""
|
||||||
|
Get a file based on its signature.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sign (str): The signature of the file to be retrieved.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
FileResponse: A response containing the file to be retrieved.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@slave_router.get(
|
||||||
|
path='/thumb/{id}',
|
||||||
|
summary='获取缩略图',
|
||||||
|
description='Get a thumbnail image based on its ID.',
|
||||||
|
dependencies=[Depends(SignRequired)],
|
||||||
|
)
|
||||||
|
def router_slave_thumb(id: str) -> ResponseModel:
|
||||||
|
"""
|
||||||
|
Get a thumbnail image based on its ID.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
id (str): The ID of the thumbnail image.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ResponseModel: A response model containing the Base64 encoded thumbnail image.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@slave_router.delete(
|
||||||
|
path='/delete',
|
||||||
|
summary='删除文件',
|
||||||
|
description='Delete a file from the server.',
|
||||||
|
dependencies=[Depends(SignRequired)],
|
||||||
|
)
|
||||||
|
def router_slave_delete(path: str) -> ResponseModel:
|
||||||
|
"""
|
||||||
|
Delete a file from the server.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path (str): The path of the file to be deleted.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ResponseModel: A response model indicating success or failure of the deletion.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@slave_aria2_router.post(
|
||||||
|
path='/test',
|
||||||
|
summary='测试从机连接Aria2服务',
|
||||||
|
description='Test the connection to the Aria2 service from the slave.',
|
||||||
|
dependencies=[Depends(SignRequired)],
|
||||||
|
)
|
||||||
|
def router_slave_aria2_test() -> ResponseModel:
|
||||||
|
"""
|
||||||
|
Test the connection to the Aria2 service from the slave.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@slave_aria2_router.get(
|
||||||
|
path='/get/{gid}',
|
||||||
|
summary='获取Aria2任务信息',
|
||||||
|
description='Get information about an Aria2 task by its GID.',
|
||||||
|
dependencies=[Depends(SignRequired)],
|
||||||
|
)
|
||||||
|
def router_slave_aria2_get(gid: str = None) -> ResponseModel:
|
||||||
|
"""
|
||||||
|
Get information about an Aria2 task by its GID.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
gid (str): The GID of the Aria2 task.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ResponseModel: A response model containing the task information.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@slave_aria2_router.post(
|
||||||
|
path='/add',
|
||||||
|
summary='添加Aria2任务',
|
||||||
|
description='Add a new Aria2 task.',
|
||||||
|
dependencies=[Depends(SignRequired)],
|
||||||
|
)
|
||||||
|
def router_slave_aria2_add(gid: str, url: str, options: dict = None) -> ResponseModel:
|
||||||
|
"""
|
||||||
|
Add a new Aria2 task.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
gid (str): The GID for the new task.
|
||||||
|
url (str): The URL of the file to be downloaded.
|
||||||
|
options (dict, optional): Additional options for the task.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ResponseModel: A response model indicating success or failure of the task addition.
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
@slave_aria2_router.delete(
|
||||||
|
path='/remove/{gid}',
|
||||||
|
summary='删除Aria2任务',
|
||||||
|
description='Remove an Aria2 task by its GID.',
|
||||||
|
dependencies=[Depends(SignRequired)],
|
||||||
|
)
|
||||||
|
def router_slave_aria2_remove(gid: str) -> ResponseModel:
|
||||||
|
"""
|
||||||
|
Remove an Aria2 task by its GID.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
gid (str): The GID of the Aria2 task to be removed.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ResponseModel: A response model indicating success or failure of the task removal.
|
||||||
|
"""
|
||||||
|
...
|
||||||
@@ -12,7 +12,8 @@ from .controllers import (
|
|||||||
vas,
|
vas,
|
||||||
tag,
|
tag,
|
||||||
webdav,
|
webdav,
|
||||||
admin
|
admin,
|
||||||
|
slave
|
||||||
)
|
)
|
||||||
|
|
||||||
Router: list[APIRouter] = [
|
Router: list[APIRouter] = [
|
||||||
@@ -39,5 +40,7 @@ Router: list[APIRouter] = [
|
|||||||
admin.admin_aria2_router,
|
admin.admin_aria2_router,
|
||||||
admin.admin_policy_router,
|
admin.admin_policy_router,
|
||||||
admin.admin_task_router,
|
admin.admin_task_router,
|
||||||
admin.admin_vas_router
|
admin.admin_vas_router,
|
||||||
|
slave.slave_router,
|
||||||
|
slave.slave_aria2_router
|
||||||
]
|
]
|
||||||
Reference in New Issue
Block a user