fix BestFilmVersion 短时间内连续触发插件 造成的重复订阅

This commit is contained in:
mayun110 2023-08-14 17:54:56 +08:00
parent 271ab494a9
commit 9e37068b75

View File

@ -1,6 +1,7 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from functools import reduce from functools import reduce
from pathlib import Path from pathlib import Path
from threading import RLock
from typing import Optional, Any, List, Dict, Tuple from typing import Optional, Any, List, Dict, Tuple
from xml.dom.minidom import parseString from xml.dom.minidom import parseString
@ -22,6 +23,8 @@ from app.schemas import WebhookEventInfo
from app.schemas.types import MediaType, EventType from app.schemas.types import MediaType, EventType
from app.utils.http import RequestUtils from app.utils.http import RequestUtils
lock = RLock()
class BestFilmVersion(_PluginBase): class BestFilmVersion(_PluginBase):
# 插件名称 # 插件名称
@ -373,128 +376,143 @@ class BestFilmVersion(_PluginBase):
""" """
通过流媒体管理工具收藏,自动洗版 通过流媒体管理工具收藏,自动洗版
""" """
# 获取锁
_is_lock: bool = lock.acquire(timeout=60)
if not _is_lock:
return
try:
# 读取缓存
caches = self._cache_path.read_text().split("\n") if self._cache_path.exists() else []
# 读取历史记录
history = self.get_data('history') or []
# 读取缓存 all_item = []
caches = self._cache_path.read_text().split("\n") if self._cache_path.exists() else [] # 读取收藏
# 读取历史记录 if settings.MEDIASERVER == 'jellyfin':
history = self.get_data('history') or [] 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:
return
all_item.extend(resp)
all_item = [] 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]
if settings.MEDIASERVER == 'jellyfin':
# 获取所有user # all_item 根据电影名去重
users_url = "{HOST}Users?&apikey={APIKEY}" result = reduce(function, all_item, [])
users = self.get_users(Jellyfin().get_data(users_url))
if not users: for data in result:
logger.info(f"bestfilmversion/users_url: {users_url}") # 检查缓存
return if data.get('Name') in caches:
for user in users:
# 根据加入日期 降序排序
url = "{HOST}Users/" + user + "/Items?SortBy=DateCreated%2CSortName" \
"&SortOrder=Descending" \
"&Filters=IsFavorite" \
"&Recursive=true" \
"&Fields=PrimaryImageAspectRatio%2CBasicSyncInfo" \
"&CollapseBoxSetItems=false" \
"&ExcludeLocationTypes=Virtual" \
"&EnableTotalRecordCount=false" \
"&Limit=20" \
"&apikey={APIKEY}"
resp = self.get_items(Jellyfin().get_data(url))
if not resp:
continue continue
all_item.extend(resp)
elif settings.MEDIASERVER == 'emby': # 获取详情
# 获取所有user if settings.MEDIASERVER == 'jellyfin':
get_users_url = "{HOST}Users?&api_key={APIKEY}" item_info_resp = Jellyfin().get_iteminfo(itemid=data.get('Id'))
users = self.get_users(Emby().get_data(get_users_url)) elif settings.MEDIASERVER == 'emby':
if not users: item_info_resp = Emby().get_iteminfo(itemid=data.get('Id'))
return else:
for user in users: item_info_resp = self.plex_get_iteminfo(itemid=data.get('Id'))
# 根据加入日期 降序排序
url = "{HOST}emby/Users/" + user + "/Items?SortBy=DateCreated%2CSortName" \ logger.info(f'BestFilmVersion插件 item打印 {item_info_resp}')
"&SortOrder=Descending" \ if not item_info_resp:
"&Filters=IsFavorite" \
"&Recursive=true" \
"&Fields=PrimaryImageAspectRatio%2CBasicSyncInfo" \
"&CollapseBoxSetItems=false" \
"&ExcludeLocationTypes=Virtual" \
"&EnableTotalRecordCount=false" \
"&Limit=20&api_key={APIKEY}"
resp = self.get_items(Emby().get_data(url))
if not resp:
continue continue
all_item.extend(resp)
else: # 只接受Movie类型
resp = self.plex_get_watchlist() if data.get('Type') != 'Movie':
continue
# 获取tmdb_id
media_info_ids = item_info_resp.get('ExternalUrls')
if not media_info_ids:
continue
for media_info_id in media_info_ids:
if 'TheMovieDb' != media_info_id.get('Name'):
continue
tmdb_find_id = str(media_info_id.get('Url')).split('/')
tmdb_find_id.reverse()
tmdb_id = tmdb_find_id[0]
# 识别媒体信息
mediainfo: MediaInfo = self.chain.recognize_media(tmdbid=tmdb_id, mtype=MediaType.MOVIE)
if not mediainfo:
logger.warn(f'未识别到媒体信息,标题:{data.get("Name")}tmdbID{tmdb_id}')
continue
# 添加订阅
self.subscribechain.add(mtype=MediaType.MOVIE,
title=mediainfo.title,
year=mediainfo.year,
tmdbid=mediainfo.tmdb_id,
best_version=True,
username="收藏洗版",
exist_ok=True)
# 加入缓存
caches.append(data.get('Name'))
# 存储历史记录
if mediainfo.tmdb_id not in [h.get("tmdbid") for h in history]:
history.append({
"title": mediainfo.title,
"type": mediainfo.type.value,
"year": mediainfo.year,
"poster": mediainfo.get_poster_image(),
"overview": mediainfo.overview,
"tmdbid": mediainfo.tmdb_id,
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
})
# 保存历史记录
self.save_data('history', history)
# 保存缓存
self._cache_path.write_text("\n".join(caches))
finally:
lock.release()
def jellyfin_get_items(self, all_item):
# 获取所有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
for user in users:
# 根据加入日期 降序排序
url = "{HOST}Users/" + user + "/Items?SortBy=DateCreated%2CSortName" \
"&SortOrder=Descending" \
"&Filters=IsFavorite" \
"&Recursive=true" \
"&Fields=PrimaryImageAspectRatio%2CBasicSyncInfo" \
"&CollapseBoxSetItems=false" \
"&ExcludeLocationTypes=Virtual" \
"&EnableTotalRecordCount=false" \
"&Limit=20" \
"&apikey={APIKEY}"
resp = self.get_items(Jellyfin().get_data(url))
if not resp: if not resp:
return continue
all_item.extend(resp) all_item.extend(resp)
def function(y, x): def emby_get_items(self, all_item):
return y if (x['Name'] in [i['Name'] for i in y]) else (lambda z, u: (z.append(u), z))(y, x)[1] # 获取所有user
# all_item 根据电影名去重 get_users_url = "{HOST}Users?&api_key={APIKEY}"
result = reduce(function, all_item, []) users = self.get_users(Emby().get_data(get_users_url))
if not users:
for data in result: return
# 检查缓存 for user in users:
if data.get('Name') in caches: # 根据加入日期 降序排序
url = "{HOST}emby/Users/" + user + "/Items?SortBy=DateCreated%2CSortName" \
"&SortOrder=Descending" \
"&Filters=IsFavorite" \
"&Recursive=true" \
"&Fields=PrimaryImageAspectRatio%2CBasicSyncInfo" \
"&CollapseBoxSetItems=false" \
"&ExcludeLocationTypes=Virtual" \
"&EnableTotalRecordCount=false" \
"&Limit=20&api_key={APIKEY}"
resp = self.get_items(Emby().get_data(url))
if not resp:
continue continue
all_item.extend(resp)
# 获取详情
if settings.MEDIASERVER == 'jellyfin':
item_info_resp = Jellyfin().get_iteminfo(itemid=data.get('Id'))
elif settings.MEDIASERVER == 'emby':
item_info_resp = Emby().get_iteminfo(itemid=data.get('Id'))
else:
item_info_resp = self.plex_get_iteminfo(itemid=data.get('Id'))
logger.info(f'BestFilmVersion插件 item打印 {item_info_resp}')
if not item_info_resp:
continue
# 只接受Movie类型
if data.get('Type') != 'Movie':
continue
# 获取tmdb_id
media_info_ids = item_info_resp.get('ExternalUrls')
for media_info_id in media_info_ids:
if 'TheMovieDb' != media_info_id.get('Name'):
continue
tmdb_find_id = str(media_info_id.get('Url')).split('/')
tmdb_find_id.reverse()
tmdb_id = tmdb_find_id[0]
# 识别媒体信息
mediainfo: MediaInfo = self.chain.recognize_media(tmdbid=tmdb_id, mtype=MediaType.MOVIE)
if not mediainfo:
logger.warn(f'未识别到媒体信息,标题:{data.get("Name")}tmdbID{tmdb_id}')
continue
# 添加订阅
self.subscribechain.add(mtype=MediaType.MOVIE,
title=mediainfo.title,
year=mediainfo.year,
tmdbid=mediainfo.tmdb_id,
best_version=True,
username="收藏洗版",
exist_ok=True)
# 加入缓存
caches.append(data.get('Name'))
# 存储历史记录
if mediainfo.tmdb_id not in [h.get("tmdbid") for h in history]:
history.append({
"title": mediainfo.title,
"type": mediainfo.type.value,
"year": mediainfo.year,
"poster": mediainfo.get_poster_image(),
"overview": mediainfo.overview,
"tmdbid": mediainfo.tmdb_id,
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
})
# 保存历史记录
self.save_data('history', history)
# 保存缓存
self._cache_path.write_text("\n".join(caches))
@staticmethod @staticmethod
def get_items(resp: Response): def get_items(resp: Response):
@ -594,83 +612,98 @@ class BestFilmVersion(_PluginBase):
return return
data: WebhookEventInfo = event.event_data data: WebhookEventInfo = event.event_data
# 排除不是收藏调用
if data.channel not in ['jellyfin', 'emby', 'plex']:
return
if data.channel in ['emby', 'plex'] and data.event != 'item.rate':
return
if data.channel == 'jellyfin' and data.save_reason != 'UpdateUserRating':
return
logger.info(f'BestFilmVersion/webhook_message_action WebhookEventInfo打印{data}') logger.info(f'BestFilmVersion/webhook_message_action WebhookEventInfo打印{data}')
mediainfo: Optional[MediaInfo] = None # 获取锁
if not data.tmdb_id: _is_lock: bool = lock.acquire(timeout=60)
info = None if not _is_lock:
if data.channel == 'jellyfin' and data.save_reason == 'UpdateUserRating' and data.item_favorite:
info = Jellyfin().get_iteminfo(itemid=data.item_id)
if data.channel == 'emby' and data.event == 'item.rate':
info = Emby().get_iteminfo(itemid=data.item_id)
if data.channel == 'plex' and data.event == 'item.rate':
info = Plex().get_iteminfo(itemid=data.item_id)
logger.info(f'BestFilmVersion/webhook_message_action item打印{info}')
if not info:
return
if info['Type'] not in ['Movie', 'MOV', 'movie']:
return
# 获取tmdb_id
media_info_ids = info.get('ExternalUrls')
for media_info_id in media_info_ids:
if 'TheMovieDb' != media_info_id.get('Name'):
continue
tmdb_find_id = str(media_info_id.get('Url')).split('/')
tmdb_find_id.reverse()
tmdb_id = tmdb_find_id[0]
mediainfo = self.chain.recognize_media(tmdbid=tmdb_id, mtype=MediaType.MOVIE)
if not mediainfo:
logger.warn(f'未识别到媒体信息,标题:{data.item_name}tmdbID{tmdb_id}')
return
else:
if data.channel == 'jellyfin' and (data.save_reason != 'UpdateUserRating' or not data.item_favorite):
return
if data.channel == 'emby' and data.event != 'item.rate':
return
if data.channel == 'plex' and data.event != 'item.rate':
return
if data.item_type not in ['Movie', 'MOV', 'movie']:
return
mediainfo = self.chain.recognize_media(tmdbid=data.tmdb_id, mtype=MediaType.MOVIE)
if not mediainfo:
logger.warn(f'未识别到媒体信息,标题:{data.item_name}tmdbID{data.tmdb_id}')
return
# 读取缓存
caches = self._cache_path.read_text().split("\n") if self._cache_path.exists() else []
# 检查缓存
if mediainfo.title in caches:
return return
# 读取历史记录 try:
history = self.get_data('history') or []
# 添加订阅 mediainfo: Optional[MediaInfo] = None
self.subscribechain.add(mtype=MediaType.MOVIE, if not data.tmdb_id:
title=mediainfo.title, info = None
year=mediainfo.year, if data.channel == 'jellyfin' and data.save_reason == 'UpdateUserRating' and data.item_favorite:
tmdbid=mediainfo.tmdb_id, info = Jellyfin().get_iteminfo(itemid=data.item_id)
best_version=True, elif data.channel == 'emby' and data.event == 'item.rate':
username="收藏洗版", info = Emby().get_iteminfo(itemid=data.item_id)
exist_ok=True) elif data.channel == 'plex' and data.event == 'item.rate':
# 加入缓存 info = Plex().get_iteminfo(itemid=data.item_id)
caches.append(data.item_name) logger.info(f'BestFilmVersion/webhook_message_action item打印{info}')
# 存储历史记录
if mediainfo.tmdb_id not in [h.get("tmdbid") for h in history]: if not info:
history.append({ return
"title": mediainfo.title, if info['Type'] not in ['Movie', 'MOV', 'movie']:
"type": mediainfo.type.value, return
"year": mediainfo.year,
"poster": mediainfo.get_poster_image(), # 获取tmdb_id
"overview": mediainfo.overview, media_info_ids = info.get('ExternalUrls')
"tmdbid": mediainfo.tmdb_id, if not media_info_ids:
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S") return
}) for media_info_id in media_info_ids:
# 保存历史记录
self.save_data('history', history) if 'TheMovieDb' != media_info_id.get('Name'):
# 保存缓存 continue
self._cache_path.write_text("\n".join(caches))
tmdb_find_id = str(media_info_id.get('Url')).split('/')
tmdb_find_id.reverse()
tmdb_id = tmdb_find_id[0]
mediainfo = self.chain.recognize_media(tmdbid=tmdb_id, mtype=MediaType.MOVIE)
if not mediainfo:
logger.warn(f'未识别到媒体信息,标题:{data.item_name}tmdbID{tmdb_id}')
return
else:
if data.channel == 'jellyfin' and (data.save_reason != 'UpdateUserRating' or not data.item_favorite):
return
if data.item_type not in ['Movie', 'MOV', 'movie']:
return
mediainfo = self.chain.recognize_media(tmdbid=data.tmdb_id, mtype=MediaType.MOVIE)
if not mediainfo:
logger.warn(f'未识别到媒体信息,标题:{data.item_name}tmdbID{data.tmdb_id}')
return
if not mediainfo:
return
# 读取缓存
caches = self._cache_path.read_text().split("\n") if self._cache_path.exists() else []
# 检查缓存
if mediainfo.title in caches:
return
# 读取历史记录
history = self.get_data('history') or []
# 添加订阅
self.subscribechain.add(mtype=MediaType.MOVIE,
title=mediainfo.title,
year=mediainfo.year,
tmdbid=mediainfo.tmdb_id,
best_version=True,
username="收藏洗版",
exist_ok=True)
# 加入缓存
caches.append(data.item_name)
# 存储历史记录
if mediainfo.tmdb_id not in [h.get("tmdbid") for h in history]:
history.append({
"title": mediainfo.title,
"type": mediainfo.type.value,
"year": mediainfo.year,
"poster": mediainfo.get_poster_image(),
"overview": mediainfo.overview,
"tmdbid": mediainfo.tmdb_id,
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
})
# 保存历史记录
self.save_data('history', history)
# 保存缓存
self._cache_path.write_text("\n".join(caches))
finally:
lock.release()