Merge remote-tracking branch 'origin/wlj0909' into wlj0909
This commit is contained in:
commit
a89bd8b816
@ -85,15 +85,18 @@ def delete_transfer_history(history_in: schemas.TransferHistory,
|
||||
|
||||
@router.post("/transfer", summary="历史记录重新转移", response_model=schemas.Response)
|
||||
def redo_transfer_history(history_in: schemas.TransferHistory,
|
||||
mtype: str,
|
||||
new_tmdbid: int,
|
||||
mtype: str = None,
|
||||
new_tmdbid: int = None,
|
||||
db: Session = Depends(get_db),
|
||||
_: schemas.TokenPayload = Depends(verify_token)) -> Any:
|
||||
"""
|
||||
历史记录重新转移
|
||||
历史记录重新转移,不输入 mtype 和 new_tmdbid 时,自动使用文件名重新识别
|
||||
"""
|
||||
if mtype and new_tmdbid:
|
||||
state, errmsg = TransferChain(db).re_transfer(logid=history_in.id,
|
||||
mtype=MediaType(mtype), tmdbid=new_tmdbid)
|
||||
else:
|
||||
state, errmsg = TransferChain(db).re_transfer(logid=history_in.id)
|
||||
if state:
|
||||
return schemas.Response(success=True)
|
||||
else:
|
||||
|
@ -4,7 +4,7 @@ from typing import Optional, List, Tuple
|
||||
from app.chain import ChainBase
|
||||
from app.core.context import Context, MediaInfo
|
||||
from app.core.meta import MetaBase
|
||||
from app.core.metainfo import MetaInfo
|
||||
from app.core.metainfo import MetaInfo, MetaInfoPath
|
||||
from app.log import logger
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
@ -38,12 +38,8 @@ class MediaChain(ChainBase):
|
||||
"""
|
||||
logger.info(f'开始识别媒体信息,文件:{path} ...')
|
||||
file_path = Path(path)
|
||||
# 上级目录元数据
|
||||
dir_meta = MetaInfo(title=file_path.parent.name)
|
||||
# 文件元数据,不包含后缀
|
||||
file_meta = MetaInfo(title=file_path.stem)
|
||||
# 合并元数据
|
||||
file_meta.merge(dir_meta)
|
||||
# 元数据
|
||||
file_meta = MetaInfoPath(file_path)
|
||||
# 识别媒体信息
|
||||
mediainfo = self.recognize_media(meta=file_meta)
|
||||
if not mediainfo:
|
||||
|
@ -12,7 +12,7 @@ from app.chain.media import MediaChain
|
||||
from app.core.config import settings
|
||||
from app.core.context import MediaInfo
|
||||
from app.core.meta import MetaBase
|
||||
from app.core.metainfo import MetaInfo
|
||||
from app.core.metainfo import MetaInfoPath
|
||||
from app.db.downloadhistory_oper import DownloadHistoryOper
|
||||
from app.db.models.downloadhistory import DownloadHistory
|
||||
from app.db.models.transferhistory import TransferHistory
|
||||
@ -202,12 +202,8 @@ class TransferChain(ChainBase):
|
||||
key=ProgressKey.FileTransfer)
|
||||
|
||||
if not meta:
|
||||
# 上级目录元数据
|
||||
dir_meta = MetaInfo(title=file_path.parent.name)
|
||||
# 文件元数据,不包含后缀
|
||||
file_meta = MetaInfo(title=file_path.stem)
|
||||
# 合并元数据
|
||||
file_meta.merge(dir_meta)
|
||||
# 文件元数据
|
||||
file_meta = MetaInfoPath(file_path)
|
||||
else:
|
||||
file_meta = meta
|
||||
|
||||
@ -474,7 +470,8 @@ class TransferChain(ChainBase):
|
||||
text=errmsg, userid=userid))
|
||||
return
|
||||
|
||||
def re_transfer(self, logid: int, mtype: MediaType, tmdbid: int) -> Tuple[bool, str]:
|
||||
def re_transfer(self, logid: int,
|
||||
mtype: MediaType = None, tmdbid: int = None) -> Tuple[bool, str]:
|
||||
"""
|
||||
根据历史记录,重新识别转移,只处理对应的src目录
|
||||
:param logid: 历史记录ID
|
||||
@ -492,11 +489,15 @@ class TransferChain(ChainBase):
|
||||
return False, f"源目录不存在:{src_path}"
|
||||
dest_path = Path(history.dest) if history.dest else None
|
||||
# 查询媒体信息
|
||||
if mtype and tmdbid:
|
||||
mediainfo = self.recognize_media(mtype=mtype, tmdbid=tmdbid)
|
||||
else:
|
||||
meta = MetaInfoPath(src_path)
|
||||
mediainfo = self.recognize_media(meta=meta)
|
||||
if not mediainfo:
|
||||
return False, f"未识别到媒体信息,类型:{mtype.value},tmdbid:{tmdbid}"
|
||||
# 重新执行转移
|
||||
logger.info(f"{mtype.value} {tmdbid} 识别为:{mediainfo.title_year}")
|
||||
logger.info(f"{src_path.name} 识别为:{mediainfo.title_year}")
|
||||
# 更新媒体图片
|
||||
self.obtain_images(mediainfo=mediainfo)
|
||||
|
||||
|
@ -9,7 +9,7 @@ from app.core.meta.words import WordsMatcher
|
||||
|
||||
def MetaInfo(title: str, subtitle: str = None) -> MetaBase:
|
||||
"""
|
||||
媒体整理入口,根据名称和副标题,判断是哪种类型的识别,返回对应对象
|
||||
根据标题和副标题识别元数据
|
||||
:param title: 标题、种子名、文件名
|
||||
:param subtitle: 副标题、描述
|
||||
:return: MetaAnime、MetaVideo
|
||||
@ -33,6 +33,20 @@ def MetaInfo(title: str, subtitle: str = None) -> MetaBase:
|
||||
return meta
|
||||
|
||||
|
||||
def MetaInfoPath(path: Path) -> MetaBase:
|
||||
"""
|
||||
根据路径识别元数据
|
||||
:param path: 路径
|
||||
"""
|
||||
# 上级目录元数据
|
||||
dir_meta = MetaInfo(title=path.parent.name)
|
||||
# 文件元数据,不包含后缀
|
||||
file_meta = MetaInfo(title=path.stem)
|
||||
# 合并元数据
|
||||
file_meta.merge(dir_meta)
|
||||
return file_meta
|
||||
|
||||
|
||||
def is_anime(name: str) -> bool:
|
||||
"""
|
||||
判断是否为动漫
|
||||
|
@ -536,16 +536,14 @@ class FileTransferModule(_ModuleBase):
|
||||
@staticmethod
|
||||
def get_library_path(path: Path):
|
||||
"""
|
||||
根据目录查询其所在的媒体库目录
|
||||
根据目录查询其所在的媒体库目录,查询不到的返回输入目录
|
||||
"""
|
||||
if not path:
|
||||
return None
|
||||
if not settings.LIBRARY_PATHS:
|
||||
return None
|
||||
return path
|
||||
# 目的路径,多路径以,分隔
|
||||
dest_paths = settings.LIBRARY_PATHS
|
||||
if len(dest_paths) == 1:
|
||||
return dest_paths[0]
|
||||
for libpath in dest_paths:
|
||||
try:
|
||||
if path.is_relative_to(libpath):
|
||||
@ -553,7 +551,7 @@ class FileTransferModule(_ModuleBase):
|
||||
except Exception as e:
|
||||
logger.debug(f"计算媒体库路径时出错:{e}")
|
||||
continue
|
||||
return None
|
||||
return path
|
||||
|
||||
@staticmethod
|
||||
def get_target_path(in_path: Path = None) -> Optional[Path]:
|
||||
|
@ -386,33 +386,37 @@ class BestFilmVersion(_PluginBase):
|
||||
# 读取历史记录
|
||||
history = self.get_data('history') or []
|
||||
|
||||
all_item = []
|
||||
# 读取收藏
|
||||
if settings.MEDIASERVER == 'jellyfin':
|
||||
self.jellyfin_get_items(all_item)
|
||||
elif settings.MEDIASERVER == 'emby':
|
||||
self.emby_get_items(all_item)
|
||||
else:
|
||||
resp = self.plex_get_watchlist()
|
||||
if not resp:
|
||||
# 媒体服务器类型,多个以,分隔
|
||||
if not settings.MEDIASERVER:
|
||||
return
|
||||
all_item.extend(resp)
|
||||
media_servers = settings.MEDIASERVER.split(',')
|
||||
|
||||
# 读取收藏
|
||||
all_items = {}
|
||||
for media_server in media_servers:
|
||||
if media_server == 'jellyfin':
|
||||
all_items['jellyfin'] = self.jellyfin_get_items()
|
||||
elif media_server == 'emby':
|
||||
all_items['emby'] = self.emby_get_items()
|
||||
else:
|
||||
all_items['plex'] = self.plex_get_watchlist()
|
||||
|
||||
def function(y, x):
|
||||
return y if (x['Name'] in [i['Name'] for i in y]) else (lambda z, u: (z.append(u), z))(y, x)[1]
|
||||
|
||||
# 处理所有结果
|
||||
for server, all_item in all_items.items():
|
||||
# all_item 根据电影名去重
|
||||
result = reduce(function, all_item, [])
|
||||
|
||||
for data in result:
|
||||
# 检查缓存
|
||||
if data.get('Name') in caches:
|
||||
continue
|
||||
|
||||
# 获取详情
|
||||
if settings.MEDIASERVER == 'jellyfin':
|
||||
if server == 'jellyfin':
|
||||
item_info_resp = Jellyfin().get_iteminfo(itemid=data.get('Id'))
|
||||
elif settings.MEDIASERVER == 'emby':
|
||||
elif server == 'emby':
|
||||
item_info_resp = Emby().get_iteminfo(itemid=data.get('Id'))
|
||||
else:
|
||||
item_info_resp = self.plex_get_iteminfo(itemid=data.get('Id'))
|
||||
@ -468,13 +472,14 @@ class BestFilmVersion(_PluginBase):
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
def jellyfin_get_items(self, all_item):
|
||||
def jellyfin_get_items(self) -> List[dict]:
|
||||
# 获取所有user
|
||||
users_url = "{HOST}Users?&apikey={APIKEY}"
|
||||
users = self.get_users(Jellyfin().get_data(users_url))
|
||||
if not users:
|
||||
logger.info(f"bestfilmversion/users_url: {users_url}")
|
||||
return
|
||||
return []
|
||||
all_items = []
|
||||
for user in users:
|
||||
# 根据加入日期 降序排序
|
||||
url = "{HOST}Users/" + user + "/Items?SortBy=DateCreated%2CSortName" \
|
||||
@ -490,14 +495,16 @@ class BestFilmVersion(_PluginBase):
|
||||
resp = self.get_items(Jellyfin().get_data(url))
|
||||
if not resp:
|
||||
continue
|
||||
all_item.extend(resp)
|
||||
all_items.extend(resp)
|
||||
return all_items
|
||||
|
||||
def emby_get_items(self, all_item):
|
||||
def emby_get_items(self) -> List[dict]:
|
||||
# 获取所有user
|
||||
get_users_url = "{HOST}Users?&api_key={APIKEY}"
|
||||
users = self.get_users(Emby().get_data(get_users_url))
|
||||
if not users:
|
||||
return
|
||||
return []
|
||||
all_items = []
|
||||
for user in users:
|
||||
# 根据加入日期 降序排序
|
||||
url = "{HOST}emby/Users/" + user + "/Items?SortBy=DateCreated%2CSortName" \
|
||||
@ -512,7 +519,8 @@ class BestFilmVersion(_PluginBase):
|
||||
resp = self.get_items(Emby().get_data(url))
|
||||
if not resp:
|
||||
continue
|
||||
all_item.extend(resp)
|
||||
all_items.extend(resp)
|
||||
return all_items
|
||||
|
||||
@staticmethod
|
||||
def get_items(resp: Response):
|
||||
@ -538,7 +546,7 @@ class BestFilmVersion(_PluginBase):
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def plex_get_watchlist():
|
||||
def plex_get_watchlist() -> List[dict]:
|
||||
# 根据加入日期 降序排序
|
||||
url = f"https://metadata.provider.plex.tv/library/sections/watchlist/all?type=1&sort=addedAt%3Adesc" \
|
||||
f"&X-Plex-Container-Start=0&X-Plex-Container-Size=50" \
|
||||
|
@ -43,7 +43,7 @@ class BrushFlow(_PluginBase):
|
||||
# 加载顺序
|
||||
plugin_order = 21
|
||||
# 可使用的用户级别
|
||||
auth_level = 3
|
||||
auth_level = 2
|
||||
|
||||
# 私有属性
|
||||
siteshelper = None
|
||||
|
@ -15,7 +15,7 @@ from watchdog.observers.polling import PollingObserver
|
||||
from app.chain.transfer import TransferChain
|
||||
from app.core.config import settings
|
||||
from app.core.context import MediaInfo
|
||||
from app.core.metainfo import MetaInfo
|
||||
from app.core.metainfo import MetaInfoPath
|
||||
from app.db.downloadhistory_oper import DownloadHistoryOper
|
||||
from app.db.transferhistory_oper import TransferHistoryOper
|
||||
from app.log import logger
|
||||
@ -237,13 +237,8 @@ class DirMonitor(_PluginBase):
|
||||
logger.info(f"{event_path} 已整理过")
|
||||
return
|
||||
|
||||
# 上级目录元数据
|
||||
meta = MetaInfo(title=file_path.parent.name)
|
||||
# 文件元数据,不包含后缀
|
||||
file_meta = MetaInfo(title=file_path.stem)
|
||||
# 合并元数据
|
||||
file_meta.merge(meta)
|
||||
|
||||
# 元数据
|
||||
file_meta = MetaInfoPath(file_path)
|
||||
if not file_meta.name:
|
||||
logger.error(f"{file_path.name} 无法识别有效信息")
|
||||
return
|
||||
@ -343,7 +338,7 @@ class DirMonitor(_PluginBase):
|
||||
}
|
||||
"""
|
||||
# 发送消息汇总
|
||||
media_list = self._medias.get(mediainfo.title_year + " " + meta.season) or {}
|
||||
media_list = self._medias.get(mediainfo.title_year + " " + file_meta.season) or {}
|
||||
if media_list:
|
||||
media_files = media_list.get("files") or []
|
||||
if media_files:
|
||||
@ -384,7 +379,7 @@ class DirMonitor(_PluginBase):
|
||||
],
|
||||
"time": datetime.now()
|
||||
}
|
||||
self._medias[mediainfo.title_year + " " + meta.season] = media_list
|
||||
self._medias[mediainfo.title_year + " " + file_meta.season] = media_list
|
||||
|
||||
# 汇总刷新媒体库
|
||||
if settings.REFRESH_MEDIASERVER:
|
||||
@ -598,7 +593,7 @@ class DirMonitor(_PluginBase):
|
||||
'rows': 5,
|
||||
'placeholder': '每一行一个目录,支持两种配置方式:\n'
|
||||
'监控目录\n'
|
||||
'监控目录:转移目的目录'
|
||||
'监控目录:转移目的目录(需同时在媒体库目录中配置该目的目录)'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -718,16 +718,18 @@ class MediaSyncDel(_PluginBase):
|
||||
"""
|
||||
# 读取历史记录
|
||||
history = self.get_data('history') or []
|
||||
|
||||
# 媒体服务器类型
|
||||
media_server = settings.MEDIASERVER
|
||||
|
||||
last_time = self.get_data("last_time")
|
||||
del_medias = []
|
||||
|
||||
# 媒体服务器类型,多个以,分隔
|
||||
if not settings.MEDIASERVER:
|
||||
return
|
||||
media_servers = settings.MEDIASERVER.split(',')
|
||||
for media_server in media_servers:
|
||||
if media_server == 'emby':
|
||||
del_medias = self.parse_emby_log(last_time)
|
||||
del_medias.extend(self.parse_emby_log(last_time))
|
||||
elif media_server == 'jellyfin':
|
||||
del_medias = self.parse_jellyfin_log(last_time)
|
||||
del_medias.extend(self.parse_jellyfin_log(last_time))
|
||||
elif media_server == 'plex':
|
||||
# TODO plex解析日志
|
||||
return
|
||||
|
@ -383,9 +383,15 @@ class SpeedLimiter(_PluginBase):
|
||||
return
|
||||
# 当前播放的总比特率
|
||||
total_bit_rate = 0
|
||||
# 媒体服务器类型,多个以,分隔
|
||||
if not settings.MEDIASERVER:
|
||||
return
|
||||
media_servers = settings.MEDIASERVER.split(',')
|
||||
# 查询所有媒体服务器状态
|
||||
for media_server in media_servers:
|
||||
# 查询播放中会话
|
||||
playing_sessions = []
|
||||
if settings.MEDIASERVER == "emby":
|
||||
if media_server == "emby":
|
||||
req_url = "{HOST}emby/Sessions?api_key={APIKEY}"
|
||||
try:
|
||||
res = Emby().get_data(req_url)
|
||||
@ -396,6 +402,7 @@ class SpeedLimiter(_PluginBase):
|
||||
playing_sessions.append(session)
|
||||
except Exception as e:
|
||||
logger.error(f"获取Emby播放会话失败:{str(e)}")
|
||||
continue
|
||||
# 计算有效比特率
|
||||
for session in playing_sessions:
|
||||
# 设置了不限速范围则判断session ip是否在不限速范围内
|
||||
@ -407,7 +414,7 @@ class SpeedLimiter(_PluginBase):
|
||||
elif not IpUtils.is_private_ip(session.get("RemoteEndPoint")) \
|
||||
and session.get("NowPlayingItem", {}).get("MediaType") == "Video":
|
||||
total_bit_rate += int(session.get("NowPlayingItem", {}).get("Bitrate") or 0)
|
||||
elif settings.MEDIASERVER == "jellyfin":
|
||||
elif media_server == "jellyfin":
|
||||
req_url = "{HOST}Sessions?api_key={APIKEY}"
|
||||
try:
|
||||
res = Jellyfin().get_data(req_url)
|
||||
@ -418,6 +425,7 @@ class SpeedLimiter(_PluginBase):
|
||||
playing_sessions.append(session)
|
||||
except Exception as e:
|
||||
logger.error(f"获取Jellyfin播放会话失败:{str(e)}")
|
||||
continue
|
||||
# 计算有效比特率
|
||||
for session in playing_sessions:
|
||||
# 设置了不限速范围则判断session ip是否在不限速范围内
|
||||
@ -433,7 +441,7 @@ class SpeedLimiter(_PluginBase):
|
||||
media_streams = session.get("NowPlayingItem", {}).get("MediaStreams") or []
|
||||
for media_stream in media_streams:
|
||||
total_bit_rate += int(media_stream.get("BitRate") or 0)
|
||||
elif settings.MEDIASERVER == "plex":
|
||||
elif media_server == "plex":
|
||||
_plex = Plex().get_plex()
|
||||
if _plex:
|
||||
sessions = _plex.sessions()
|
||||
|
@ -61,7 +61,9 @@ class SystemUtils:
|
||||
移动
|
||||
"""
|
||||
try:
|
||||
# 当前目录改名
|
||||
temp = src.replace(src.parent / dest.name)
|
||||
# 移动到目标目录
|
||||
shutil.move(temp, dest)
|
||||
return 0, ""
|
||||
except Exception as err:
|
||||
@ -74,7 +76,11 @@ class SystemUtils:
|
||||
硬链接
|
||||
"""
|
||||
try:
|
||||
dest.hardlink_to(src)
|
||||
# link到当前目录并改名
|
||||
tmp_path = src.parent / dest.name
|
||||
tmp_path.hardlink_to(src)
|
||||
# 移动到目标目录
|
||||
shutil.move(tmp_path, dest)
|
||||
return 0, ""
|
||||
except Exception as err:
|
||||
print(str(err))
|
||||
|
Loading…
x
Reference in New Issue
Block a user