fix directories

This commit is contained in:
jxxghp
2024-07-02 17:47:29 +08:00
parent f23be671c0
commit 1822d01d17
17 changed files with 176 additions and 239 deletions

View File

@@ -2,7 +2,7 @@ from fastapi import APIRouter
from app.api.endpoints import login, user, site, message, webhook, subscribe, \
media, douban, search, plugin, tmdb, history, system, download, dashboard, \
transfer, mediaserver, bangumi, aliyun, storage
transfer, mediaserver, bangumi, storage
api_router = APIRouter()
api_router.include_router(login.router, prefix="/login", tags=["login"])
@@ -20,8 +20,7 @@ api_router.include_router(system.router, prefix="/system", tags=["system"])
api_router.include_router(plugin.router, prefix="/plugin", tags=["plugin"])
api_router.include_router(download.router, prefix="/download", tags=["download"])
api_router.include_router(dashboard.router, prefix="/dashboard", tags=["dashboard"])
api_router.include_router(storage.router, prefix="/local", tags=["storage"])
api_router.include_router(storage.router, prefix="/storage", tags=["storage"])
api_router.include_router(transfer.router, prefix="/transfer", tags=["transfer"])
api_router.include_router(mediaserver.router, prefix="/mediaserver", tags=["mediaserver"])
api_router.include_router(bangumi.router, prefix="/bangumi", tags=["bangumi"])
api_router.include_router(aliyun.router, prefix="/aliyun", tags=["aliyun"])

View File

