Skip to content

Commit 56be5c9

Browse files
committed
fix: 合并冲突
2 parents 3f97c1b + 8bada58 commit 56be5c9

File tree

21 files changed

+1040
-327
lines changed

21 files changed

+1040
-327
lines changed

app/media/doubanapi/apiv2.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ class DoubanApi(object):
132132
"music_interests": "/music/%s/interests",
133133
"music_reviews": "/music/%s/reviews",
134134
"music_recommendations": "/music/%s/recommendations",
135+
136+
# doulist
137+
"doulist": "/doulist/",
138+
"doulist_items": "/doulist/%s/items",
135139
}
136140

137141
_user_agents = [
@@ -239,3 +243,122 @@ def tv_chinese_best_weekly(self, start=0, count=20, ts=datetime.strftime(datetim
239243

240244
def tv_global_best_weekly(self, start=0, count=20, ts=datetime.strftime(datetime.now(), '%Y%m%d')):
241245
return self.__invoke(self._urls["tv_global_best_weekly"], start=start, count=count, _ts=ts)
246+
247+
def doulist_detail(self, subject_id):
248+
"""
249+
豆列详情
250+
:param subject_id: 豆列id
251+
:return:
252+
{
253+
"is_follow": false,
254+
"screenshot_title": "分享海报",
255+
"playable_count": 1226,
256+
"screenshot_url": "douban:\/\/partial.douban.com\/screenshot\/doulist\/13712178\/_content",
257+
"create_time": "2014-10-05 10:41:22",
258+
"owner": {
259+
"kind": "user",
260+
"name": "依然饭特稀",
261+
"url": "https:\/\/www.douban.com\/people\/56698183\/",
262+
"uri": "douban:\/\/douban.com\/user\/56698183",
263+
"avatar": "https://img2.doubanio.com\/icon\/up56698183-12.jpg",
264+
"is_club": false,
265+
"type": "user",
266+
"id": "56698183",
267+
"uid": "yrftx"
268+
},
269+
"screenshot_type": "rexxar",
270+
"id": "13712178",
271+
"category": "movie",
272+
"is_merged_cover": false,
273+
"title": "评价人数超过十万的电影",
274+
"is_subject_selection": false,
275+
"followers_count": 53081,
276+
"is_private": false,
277+
"item_abstracts": [],
278+
"type": "doulist",
279+
"update_time": "2023-04-22 22:19:48",
280+
"list_type": "ugc_doulist",
281+
"tags": [],
282+
"syncing_note": null,
283+
"cover_url": "https://img9.doubanio.com\/view\/elanor_image\/raw\/public\/91314905.jpg",
284+
"header_bg_image": "",
285+
"doulist_type": "",
286+
"done_count": 0,
287+
"desc": "谢谢大家的关注和点赞,不过我更希望大家能在留言板上补充遗漏。\r\n看腻了豆瓣的评分排序,不如试试评价人数排序。评价人数并不代表作品的优劣,但是它起码说明了作品的存在感。这不一定是选电影最好的方法,却一定是选电影风险最小的方法。\r\n欢迎关注我关于读书的两个豆列: \r\n豆瓣评价人数超过一万的外文书籍 \r\nhttp:\/\/www.douban.com\/doulist\/37912871\/ \r\n豆瓣评价人数超过一万的中文书籍\r\nhttp:\/\/www.douban.com\/doulist\/36708212\/",
288+
"items_count": 1453,
289+
"wechat_timeline_share": "url",
290+
"url": "https:\/\/www.douban.com\/doulist\/13712178\/",
291+
"is_sys_private": false,
292+
"uri": "douban:\/\/douban.com\/doulist\/13712178",
293+
"sharing_url": "https:\/\/www.douban.com\/doulist\/13712178\/"
294+
}
295+
"""
296+
return self.__invoke(self._urls["doulist"] + subject_id)
297+
298+
def doulist_items(self, subject_id, start=0, count=20, ts=datetime.strftime(datetime.now(), '%Y%m%d')):
299+
"""
300+
豆列列表
301+
:param subject_id: 豆列id
302+
:param start: 开始
303+
:param count: 数量
304+
:param ts: 时间戳
305+
:return:
306+
{
307+
"count": 3,
308+
"start": 0,
309+
"total": 1453,
310+
"items": [{
311+
"comment": "",
312+
"rating": {
313+
"count": 2834097,
314+
"max": 10,
315+
"star_count": 5.0,
316+
"value": 9.7
317+
},
318+
"subtitle": "1994 \/ 美国 \/ 剧情 犯罪 \/ 弗兰克·德拉邦特 \/ 蒂姆·罗宾斯 摩根·弗里曼",
319+
"title": "肖申克的救赎",
320+
"url": "https:\/\/movie.douban.com\/subject\/1292052\/",
321+
"target_id": "1292052",
322+
"uri": "douban:\/\/douban.com\/movie\/1292052",
323+
"cover_url": "https:\/\/qnmob3.doubanio.com\/view\/photo\/m_ratio_poster\/public\/p480747492.jpg?imageView2\/2\/q\/80\/w\/300\/h\/300\/format\/jpg",
324+
"create_time": "2014-10-05 10:41:51",
325+
"type": "movie",
326+
"id": "19877287"
327+
}, {
328+
"comment": "",
329+
"rating": {
330+
"count": 2255839,
331+
"max": 10,
332+
"star_count": 4.5,
333+
"value": 9.4
334+
},
335+
"subtitle": "1994 \/ 法国 美国 \/ 剧情 动作 犯罪 \/ 吕克·贝松 \/ 让·雷诺 娜塔莉·波特曼",
336+
"title": "这个杀手不太冷",
337+
"url": "https:\/\/movie.douban.com\/subject\/1295644\/",
338+
"target_id": "1295644",
339+
"uri": "douban:\/\/douban.com\/movie\/1295644",
340+
"cover_url": "https:\/\/qnmob3.doubanio.com\/view\/photo\/m_ratio_poster\/public\/p511118051.jpg?imageView2\/2\/q\/80\/w\/300\/h\/300\/format\/jpg",
341+
"create_time": "2014-10-05 10:42:34",
342+
"type": "movie",
343+
"id": "19877286"
344+
}, {
345+
"comment": "",
346+
"rating": {
347+
"count": 2198702,
348+
"max": 10,
349+
"star_count": 4.5,
350+
"value": 9.4
351+
},
352+
"subtitle": "2001 \/ 日本 \/ 剧情 动画 奇幻 \/ 宫崎骏 \/ 柊瑠美 入野自由",
353+
"title": "千与千寻",
354+
"url": "https:\/\/movie.douban.com\/subject\/1291561\/",
355+
"target_id": "1291561",
356+
"uri": "douban:\/\/douban.com\/movie\/1291561",
357+
"cover_url": "https:\/\/qnmob3.doubanio.com\/view\/photo\/m_ratio_poster\/public\/p2557573348.jpg?imageView2\/2\/q\/80\/w\/300\/h\/300\/format\/jpg",
358+
"create_time": "2014-10-05 10:47:12",
359+
"type": "movie",
360+
"id": "19877280"
361+
}]
362+
}
363+
"""
364+
return self.__invoke(self._urls["doulist_items"] % subject_id, start=start, count=count, _ts=ts)

app/mediaserver/client/plex.py

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import os
12
from functools import lru_cache
2-
3+
from urllib.parse import quote_plus
34
import log
45
from app.mediaserver.client._base import _IMediaClient
56
from app.utils import ExceptionUtils
@@ -103,7 +104,7 @@ def get_activity_log(self, num):
103104
return []
104105
ret_array = []
105106
try:
106-
# type的含义: 1 电影 4 剧集单集
107+
# type的含义: 1 电影 4 剧集单集 详见 plexapi/utils.py中SEARCHTYPES的定义
107108
# 根据最后播放时间倒序获取数据
108109
historys = self._plex.library.search(sort='lastViewedAt:desc', limit=num, type='1,4')
109110
for his in historys:
@@ -291,11 +292,51 @@ def refresh_root_library(self):
291292

292293
def refresh_library_by_items(self, items):
293294
"""
294-
按类型、名称、年份来刷新媒体库,未找到对应的API,直接刷整个库
295+
按路径刷新媒体库
295296
"""
296297
if not self._plex:
297298
return False
298-
return self._plex.library.update()
299+
# _libraries可能未初始化,初始化一下
300+
if not self._libraries:
301+
try:
302+
self._libraries = self._plex.library.sections()
303+
except Exception as err:
304+
ExceptionUtils.exception_traceback(err)
305+
result_dict = {}
306+
for item in items:
307+
file_path = item.get("file_path")
308+
lib_key, path = self.__find_librarie(file_path, self._libraries)
309+
# 如果存在同一剧集的多集,key(path)相同会合并
310+
result_dict[path] = lib_key
311+
if "" in result_dict:
312+
# 如果有匹配失败的,刷新整个库
313+
self._plex.library.update()
314+
else:
315+
# 否则一个一个刷新
316+
for path, lib_key in result_dict.items():
317+
log.info(f"【{self.client_name}】刷新媒体库:{lib_key} : {path}")
318+
self._plex.query(f'/library/sections/{lib_key}/refresh?path={quote_plus(path)}')
319+
320+
@staticmethod
321+
def __find_librarie(path, libraries):
322+
"""
323+
判断这个path属于哪个媒体库
324+
多个媒体库配置的目录不应有重复和嵌套,
325+
使用os.path.commonprefix([path, location]) == location应该没问题
326+
"""
327+
if path is None:
328+
return "", ""
329+
# 只要路径,不要文件名
330+
dir_path = os.path.dirname(path)
331+
try:
332+
for lib in libraries:
333+
if hasattr(lib, "locations") and lib.locations:
334+
for location in lib.locations:
335+
if os.path.commonprefix([dir_path, location]) == location:
336+
return lib.key, dir_path
337+
except Exception as err:
338+
ExceptionUtils.exception_traceback(err)
339+
return "", ""
299340

300341
def get_libraries(self):
301342
"""
@@ -313,10 +354,10 @@ def get_libraries(self):
313354
match library.type:
314355
case "movie":
315356
library_type = MediaType.MOVIE.value
316-
image_list_str = self.get_libraries_image(library.key)
357+
image_list_str = self.get_libraries_image(library.key, 1)
317358
case "show":
318359
library_type = MediaType.TV.value
319-
image_list_str = self.get_libraries_image(library.key)
360+
image_list_str = self.get_libraries_image(library.key, 2)
320361
case _:
321362
continue
322363
libraries.append({
@@ -331,12 +372,18 @@ def get_libraries(self):
331372
return libraries
332373

333374
@lru_cache(maxsize=10)
334-
def get_libraries_image(self, library_key):
375+
def get_libraries_image(self, library_key, type):
376+
"""
377+
获取媒体服务器最近添加的媒体的图片列表
378+
param: library_key
379+
param: type type的含义: 1 电影 2 剧集 详见 plexapi/utils.py中SEARCHTYPES的定义
380+
"""
335381
if not self._plex:
336382
return ""
337-
library = self._plex.library.sectionByID(library_key)
338383
# 担心有些没图片,多获取几个
339-
items = library.recentlyAdded(maxresults=8)
384+
items = self._plex.fetchItems(f"/hubs/home/recentlyAdded?type={type}&sectionID={library_key}",
385+
container_size=8,
386+
container_start=0)
340387
poster_urls = []
341388
for item in items:
342389
if item.posterUrl is not None:
@@ -491,12 +538,7 @@ def get_resume(self, num=12):
491538
"""
492539
if not self._plex:
493540
return []
494-
items = self._plex.library.search(**{
495-
'sort': 'lastViewedAt:desc', # 按最后观看时间排序
496-
'type': '1,4', # 1 电影 4 剧集单集
497-
'viewOffset!': '0', # 播放进度不等于0的
498-
'limit': num # 限制结果数量
499-
})
541+
items = self._plex.fetchItems('/hubs/continueWatching/items', container_start=0, container_size=num)
500542
ret_resume = []
501543
for item in items:
502544
item_type = MediaType.MOVIE.value if item.TYPE == "movie" else MediaType.TV.value
@@ -525,14 +567,14 @@ def get_latest(self, num=20):
525567
"""
526568
if not self._plex:
527569
return []
528-
items = self._plex.library.recentlyAdded()
570+
items = self._plex.fetchItems('/library/recentlyAdded', container_start=0, container_size=num)
529571
ret_resume = []
530-
for item in items[:num]:
572+
for item in items:
531573
item_type = MediaType.MOVIE.value if item.TYPE == "movie" else MediaType.TV.value
532574
link = self.get_play_url(item.key)
533575
title = item.title if item_type == MediaType.MOVIE.value else \
534576
"%s 第%s季" % (item.parentTitle, item.index)
535-
image = self.get_nt_image_url(item.artUrl)
577+
image = self.get_nt_image_url(item.posterUrl)
536578
ret_resume.append({
537579
"id": item.key,
538580
"name": title,

0 commit comments

Comments
 (0)