mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
feat: MediaServerItem新增用户播放状态、mediaserver.items()增加分页参数
This commit is contained in:
@@ -27,11 +27,17 @@ class MediaServerChain(ChainBase):
|
|||||||
"""
|
"""
|
||||||
return self.run_module("mediaserver_librarys", server=server, username=username, hidden=hidden)
|
return self.run_module("mediaserver_librarys", server=server, username=username, hidden=hidden)
|
||||||
|
|
||||||
def items(self, server: str, library_id: Union[str, int]) -> List[schemas.MediaServerItem]:
|
def items(self, server: str, library_id: Union[str, int], start_index: int = 0, limit: int = 100) -> List[schemas.MediaServerItem]:
|
||||||
"""
|
"""
|
||||||
获取媒体服务器所有项目
|
获取媒体服务器所有项目
|
||||||
"""
|
"""
|
||||||
return self.run_module("mediaserver_items", server=server, library_id=library_id)
|
data = []
|
||||||
|
data_generator = self.run_module("mediaserver_items", server=server, library_id=library_id, start_index=start_index, limit=limit)
|
||||||
|
if data_generator:
|
||||||
|
for item in data_generator:
|
||||||
|
if item:
|
||||||
|
data.append(item)
|
||||||
|
return data
|
||||||
|
|
||||||
def iteminfo(self, server: str, item_id: Union[str, int]) -> schemas.MediaServerItem:
|
def iteminfo(self, server: str, item_id: Union[str, int]) -> schemas.MediaServerItem:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -182,13 +182,13 @@ class EmbyModule(_ModuleBase, _MediaServerBase):
|
|||||||
return server.get_librarys(username=username, hidden=hidden)
|
return server.get_librarys(username=username, hidden=hidden)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mediaserver_items(self, server: str, library_id: str) -> Optional[Generator]:
|
def mediaserver_items(self, server: str, library_id: str, start_index: int = 0, limit: int = 100) -> Optional[Generator]:
|
||||||
"""
|
"""
|
||||||
媒体库项目列表
|
媒体库项目列表
|
||||||
"""
|
"""
|
||||||
server: Emby = self.get_server(server)
|
server: Emby = self.get_server(server)
|
||||||
if server:
|
if server:
|
||||||
return server.get_items(library_id)
|
return server.get_items(library_id, start_index, limit)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mediaserver_iteminfo(self, server: str, item_id: str) -> Optional[schemas.MediaServerItem]:
|
def mediaserver_iteminfo(self, server: str, item_id: str) -> Optional[schemas.MediaServerItem]:
|
||||||
|
|||||||
+76
-52
@@ -1,6 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional, Union, Dict, Generator, Tuple
|
from typing import List, Optional, Union, Dict, Generator, Tuple
|
||||||
|
|
||||||
@@ -352,7 +353,7 @@ class Emby:
|
|||||||
url = f"{self._host}emby/Items"
|
url = f"{self._host}emby/Items"
|
||||||
params = {
|
params = {
|
||||||
"IncludeItemTypes": "Movie",
|
"IncludeItemTypes": "Movie",
|
||||||
"Fields": "ProductionYear",
|
"Fields": "ProviderIds,OriginalTitle,ProductionYear,Path,UserDataPlayCount,UserDataLastPlayedDate,ParentId",
|
||||||
"StartIndex": 0,
|
"StartIndex": 0,
|
||||||
"Recursive": "true",
|
"Recursive": "true",
|
||||||
"SearchTerm": title,
|
"SearchTerm": title,
|
||||||
@@ -366,30 +367,15 @@ class Emby:
|
|||||||
res_items = res.json().get("Items")
|
res_items = res.json().get("Items")
|
||||||
if res_items:
|
if res_items:
|
||||||
ret_movies = []
|
ret_movies = []
|
||||||
for res_item in res_items:
|
for item in res_items:
|
||||||
item_tmdbid = res_item.get("ProviderIds", {}).get("Tmdb")
|
if not item:
|
||||||
mediaserver_item = schemas.MediaServerItem(
|
continue
|
||||||
server="emby",
|
mediaserver_item = self.__format_item_info(item)
|
||||||
library=res_item.get("ParentId"),
|
if mediaserver_item:
|
||||||
item_id=res_item.get("Id"),
|
if (not tmdb_id or mediaserver_item.tmdbid == tmdb_id) and \
|
||||||
item_type=res_item.get("Type"),
|
mediaserver_item.title == title and \
|
||||||
title=res_item.get("Name"),
|
(not year or str(mediaserver_item.year) == str(year)):
|
||||||
original_title=res_item.get("OriginalTitle"),
|
|
||||||
year=res_item.get("ProductionYear"),
|
|
||||||
tmdbid=int(item_tmdbid) if item_tmdbid else None,
|
|
||||||
imdbid=res_item.get("ProviderIds", {}).get("Imdb"),
|
|
||||||
tvdbid=res_item.get("ProviderIds", {}).get("Tvdb"),
|
|
||||||
path=res_item.get("Path")
|
|
||||||
)
|
|
||||||
if tmdb_id and item_tmdbid:
|
|
||||||
if str(item_tmdbid) != str(tmdb_id):
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
ret_movies.append(mediaserver_item)
|
ret_movies.append(mediaserver_item)
|
||||||
continue
|
|
||||||
if (mediaserver_item.title == title
|
|
||||||
and (not year or str(mediaserver_item.year) == str(year))):
|
|
||||||
ret_movies.append(mediaserver_item)
|
|
||||||
return ret_movies
|
return ret_movies
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"连接Items出错:" + str(e))
|
logger.error(f"连接Items出错:" + str(e))
|
||||||
@@ -615,6 +601,48 @@ class Emby:
|
|||||||
# 刷新根目录
|
# 刷新根目录
|
||||||
return "/"
|
return "/"
|
||||||
|
|
||||||
|
def __format_item_info(self, item) -> Optional[schemas.MediaServerItem]:
|
||||||
|
"""
|
||||||
|
格式化item
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
user_data = item.get("UserData", {})
|
||||||
|
if not user_data:
|
||||||
|
user_state = None
|
||||||
|
else:
|
||||||
|
resume = item.get("UserData", {}).get("PlaybackPositionTicks") and item.get("UserData", {}).get("PlaybackPositionTicks") > 0
|
||||||
|
last_played_date = item.get("UserData", {}).get("LastPlayedDate")
|
||||||
|
if last_played_date is not None and "." in last_played_date:
|
||||||
|
last_played_date = last_played_date.split(".")[0]
|
||||||
|
user_state = schemas.MediaServerItemUserState(
|
||||||
|
played=item.get("UserData", {}).get("Played"),
|
||||||
|
resume=resume,
|
||||||
|
last_played_date=datetime.strptime(last_played_date, "%Y-%m-%dT%H:%M:%S").strftime(
|
||||||
|
"%Y-%m-%d %H:%M:%S") if last_played_date else None,
|
||||||
|
play_count=item.get("UserData", {}).get("PlayCount"),
|
||||||
|
percentage=item.get("UserData", {}).get("PlayedPercentage"),
|
||||||
|
)
|
||||||
|
tmdbid = item.get("ProviderIds", {}).get("Tmdb")
|
||||||
|
return schemas.MediaServerItem(
|
||||||
|
id=item.get("Id"),
|
||||||
|
server="emby",
|
||||||
|
library=item.get("ParentId"),
|
||||||
|
item_id=item.get("Id"),
|
||||||
|
item_type=item.get("Type"),
|
||||||
|
title=item.get("Name"),
|
||||||
|
original_title=item.get("OriginalTitle"),
|
||||||
|
year=item.get("ProductionYear"),
|
||||||
|
tmdbid=int(tmdbid) if tmdbid else None,
|
||||||
|
imdbid=item.get("ProviderIds", {}).get("Imdb"),
|
||||||
|
tvdbid=item.get("ProviderIds", {}).get("Tvdb"),
|
||||||
|
path=item.get("Path"),
|
||||||
|
user_state=user_state
|
||||||
|
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
return None
|
||||||
|
|
||||||
def get_iteminfo(self, itemid: str) -> Optional[schemas.MediaServerItem]:
|
def get_iteminfo(self, itemid: str) -> Optional[schemas.MediaServerItem]:
|
||||||
"""
|
"""
|
||||||
获取单个项目详情
|
获取单个项目详情
|
||||||
@@ -630,28 +658,19 @@ class Emby:
|
|||||||
try:
|
try:
|
||||||
res = RequestUtils().get_res(url, params)
|
res = RequestUtils().get_res(url, params)
|
||||||
if res and res.status_code == 200:
|
if res and res.status_code == 200:
|
||||||
item = res.json()
|
iteminfo = self.__format_item_info(res.json())
|
||||||
tmdbid = item.get("ProviderIds", {}).get("Tmdb")
|
return iteminfo
|
||||||
return schemas.MediaServerItem(
|
|
||||||
server="emby",
|
|
||||||
library=item.get("ParentId"),
|
|
||||||
item_id=item.get("Id"),
|
|
||||||
item_type=item.get("Type"),
|
|
||||||
title=item.get("Name"),
|
|
||||||
original_title=item.get("OriginalTitle"),
|
|
||||||
year=item.get("ProductionYear"),
|
|
||||||
tmdbid=int(tmdbid) if tmdbid else None,
|
|
||||||
imdbid=item.get("ProviderIds", {}).get("Imdb"),
|
|
||||||
tvdbid=item.get("ProviderIds", {}).get("Tvdb"),
|
|
||||||
path=item.get("Path")
|
|
||||||
)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"连接Items/Id出错:" + str(e))
|
logger.error(f"连接/Users/{self.user}/Items/{itemid}出错:" + str(e))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_items(self, parent: str) -> Generator:
|
def get_items(self, parent: str, start_index: int = 0, limit: int = 100) -> Generator:
|
||||||
"""
|
"""
|
||||||
获取媒体服务器所有媒体库列表
|
获取媒体服务器所有媒体库列表
|
||||||
|
:param parent: 父媒体库ID
|
||||||
|
:param start_index: 开始索引,用于分页
|
||||||
|
:param limit: 每次请求返回的项目数量
|
||||||
|
:return: 生成器 schemas.MediaServerItem
|
||||||
"""
|
"""
|
||||||
if not parent:
|
if not parent:
|
||||||
yield None
|
yield None
|
||||||
@@ -660,20 +679,25 @@ class Emby:
|
|||||||
url = f"{self._host}emby/Users/{self.user}/Items"
|
url = f"{self._host}emby/Users/{self.user}/Items"
|
||||||
params = {
|
params = {
|
||||||
"ParentId": parent,
|
"ParentId": parent,
|
||||||
"api_key": self._apikey
|
"api_key": self._apikey,
|
||||||
|
"Fields": "ProviderIds,OriginalTitle,ProductionYear,Path,UserDataPlayCount,UserDataLastPlayedDate,ParentId",
|
||||||
|
"StartIndex": start_index,
|
||||||
|
"Limit": limit
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
res = RequestUtils().get_res(url, params)
|
res = RequestUtils().get_res(url, params)
|
||||||
if res and res.status_code == 200:
|
if not res or res.status_code != 200:
|
||||||
results = res.json().get("Items") or []
|
yield None
|
||||||
for result in results:
|
items = res.json().get("Items") or []
|
||||||
if not result:
|
for item in items:
|
||||||
continue
|
if not item:
|
||||||
if result.get("Type") in ["Movie", "Series"]:
|
continue
|
||||||
yield self.get_iteminfo(result.get("Id"))
|
if "Folder" in item.get("Type"):
|
||||||
elif "Folder" in result.get("Type"):
|
for items in self.get_items(parent=item.get('Id')):
|
||||||
for item in self.get_items(parent=result.get('Id')):
|
yield items
|
||||||
yield item
|
elif item.get("Type") in ["Movie", "Series"]:
|
||||||
|
yield self.__format_item_info(item)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"连接Users/Items出错:" + str(e))
|
logger.error(f"连接Users/Items出错:" + str(e))
|
||||||
yield None
|
yield None
|
||||||
|
|||||||
@@ -180,13 +180,13 @@ class JellyfinModule(_ModuleBase, _MediaServerBase):
|
|||||||
return server.get_librarys(username=username, hidden=hidden)
|
return server.get_librarys(username=username, hidden=hidden)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mediaserver_items(self, server: str, library_id: str) -> Optional[Generator]:
|
def mediaserver_items(self, server: str, library_id: str, start_index: int = 0, limit: int = 100) -> Optional[Generator]:
|
||||||
"""
|
"""
|
||||||
媒体库项目列表
|
媒体库项目列表
|
||||||
"""
|
"""
|
||||||
server: Jellyfin = self.get_server(server)
|
server: Jellyfin = self.get_server(server)
|
||||||
if server:
|
if server:
|
||||||
return server.get_items(library_id)
|
return server.get_items(library_id, start_index, limit)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mediaserver_iteminfo(self, server: str, item_id: str) -> Optional[schemas.MediaServerItem]:
|
def mediaserver_iteminfo(self, server: str, item_id: str) -> Optional[schemas.MediaServerItem]:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
|
from datetime import datetime
|
||||||
from typing import List, Union, Optional, Dict, Generator, Tuple
|
from typing import List, Union, Optional, Dict, Generator, Tuple
|
||||||
|
|
||||||
from requests import Response
|
from requests import Response
|
||||||
@@ -345,6 +346,8 @@ class Jellyfin:
|
|||||||
url = f"{self._host}Users/{self.user}/Items"
|
url = f"{self._host}Users/{self.user}/Items"
|
||||||
params = {
|
params = {
|
||||||
"IncludeItemTypes": "Movie",
|
"IncludeItemTypes": "Movie",
|
||||||
|
"Fields": "ProviderIds,OriginalTitle,ProductionYear,Path,UserDataPlayCount,UserDataLastPlayedDate,ParentId",
|
||||||
|
"StartIndex": 0,
|
||||||
"Recursive": "true",
|
"Recursive": "true",
|
||||||
"searchTerm": title,
|
"searchTerm": title,
|
||||||
"Limit": 10,
|
"Limit": 10,
|
||||||
@@ -357,29 +360,14 @@ class Jellyfin:
|
|||||||
if res_items:
|
if res_items:
|
||||||
ret_movies = []
|
ret_movies = []
|
||||||
for item in res_items:
|
for item in res_items:
|
||||||
item_tmdbid = item.get("ProviderIds", {}).get("Tmdb")
|
if not item:
|
||||||
mediaserver_item = schemas.MediaServerItem(
|
continue
|
||||||
server="jellyfin",
|
mediaserver_item = self.__format_item_info(item)
|
||||||
library=item.get("ParentId"),
|
if mediaserver_item:
|
||||||
item_id=item.get("Id"),
|
if (not tmdb_id or mediaserver_item.tmdbid == tmdb_id) and \
|
||||||
item_type=item.get("Type"),
|
mediaserver_item.title == title and \
|
||||||
title=item.get("Name"),
|
(not year or str(mediaserver_item.year) == str(year)):
|
||||||
original_title=item.get("OriginalTitle"),
|
|
||||||
year=item.get("ProductionYear"),
|
|
||||||
tmdbid=int(item_tmdbid) if item_tmdbid else None,
|
|
||||||
imdbid=item.get("ProviderIds", {}).get("Imdb"),
|
|
||||||
tvdbid=item.get("ProviderIds", {}).get("Tvdb"),
|
|
||||||
path=item.get("Path")
|
|
||||||
)
|
|
||||||
if tmdb_id and item_tmdbid:
|
|
||||||
if str(item_tmdbid) != str(tmdb_id):
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
ret_movies.append(mediaserver_item)
|
ret_movies.append(mediaserver_item)
|
||||||
continue
|
|
||||||
if mediaserver_item.title == title and (
|
|
||||||
not year or str(mediaserver_item.year) == str(year)):
|
|
||||||
ret_movies.append(mediaserver_item)
|
|
||||||
return ret_movies
|
return ret_movies
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"连接Items出错:" + str(e))
|
logger.error(f"连接Items出错:" + str(e))
|
||||||
@@ -674,6 +662,49 @@ class Jellyfin:
|
|||||||
|
|
||||||
return eventItem
|
return eventItem
|
||||||
|
|
||||||
|
|
||||||
|
def __format_item_info(self, item) -> Optional[schemas.MediaServerItem]:
|
||||||
|
"""
|
||||||
|
格式化item
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
user_data = item.get("UserData", {})
|
||||||
|
if not user_data:
|
||||||
|
user_state = None
|
||||||
|
else:
|
||||||
|
resume = item.get("UserData", {}).get("PlaybackPositionTicks") and item.get("UserData", {}).get("PlaybackPositionTicks") > 0
|
||||||
|
last_played_date = item.get("UserData", {}).get("LastPlayedDate")
|
||||||
|
if last_played_date is not None and "." in last_played_date:
|
||||||
|
last_played_date = last_played_date.split(".")[0]
|
||||||
|
user_state = schemas.MediaServerItemUserState(
|
||||||
|
played=item.get("UserData", {}).get("Played"),
|
||||||
|
resume=resume,
|
||||||
|
last_played_date=datetime.strptime(last_played_date, "%Y-%m-%dT%H:%M:%S").strftime(
|
||||||
|
"%Y-%m-%d %H:%M:%S") if last_played_date else None,
|
||||||
|
play_count=item.get("UserData", {}).get("PlayCount"),
|
||||||
|
percentage=item.get("UserData", {}).get("PlayedPercentage"),
|
||||||
|
)
|
||||||
|
tmdbid = item.get("ProviderIds", {}).get("Tmdb")
|
||||||
|
return schemas.MediaServerItem(
|
||||||
|
server="jellyfin",
|
||||||
|
id=item.get("Id"),
|
||||||
|
library=item.get("ParentId"),
|
||||||
|
item_id=item.get("Id"),
|
||||||
|
item_type=item.get("Type"),
|
||||||
|
title=item.get("Name"),
|
||||||
|
original_title=item.get("OriginalTitle"),
|
||||||
|
year=item.get("ProductionYear"),
|
||||||
|
tmdbid=int(tmdbid) if tmdbid else None,
|
||||||
|
imdbid=item.get("ProviderIds", {}).get("Imdb"),
|
||||||
|
tvdbid=item.get("ProviderIds", {}).get("Tvdb"),
|
||||||
|
path=item.get("Path"),
|
||||||
|
user_state=user_state
|
||||||
|
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
return None
|
||||||
|
|
||||||
def get_iteminfo(self, itemid: str) -> Optional[schemas.MediaServerItem]:
|
def get_iteminfo(self, itemid: str) -> Optional[schemas.MediaServerItem]:
|
||||||
"""
|
"""
|
||||||
获取单个项目详情
|
获取单个项目详情
|
||||||
@@ -689,28 +720,18 @@ class Jellyfin:
|
|||||||
try:
|
try:
|
||||||
res = RequestUtils().get_res(url, params)
|
res = RequestUtils().get_res(url, params)
|
||||||
if res and res.status_code == 200:
|
if res and res.status_code == 200:
|
||||||
item = res.json()
|
return self.__format_item_info(res.json())
|
||||||
tmdbid = item.get("ProviderIds", {}).get("Tmdb")
|
|
||||||
return schemas.MediaServerItem(
|
|
||||||
server="jellyfin",
|
|
||||||
library=item.get("ParentId"),
|
|
||||||
item_id=item.get("Id"),
|
|
||||||
item_type=item.get("Type"),
|
|
||||||
title=item.get("Name"),
|
|
||||||
original_title=item.get("OriginalTitle"),
|
|
||||||
year=item.get("ProductionYear"),
|
|
||||||
tmdbid=int(tmdbid) if tmdbid else None,
|
|
||||||
imdbid=item.get("ProviderIds", {}).get("Imdb"),
|
|
||||||
tvdbid=item.get("ProviderIds", {}).get("Tvdb"),
|
|
||||||
path=item.get("Path")
|
|
||||||
)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"连接Users/Items出错:" + str(e))
|
logger.error(f"连接Users/{self.user}/Items/{itemid}:" + str(e))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_items(self, parent: str) -> Generator:
|
def get_items(self, parent: str, start_index: int = 0, limit: int = 100) -> Generator:
|
||||||
"""
|
"""
|
||||||
获取媒体服务器所有媒体库列表
|
获取媒体服务器所有媒体库列表
|
||||||
|
:param parent: 父媒体库ID
|
||||||
|
:param start_index: 开始索引,用于分页
|
||||||
|
:param limit: 每次请求返回的项目数量
|
||||||
|
:return: 生成器 schemas.MediaServerItem
|
||||||
"""
|
"""
|
||||||
if not parent:
|
if not parent:
|
||||||
yield None
|
yield None
|
||||||
@@ -719,20 +740,24 @@ class Jellyfin:
|
|||||||
url = f"{self._host}Users/{self.user}/Items"
|
url = f"{self._host}Users/{self.user}/Items"
|
||||||
params = {
|
params = {
|
||||||
"parentId": parent,
|
"parentId": parent,
|
||||||
"api_key": self._apikey
|
"api_key": self._apikey,
|
||||||
|
"Fields": "ProviderIds,OriginalTitle,ProductionYear,Path,UserDataPlayCount,UserDataLastPlayedDate,ParentId",
|
||||||
|
"StartIndex": start_index,
|
||||||
|
"Limit": limit,
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
res = RequestUtils().get_res(url, params)
|
res = RequestUtils().get_res(url, params)
|
||||||
if res and res.status_code == 200:
|
if not res or res.status_code != 200:
|
||||||
results = res.json().get("Items") or []
|
yield None
|
||||||
for result in results:
|
items = res.json().get("Items") or []
|
||||||
if not result:
|
for item in items:
|
||||||
continue
|
if not item:
|
||||||
if result.get("Type") in ["Movie", "Series"]:
|
continue
|
||||||
yield self.get_iteminfo(result.get("Id"))
|
if "Folder" in item.get("Type"):
|
||||||
elif "Folder" in result.get("Type"):
|
for items in self.get_items(item.get("Id")):
|
||||||
for item in self.get_items(result.get("Id")):
|
yield items
|
||||||
yield item
|
elif item.get("Type") in ["Movie", "Series"]:
|
||||||
|
yield self.__format_item_info(item)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"连接Users/Items出错:" + str(e))
|
logger.error(f"连接Users/Items出错:" + str(e))
|
||||||
yield None
|
yield None
|
||||||
|
|||||||
@@ -168,13 +168,13 @@ class PlexModule(_ModuleBase, _MediaServerBase):
|
|||||||
return server.get_librarys(hidden)
|
return server.get_librarys(hidden)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mediaserver_items(self, server: str, library_id: str) -> Optional[Generator]:
|
def mediaserver_items(self, server: str, library_id: str, start_index: int = 0, limit: int = 100) -> Optional[Generator]:
|
||||||
"""
|
"""
|
||||||
媒体库项目列表
|
媒体库项目列表
|
||||||
"""
|
"""
|
||||||
server: Plex = self.get_server(server)
|
server: Plex = self.get_server(server)
|
||||||
if server:
|
if server:
|
||||||
return server.get_items(library_id)
|
return server.get_items(library_id, start_index, limit)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mediaserver_iteminfo(self, server: str, item_id: str) -> Optional[schemas.MediaServerItem]:
|
def mediaserver_iteminfo(self, server: str, item_id: str) -> Optional[schemas.MediaServerItem]:
|
||||||
|
|||||||
@@ -446,9 +446,13 @@ class Plex:
|
|||||||
|
|
||||||
return ids
|
return ids
|
||||||
|
|
||||||
def get_items(self, parent: str) -> Generator:
|
def get_items(self, parent: str, start_index: int = 0, limit: int = 100) -> Generator:
|
||||||
"""
|
"""
|
||||||
获取媒体服务器所有媒体库列表
|
获取媒体服务器所有媒体库列表
|
||||||
|
:param parent: 父媒体库ID
|
||||||
|
:param start_index: 开始索引,用于分页
|
||||||
|
:param limit: 每次请求返回的项目数量
|
||||||
|
:return: 生成器 schemas.MediaServerItem
|
||||||
"""
|
"""
|
||||||
if not parent:
|
if not parent:
|
||||||
yield None
|
yield None
|
||||||
@@ -457,7 +461,7 @@ class Plex:
|
|||||||
try:
|
try:
|
||||||
section = self._plex.library.sectionByID(int(parent))
|
section = self._plex.library.sectionByID(int(parent))
|
||||||
if section:
|
if section:
|
||||||
for item in section.all():
|
for item in section.all(container_start=start_index, limit=limit):
|
||||||
try:
|
try:
|
||||||
if not item:
|
if not item:
|
||||||
continue
|
continue
|
||||||
@@ -465,7 +469,22 @@ class Plex:
|
|||||||
path = None
|
path = None
|
||||||
if item.locations:
|
if item.locations:
|
||||||
path = item.locations[0]
|
path = item.locations[0]
|
||||||
|
playback_position = item.viewOffset if hasattr(item, 'viewOffset') else 0
|
||||||
|
duration = item.duration if hasattr(item, 'duration') else 0
|
||||||
|
percentage = (playback_position / duration * 100) if duration > 0 else None
|
||||||
|
played = item.isPlayed if hasattr(item, 'isPlayed') else False
|
||||||
|
play_count = item.viewCount if hasattr(item, 'viewCount') else 0
|
||||||
|
last_played_date = item.lastViewedAt if hasattr(item, 'lastViewedAt') else None
|
||||||
|
user_state = schemas.MediaServerItemUserState(
|
||||||
|
played=played,
|
||||||
|
resume=playback_position > 0,
|
||||||
|
last_played_date=last_played_date.isoformat() if last_played_date else None,
|
||||||
|
play_count=play_count,
|
||||||
|
percentage=percentage,
|
||||||
|
)
|
||||||
|
|
||||||
yield schemas.MediaServerItem(
|
yield schemas.MediaServerItem(
|
||||||
|
id=item.ratingKey,
|
||||||
server="plex",
|
server="plex",
|
||||||
library=item.librarySectionID,
|
library=item.librarySectionID,
|
||||||
item_id=item.key,
|
item_id=item.key,
|
||||||
@@ -477,6 +496,7 @@ class Plex:
|
|||||||
imdbid=ids['imdb_id'],
|
imdbid=ids['imdb_id'],
|
||||||
tvdbid=ids['tvdb_id'],
|
tvdbid=ids['tvdb_id'],
|
||||||
path=path,
|
path=path,
|
||||||
|
user_state=user_state,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"处理媒体项目时出错:{str(e)}, 跳过此项目。")
|
logger.error(f"处理媒体项目时出错:{str(e)}, 跳过此项目。")
|
||||||
|
|||||||
@@ -72,6 +72,19 @@ class MediaServerLibrary(BaseModel):
|
|||||||
link: Optional[str] = None
|
link: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MediaServerItemUserState(BaseModel):
|
||||||
|
# 已播放
|
||||||
|
played: Optional[bool] = None
|
||||||
|
# 继续播放
|
||||||
|
resume: Optional[bool] = None
|
||||||
|
# 上次播放时间 10位时间戳
|
||||||
|
last_played_date: Optional[str] = None
|
||||||
|
# 播放次数(不等于完播次数,理解为浏览次数)
|
||||||
|
play_count: Optional[int] = None
|
||||||
|
# 播放进度
|
||||||
|
percentage: Optional[float] = None
|
||||||
|
|
||||||
class MediaServerItem(BaseModel):
|
class MediaServerItem(BaseModel):
|
||||||
"""
|
"""
|
||||||
媒体服务器媒体信息
|
媒体服务器媒体信息
|
||||||
@@ -106,6 +119,7 @@ class MediaServerItem(BaseModel):
|
|||||||
note: Optional[str] = None
|
note: Optional[str] = None
|
||||||
# 同步时间
|
# 同步时间
|
||||||
lst_mod_date: Optional[str] = None
|
lst_mod_date: Optional[str] = None
|
||||||
|
user_state: Optional[MediaServerItemUserState] = None
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
orm_mode = True
|
orm_mode = True
|
||||||
|
|||||||
Reference in New Issue
Block a user