@@ -43,23 +43,23 @@ def statistic2(_: str = Depends(verify_apitoken)) -> Any:
return statistic()
@router.get("/storage", summary="存储空间", response_model=schemas.Storage)
@router.get("/storage", summary="本地存储空间", response_model=schemas.Storage)
def storage(_: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
查询存储空间信息
查询本地存储空间信息
"""
library_dirs = DirectoryHelper().get_library_dirs()
total_storage, free_storage = SystemUtils.space_usage([Path(d.path) for d in library_dirs if d.path])
library_dirs = DirectoryHelper().get_local_library_dirs()
total_storage, free_storage = SystemUtils.space_usage([Path(d.library_path) for d in library_dirs])
return schemas.Storage(
total_storage=total_storage,
used_storage=total_storage - free_storage
)
@router.get("/storage2", summary="存储空间API_TOKEN", response_model=schemas.Storage)
@router.get("/storage2", summary="本地存储空间API_TOKEN", response_model=schemas.Storage)
def storage2(_: str = Depends(verify_apitoken)) -> Any:
"""
查询存储空间信息 API_TOKEN认证?token=xxx
查询本地存储空间信息 API_TOKEN认证?token=xxx
"""
return storage()
@@ -78,8 +78,8 @@ def downloader(_: schemas.TokenPayload = Depends(verify_token)) -> Any:
查询下载器信息
"""
# 下载目录空间
download_dirs = DirectoryHelper().get_download_dirs()
_, free_space = SystemUtils.space_usage([Path(d.path) for d in download_dirs if d.path])
download_dirs = DirectoryHelper().get_local_download_dirs()
_, free_space = SystemUtils.space_usage([Path(d.download_path) for d in download_dirs])
# 下载器信息
downloader_info = schemas.DownloaderInfo()
transfer_infos = DashboardChain().downloader_info()

View File

@@ -176,7 +176,6 @@ def tv_hot(page: int = 1,
@router.get("/credits/{doubanid}/{type_name}", summary="豆瓣演员阵容", response_model=List[schemas.MediaPerson])
def douban_credits(doubanid: str,
type_name: str,
page: int = 1,
_: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
根据豆瓣ID查询演员阵容type_name: 电影/电视剧

View File

@@ -1,4 +1,4 @@
from pathlib import Path
import json
from typing import List, Any
from fastapi import APIRouter, Depends
@@ -81,17 +81,19 @@ def delete_transfer_history(history_in: schemas.TransferHistory,
"""
删除转移历史记录
"""
history = TransferHistory.get(db, history_in.id)
history: TransferHistory = TransferHistory.get(db, history_in.id)
if not history:
return schemas.Response(success=False, msg="记录不存在")
# 册除媒体库文件
if deletedest and history.dest:
state, msg = TransferChain().delete_files(Path(history.dest))
if deletedest and history.dest_fileitem:
dest_fileitem = schemas.FileItem(**json.loads(history.dest_fileitem))
state, msg = TransferChain().delete_files(dest_fileitem)
if not state:
return schemas.Response(success=False, msg=msg)
# 删除源文件
if deletesrc and history.src:
state, msg = TransferChain().delete_files(Path(history.src))
if deletesrc and history.dest_fileitem:
dest_fileitem = schemas.FileItem(**json.loads(history.dest_fileitem))
state, msg = TransferChain().delete_files(dest_fileitem)
if not state:
return schemas.Response(success=False, msg=msg)
# 发送事件

View File

@@ -120,7 +120,7 @@ def scrape(fileitem: schemas.FileItem,
if not fileitem.fileid:
return schemas.Response(success=False, message="刮削文件ID无效")
# 手动刮削
chain.scrape_metadata(storage=storage, fileitem=fileitem, meta=meta, mediainfo=mediainfo)
chain.scrape_metadata(fileitem=fileitem, meta=meta, mediainfo=mediainfo)
return schemas.Response(success=True, message=f"{fileitem.path} 刮削完成")

View File

@@ -119,26 +119,26 @@ def not_exists(media_in: schemas.MediaInfo,
@router.get("/latest", summary="最新入库条目", response_model=List[schemas.MediaServerPlayItem])
def latest(count: int = 18,
def latest(server: str, count: int = 18,
userinfo: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
获取媒体服务器最新入库条目
"""
return MediaServerChain().latest(count=count, username=userinfo.username) or []
return MediaServerChain().latest(server=server, count=count, username=userinfo.username) or []
@router.get("/playing", summary="正在播放条目", response_model=List[schemas.MediaServerPlayItem])
def playing(count: int = 12,
def playing(server: str, count: int = 12,
userinfo: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
获取媒体服务器正在播放条目
"""
return MediaServerChain().playing(count=count, username=userinfo.username) or []
return MediaServerChain().playing(server=server, count=count, username=userinfo.username) or []
@router.get("/library", summary="媒体库列表", response_model=List[schemas.MediaServerLibrary])
def library(userinfo: schemas.TokenPayload = Depends(verify_token)) -> Any:
def library(server: str, userinfo: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
获取媒体服务器媒体库列表
"""
return MediaServerChain().librarys(username=userinfo.username) or []
return MediaServerChain().librarys(server=server, username=userinfo.username) or []

View File

@@ -164,7 +164,7 @@ def plugin_dashboard(plugin_id: str, user_agent: Annotated[str | None, Header()]
"""
根据插件ID获取插件仪表板
"""
return PluginManager().get_plugin_dashboard(plugin_id, key=None, user_agent=user_agent)
return PluginManager().get_plugin_dashboard(plugin_id, user_agent=user_agent)
@router.get("/dashboard/{plugin_id}/{key}", summary="获取插件仪表板配置")

View File

@@ -96,14 +96,14 @@ def manual_transfer(fileitem: FileItem = None,
force = True
if history.status and ("move" in history.mode):
# 重新整理成功的转移,则使用成功的 dest 做 in_path
src_fileitem = json.loads(history.dest_fileitem)
src_fileitem = FileItem(**json.loads(history.dest_fileitem))
else:
# 源路径
src_fileitem = json.loads(history.src_fileitem)
src_fileitem = FileItem(**json.loads(history.src_fileitem))
# 目的路径
if history.dest_fileitem:
# 删除旧的已整理文件
dest_fileitem = json.loads(history.dest_fileitem)
dest_fileitem = FileItem(**json.loads(history.dest_fileitem))
transfer.delete_files(dest_fileitem)
elif fileitem:
src_fileitem = fileitem

View File

@@ -245,22 +245,23 @@ class DownloadChain(ChainBase):
# 下载目录
if save_path:
# 有自定义下载目录时,尝试匹配目录配置
dir_info = self.directoryhelper.get_download_dir(_media, to_path=Path(save_path))
dir_info = self.directoryhelper.get_dir(_media, src_path=Path(save_path), local=True)
else:
# 根据媒体信息查询下载目录配置
dir_info = self.directoryhelper.get_download_dir(_media)
dir_info = self.directoryhelper.get_dir(_media, local=True)
# 拼装子目录
if dir_info:
# 一级目录
if not dir_info.media_type and dir_info.auto_category:
if not dir_info.media_type and dir_info.download_type_folder:
# 一级自动分类
download_dir = Path(dir_info.path) / _media.type.value
download_dir = Path(dir_info.download_path) / _media.type.value
else:
# 一级不分类
download_dir = Path(dir_info.path)
download_dir = Path(dir_info.download_path)
# 二级目录
if not dir_info.category and dir_info.auto_category and _media and _media.category:
if not dir_info.media_category and dir_info.download_category_folder and _media and _media.category:
# 二级自动分类
download_dir = download_dir / _media.category
elif save_path:

View File

@@ -5,7 +5,6 @@ from cachetools import cached, TTLCache
from app import schemas
from app.chain import ChainBase
from app.core.config import settings
from app.core.context import MediaInfo
from app.schemas import MediaType
from app.utils.singleton import Singleton

View File

@@ -63,11 +63,11 @@ class TransferChain(ChainBase):
# 全局锁,避免重复处理
with lock:
logger.info("开始执行下载器文件转移 ...")
logger.info("开始整理下载器中已经完成下载的文件 ...")
# 从下载器获取种子列表
torrents: Optional[List[TransferTorrent]] = self.list_torrents(status=TorrentStatus.TRANSFER)
if not torrents:
logger.info("没有获取到已完成下载任务")
logger.info("没有已完成下载但未整理的任务")
return False
logger.info(f"获取到 {len(torrents)} 个已完成的下载任务")
@@ -109,7 +109,7 @@ class TransferChain(ChainBase):
# 设置下载任务状态
self.transfer_completed(hashs=torrent.hash, path=torrent.path)
# 结束
logger.info("下载器文件转移执行完成")
logger.info("所有下载器中下载完成的文件已整理完成")
return True
def __do_transfer(self, fileitem: FileItem,

View File

@@ -374,7 +374,7 @@ class PluginManager(metaclass=Singleton):
return plugin.get_page() or []
return []
def get_plugin_dashboard(self, pid: str, key: str, **kwargs) -> Optional[schemas.PluginDashboard]:
def get_plugin_dashboard(self, pid: str, key: str = None, **kwargs) -> Optional[schemas.PluginDashboard]:
"""
获取插件仪表盘
:param pid: 插件ID

View File

@@ -2,12 +2,9 @@ from pathlib import Path
from typing import List, Optional
from app import schemas
from app.core.config import settings
from app.core.context import MediaInfo
from app.db.systemconfig_oper import SystemConfigOper
from app.log import logger
from app.schemas.types import SystemConfigKey, MediaType
from app.utils.system import SystemUtils
class DirectoryHelper:
@@ -18,147 +15,72 @@ class DirectoryHelper:
def __init__(self):
self.systemconfig = SystemConfigOper()
def get_download_dirs(self) -> List[schemas.MediaDirectory]:
def get_download_dirs(self) -> List[schemas.TransferDirectoryConf]:
"""
获取下载目录
获取所有下载目录
"""
dir_conf: List[dict] = self.systemconfig.get(SystemConfigKey.DownloadDirectories)
if not dir_conf:
dir_confs: List[dict] = self.systemconfig.get(SystemConfigKey.Directories)
if not dir_confs:
return []
return [schemas.MediaDirectory(**d) for d in dir_conf]
dirs = [schemas.TransferDirectoryConf(**d) for d in dir_confs]
return sorted([d for d in dirs if d.download_path], key=lambda x: x.priority)
def get_library_dirs(self) -> List[schemas.MediaDirectory]:
def get_local_download_dirs(self) -> List[schemas.TransferDirectoryConf]:
"""
获取媒体库目录
获取所有本地的可下载目录
"""
dir_conf: List[dict] = self.systemconfig.get(SystemConfigKey.LibraryDirectories)
if not dir_conf:
return [d for d in self.get_download_dirs() if d.storage == "local"]
def get_library_dirs(self) -> List[schemas.TransferDirectoryConf]:
"""
获取所有媒体库目录
"""
dir_confs: List[dict] = self.systemconfig.get(SystemConfigKey.Directories)
if not dir_confs:
return []
return [schemas.MediaDirectory(**d) for d in dir_conf]
dirs = [schemas.TransferDirectoryConf(**d) for d in dir_confs]
return sorted([d for d in dirs if d.library_path], key=lambda x: x.priority)
def get_download_dir(self, media: MediaInfo = None, to_path: Path = None) -> Optional[schemas.MediaDirectory]:
def get_local_library_dirs(self) -> List[schemas.TransferDirectoryConf]:
"""
根据媒体信息获取下载目录
获取所有本地的媒体库目录
"""
return [d for d in self.get_library_dirs() if d.library_storage == "local"]
def get_dir(self, media: MediaInfo, src_path: Path = None, dest_path: Path = None,
local: bool = False) -> Optional[schemas.TransferDirectoryConf]:
"""
根据媒体信息获取下载目录、媒体库目录配置
:param media: 媒体信息
:param to_path: 目标目录
:param src_path: 源目录,有值时直接匹配
:param dest_path: 目标目录,有值时直接匹配
:param local: 是否本地目录
"""
# 处理类型
if media:
media_type = media.type.value
else:
media_type = MediaType.UNKNOWN.value
download_dirs = self.get_download_dirs()
# 按照配置顺序查找(保存后的数据已经排序)
for download_dir in download_dirs:
if not download_dir.path:
dirs = self.get_download_dirs()
# 按照配置顺序查找
for d in dirs:
download_path = Path(d.download_path)
# 有目录时直接匹配
if src_path and download_path != src_path:
continue
download_path = Path(download_dir.path)
# 有目标目录,但目标目录与当前目录不相等时不要
if to_path and download_path != to_path:
if dest_path and download_path != dest_path:
continue
# 本地目录
if local and d.storage != "local":
continue
# 目录类型为全部的,符合条件
if not download_dir.media_type:
return download_dir
if not d.media_type:
return d
# 目录类型相等,目录类别为全部,符合条件
if download_dir.media_type == media_type and not download_dir.category:
return download_dir
if d.media_type == media_type and not d.media_category:
return d
# 目录类型相等,目录类别相等,符合条件
if download_dir.media_type == media_type and download_dir.category == media.category:
return download_dir
if d.media_type == media_type and d.media_category == media.category:
return d
return None
def get_library_dir(self, media: MediaInfo = None, in_path: Path = None,
to_path: Path = None) -> Optional[schemas.MediaDirectory]:
"""
根据媒体信息获取媒体库目录,需判断是否同盘优先
:param media: 媒体信息
:param in_path: 源目录
:param to_path: 目标目录
"""
def __comman_parts(path1: Path, path2: Path) -> int:
"""
计算两个路径的公共路径长度
"""
parts1 = path1.parts
parts2 = path2.parts
root_flag = parts1[0] == '/' and parts2[0] == '/'
length = min(len(parts1), len(parts2))
for i in range(length):
if parts1[i] == '/' and parts2[i] == '/':
continue
if parts1[i] != parts2[i]:
return i - 1 if root_flag else i
return length - 1 if root_flag else length
# 处理类型
if media:
media_type = media.type.value
else:
media_type = MediaType.UNKNOWN.value
# 匹配的目录
matched_dirs = []
library_dirs = self.get_library_dirs()
# 按照配置顺序查找(保存后的数据已经排序)
for library_dir in library_dirs:
if not library_dir.path:
continue
# 有目标目录,但目标目录与当前目录不相等时不要
if to_path and Path(library_dir.path) != to_path:
continue
# 目录类型为全部的,符合条件
if not library_dir.media_type:
matched_dirs.append(library_dir)
# 目录类型相等,目录类别为全部,符合条件
if library_dir.media_type == media_type and not library_dir.category:
matched_dirs.append(library_dir)
# 目录类型相等,目录类别相等,符合条件
if library_dir.media_type == media_type and library_dir.category == media.category:
matched_dirs.append(library_dir)
# 未匹配到
if not matched_dirs:
return None
# 没有目录则创建
for matched_dir in matched_dirs:
matched_path = Path(matched_dir.path)
if not matched_path.exists():
matched_path.mkdir(parents=True, exist_ok=True)
# 只匹配到一项
if len(matched_dirs) == 1:
return matched_dirs[0]
# 有源路径,且开启同盘/同目录优先时
if in_path and settings.TRANSFER_SAME_DISK:
# 优先同根路径
max_length = 0
target_dirs = []
for matched_dir in matched_dirs:
try:
# 计算in_path和path的公共路径长度
relative_len = __comman_parts(in_path, Path(matched_dir.path))
if relative_len and relative_len >= max_length:
max_length = relative_len
target_dirs.append({
'path': matched_dir,
'relative_len': relative_len
})
except Exception as e:
logger.debug(f"计算目标路径时出错:{str(e)}")
continue
if target_dirs:
target_dirs.sort(key=lambda x: x['relative_len'], reverse=True)
matched_dirs = [x['path'] for x in target_dirs]
# 优先同盘
for matched_dir in matched_dirs:
matched_path = Path(matched_dir.path)
if SystemUtils.is_same_disk(matched_path, in_path):
return matched_dir
# 返回最优先的匹配
return matched_dirs[0]

View File

@@ -15,7 +15,7 @@ from app.helper.module import ModuleHelper
from app.log import logger
from app.modules import _ModuleBase
from app.modules.filemanager.storage import StorageBase
from app.schemas import TransferInfo, ExistMediaInfo, TmdbEpisode, MediaDirectory, FileItem
from app.schemas import TransferInfo, ExistMediaInfo, TmdbEpisode, TransferDirectoryConf, FileItem
from app.schemas.types import MediaType
from app.utils.system import SystemUtils
@@ -51,39 +51,31 @@ class FileManagerModule(_ModuleBase):
测试模块连接性
"""
directoryhelper = DirectoryHelper()
# 检查下载目录
download_paths = directoryhelper.get_download_dirs()
# 检查本地下载目录是否存在
download_paths = directoryhelper.get_local_download_dirs()
if not download_paths:
return False, "下载目录未设置"
for d_path in download_paths:
path = d_path.path
path = d_path.download_path
if not path:
return False, f"下载目录 {d_path.name} 对应路径未设置"
download_path = Path(path)
if not download_path.exists():
return False, f"下载目录 {d_path.name} 对应路径 {path} 不存在"
# 检查媒体库目录
libaray_paths = directoryhelper.get_library_dirs()
# 检查本地媒体库目录是否存在
libaray_paths = directoryhelper.get_local_library_dirs()
if not libaray_paths:
return False, "媒体库目录未设置"
for l_path in libaray_paths:
path = l_path.path
path = l_path.library_path
if not path:
return False, f"媒体库目录 {l_path.name} 对应路径未设置"
library_path = Path(path)
if not library_path.exists():
return False, f"媒体库目录{l_path.name} 对应的路径 {path} 不存在"
# 检查硬链接条件
if settings.DOWNLOADER_MONITOR and settings.TRANSFER_TYPE == "link":
for d_path in download_paths:
link_ok = False
for l_path in libaray_paths:
if SystemUtils.is_same_disk(Path(d_path.path), Path(l_path.path)):
link_ok = True
break
if not link_ok:
return False, f"媒体库目录中未找到" \
f"与下载目录 {d_path.path} 在同一磁盘/存储空间/映射路径的目录,将无法硬链接"
# TODO 检查硬链接条件
# TODO 检查网盘目录
return True, ""
def init_setting(self) -> Tuple[str, Union[str, bool]]:
@@ -198,20 +190,23 @@ class FileManagerModule(_ModuleBase):
# 获取目标路径
directoryhelper = DirectoryHelper()
if target_path:
dir_info = directoryhelper.get_library_dir(mediainfo, in_path=fileitem.path, to_path=target_path)
dir_info = directoryhelper.get_dir(mediainfo, dest_path=target_path)
else:
dir_info = directoryhelper.get_library_dir(mediainfo, in_path=fileitem.path)
dir_info = directoryhelper.get_dir(mediainfo)
if dir_info:
# 是否需要刮削
if scrape is None:
need_scrape = dir_info.scrape
need_scrape = dir_info.scraping
else:
need_scrape = scrape
# 是否需要重命名
need_rename = dir_info.renaming
# 拼装媒体库一、二级子目录
target_path = self.__get_dest_dir(mediainfo=mediainfo, target_dir=dir_info)
elif target_path:
# 自定义目标路径
need_scrape = scrape or False
need_rename = True
else:
# 未找到有效的媒体库目录
logger.error(
@@ -229,7 +224,8 @@ class FileManagerModule(_ModuleBase):
target_storage=target_storage,
target_path=target_path,
episodes_info=episodes_info,
need_scrape=need_scrape)
need_scrape=need_scrape,
need_rename=need_rename)
def __get_storage_oper(self, _storage: str):
"""
@@ -595,7 +591,7 @@ class FileManagerModule(_ModuleBase):
if target_storage == "local" and (target_file.exists() or target_file.is_symlink()):
if not over_flag:
logger.warn(f"文件已存在:{target_file}")
return 0
return None, f"{target_file} 已存在"
else:
logger.info(f"正在删除已存在的文件:{target_file}")
target_file.unlink()
@@ -617,24 +613,24 @@ class FileManagerModule(_ModuleBase):
return None, errmsg
@staticmethod
def __get_dest_dir(mediainfo: MediaInfo, target_dir: MediaDirectory) -> Path:
def __get_dest_dir(mediainfo: MediaInfo, target_dir: TransferDirectoryConf) -> Path:
"""
根据设置并装媒体库目录
:param mediainfo: 媒体信息
:target_dir: 媒体库根目录
:typename_dir: 是否加上类型目录
"""
if not target_dir.media_type and target_dir.auto_category:
if not target_dir.media_type and target_dir.library_type_folder:
# 一级自动分类
download_dir = Path(target_dir.path) / mediainfo.type.value
library_dir = Path(target_dir.library_path) / mediainfo.type.value
else:
download_dir = Path(target_dir.path)
library_dir = Path(target_dir.library_path)
if not target_dir.category and target_dir.auto_category and mediainfo.category:
if not target_dir.media_category and target_dir.library_category_folder and mediainfo.category:
# 二级自动分类
download_dir = download_dir / mediainfo.category
library_dir = library_dir / mediainfo.category
return download_dir
return library_dir
def transfer_media(self,
fileitem: FileItem,
@@ -644,7 +640,8 @@ class FileManagerModule(_ModuleBase):
target_storage: str,
target_path: Path,
episodes_info: List[TmdbEpisode] = None,
need_scrape: bool = False
need_scrape: bool = False,
need_rename: bool = True
) -> TransferInfo:
"""
识别并整理一个文件或者一个目录下的所有文件
@@ -656,6 +653,7 @@ class FileManagerModule(_ModuleBase):
:param transfer_type: 文件整理方式
:param episodes_info: 当前季的全部集信息
:param need_scrape: 是否需要刮削
:param need_rename: 是否需要重命名
:return: TransferInfo、错误信息
"""
@@ -693,12 +691,15 @@ class FileManagerModule(_ModuleBase):
# 判断是否为文件夹
if fileitem.type == "dir":
# 整理整个目录,一般为蓝光原盘
new_path = self.get_rename_path(
path=target_path,
template_string=rename_format,
rename_dict=self.__get_naming_dict(meta=in_meta,
mediainfo=mediainfo)
).parent
if need_rename:
new_path = self.get_rename_path(
path=target_path,
template_string=rename_format,
rename_dict=self.__get_naming_dict(meta=in_meta,
mediainfo=mediainfo)
).parent
else:
new_path = target_path / fileitem.name
# 整理目录
new_item, errmsg = self.__transfer_dir(fileitem=fileitem,
target_storage=target_storage,
@@ -740,16 +741,19 @@ class FileManagerModule(_ModuleBase):
in_meta.end_episode = None
# 目的文件名
new_file = self.get_rename_path(
path=target_path,
template_string=rename_format,
rename_dict=self.__get_naming_dict(
meta=in_meta,
mediainfo=mediainfo,
episodes_info=episodes_info,
file_ext=f".{fileitem.extension}"
if need_rename:
new_file = self.get_rename_path(
path=target_path,
template_string=rename_format,
rename_dict=self.__get_naming_dict(
meta=in_meta,
mediainfo=mediainfo,
episodes_info=episodes_info,
file_ext=f".{fileitem.extension}"
)
)
)
else:
new_file = target_path / fileitem.name
# 判断是否要覆盖
overflag = False

View File

@@ -1,25 +0,0 @@
from typing import Optional
from pydantic import BaseModel
class MediaDirectory(BaseModel):
"""
下载目录/媒体库目录
"""
# 类型 download/library
type: Optional[str] = None
# 别名
name: Optional[str] = None
# 路径
path: Optional[str] = None
# 媒体类型 电影/电视剧
media_type: Optional[str] = None
# 媒体类别 动画电影/国产剧
category: Optional[str] = None
# 刮削媒体信息
scrape: Optional[bool] = False
# 自动二级分类,未指定类别时自动分类
auto_category: Optional[bool] = False
# 优先级
priority: Optional[int] = 0

View File

@@ -47,3 +47,41 @@ class NotificationConf(BaseModel):
switchs: Optional[list] = []
# 是否启用
enabled: Optional[bool] = False
class TransferDirectoryConf(BaseModel):
"""
文件整理目录配置
"""
# 名称
name: Optional[str] = None
# 优先级
priority: Optional[int] = 0
# 存储
storage: Optional[str] = None
# 下载目录
download_path: Optional[str] = None
# 适用媒体类型
media_type: Optional[str] = None
# 适用媒体类别
media_category: Optional[str] = None
# 下载类型子目录
download_type_folder: Optional[bool] = False
# 下载类别子目录
download_category_folder: Optional[bool] = False
# 监控方式 downloader/monitorNone为不监控
monitor_type: Optional[str] = None
# 整理方式 move/copy/link/softlink
transfer_type: Optional[str] = None
# 整理到媒体库目录
library_path: Optional[str] = None
# 媒体库目录存储
library_storage: Optional[str] = None
# 智能重命名
renaming: Optional[bool] = False
# 刮削
scraping: Optional[bool] = False
# 媒体库类型子目录
library_type_folder: Optional[bool] = False
# 媒体库类别子目录
library_category_folder: Optional[bool] = False

View File

@@ -64,10 +64,8 @@ class SystemConfigKey(Enum):
MediaServers = "MediaServers"
# 消息通知配置
Notifications = "Notifications"
# 下载目录配置
DownloadDirectories = "DownloadDirectories"
# 媒体库目录配置
LibraryDirectories = "LibraryDirectories"
# 目录配置
Directories = "Directories"
# 阿里云盘认证参数
UserAliyunParams = "UserAliyunParams"
# 115网盘认证参数