Merge remote-tracking branch 'origin/wlj0909' into wlj0909

This commit is contained in:
mayun110 2023-09-27 18:05:46 +08:00
commit a89bd8b816
11 changed files with 347 additions and 316 deletions

View File

@ -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:

View File

@ -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:

View File

@ -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)

View File

@ -9,7 +9,7 @@ from app.core.meta.words import WordsMatcher
def MetaInfo(title: str, subtitle: str = None) -> MetaBase:
"""
媒体整理入口根据名称和副标题判断是哪种类型的识别返回对应对象
根据标题和副标题识别元数据
:param title: 标题种子名文件名
:param subtitle: 副标题描述
:return: MetaAnimeMetaVideo
@ -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:
"""
判断是否为动漫

View File

@ -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]:

View File

@ -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" \

View File

@ -43,7 +43,7 @@ class BrushFlow(_PluginBase):
# 加载顺序
plugin_order = 21
# 可使用的用户级别
auth_level = 3
auth_level = 2
# 私有属性
siteshelper = None

View File

@ -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'
'监控目录:转移目的目录'
'监控目录:转移目的目录(需同时在媒体库目录中配置该目的目录)'
}
}
]

View File

@ -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

View File

@ -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()

View File

@ -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))