|
"""
|
|
bilibili_api.favorite_list
|
|
|
|
收藏夹操作。
|
|
"""
|
|
|
|
from enum import Enum
|
|
from typing import List, Union, Optional
|
|
|
|
from . import user
|
|
from .video import Video
|
|
from .utils.utils import join, get_api, raise_for_statement
|
|
from .utils.credential import Credential
|
|
from .utils.network import Api
|
|
from .exceptions.ArgsException import ArgsException
|
|
|
|
API = get_api("favorite-list")
|
|
|
|
|
|
class FavoriteListContentOrder(Enum):
|
|
"""
|
|
收藏夹列表内容排序方式枚举。
|
|
|
|
+ MTIME : 最近收藏
|
|
+ VIEW : 最多播放
|
|
+ PUBTIME: 最新投稿
|
|
"""
|
|
|
|
MTIME = "mtime"
|
|
VIEW = "view"
|
|
PUBTIME = "pubtime"
|
|
|
|
|
|
class FavoriteListType(Enum):
|
|
"""
|
|
收藏夹类型枚举
|
|
|
|
+ VIDEO : 视频收藏夹
|
|
+ ARTICLE: 专栏收藏夹
|
|
+ CHEESE : 课程收藏夹
|
|
"""
|
|
|
|
VIDEO = "video"
|
|
ARTICLE = "articles"
|
|
CHEESE = "pugvfav"
|
|
|
|
|
|
class SearchFavoriteListMode(Enum):
|
|
"""
|
|
收藏夹搜索模式枚举
|
|
|
|
+ ONLY : 仅当前收藏夹
|
|
+ ALL : 该用户所有收藏夹
|
|
"""
|
|
|
|
ONLY = 0
|
|
ALL = 1
|
|
|
|
|
|
class FavoriteList:
|
|
"""
|
|
收藏夹类
|
|
|
|
Attributes:
|
|
credential (Credential): 凭据类
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
type_: FavoriteListType = FavoriteListType.VIDEO,
|
|
media_id: Union[int, None] = None,
|
|
credential: Union[Credential, None] = None,
|
|
) -> None:
|
|
"""
|
|
Args:
|
|
type_ (FavoriteListType, optional): 收藏夹类型. Defaults to FavoriteListType.VIDEO.
|
|
|
|
media_id (int, optional) : 收藏夹号(仅为视频收藏夹时提供). Defaults to None.
|
|
|
|
credential (Credential, optional) : 凭据类. Defaults to Credential().
|
|
"""
|
|
self.__type = type_
|
|
self.__media_id = media_id
|
|
self.credential = credential if credential else Credential()
|
|
|
|
def is_video_favorite_list(self) -> bool:
|
|
"""
|
|
收藏夹是否为视频收藏夹
|
|
|
|
Returns:
|
|
bool: 是否为视频收藏夹
|
|
"""
|
|
return self.__type == FavoriteListType.VIDEO
|
|
|
|
def get_media_id(self) -> Union[int, None]:
|
|
return self.__media_id
|
|
|
|
def get_favorite_list_type(self) -> FavoriteListType:
|
|
return self.__type
|
|
|
|
async def get_info(self):
|
|
"""
|
|
获取收藏夹信息。
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
raise_for_statement(self.__media_id != None, "视频收藏夹需要 media_id")
|
|
|
|
api = API["info"]["info"]
|
|
params = {"media_id": self.__media_id}
|
|
|
|
return (
|
|
await Api(**api, credential=self.credential).update_params(**params).result
|
|
)
|
|
|
|
async def get_content_video(
|
|
self,
|
|
page: int = 1,
|
|
keyword: Union[str, None] = None,
|
|
order: FavoriteListContentOrder = FavoriteListContentOrder.MTIME,
|
|
tid=0,
|
|
) -> dict:
|
|
"""
|
|
获取视频收藏夹内容。
|
|
|
|
Args:
|
|
page (int, optional) : 页码. Defaults to 1.
|
|
|
|
keyword (str | None, optional) : 搜索关键词. Defaults to None.
|
|
|
|
order (FavoriteListContentOrder, optional): 排序方式. Defaults to FavoriteListContentOrder.MTIME.
|
|
|
|
tid (int, optional) : 分区 ID. Defaults to 0.
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
raise_for_statement(self.__type == FavoriteListType.VIDEO, "此函数仅在收藏夹为视频收藏家时可用")
|
|
raise_for_statement(self.__media_id != None, "视频收藏夹需要 media_id")
|
|
|
|
return await get_video_favorite_list_content(
|
|
self.__media_id, page, keyword, order, tid, self.credential
|
|
)
|
|
|
|
async def get_content(self, page: int = 1) -> dict:
|
|
"""
|
|
获取收藏夹内容。
|
|
|
|
Args:
|
|
page (int, optional): 页码. Defaults to 1.
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
if self.__type == FavoriteListType.ARTICLE:
|
|
return await get_article_favorite_list(page, self.credential)
|
|
elif self.__type == FavoriteListType.CHEESE:
|
|
return await get_course_favorite_list(page, self.credential)
|
|
elif self.__type == FavoriteListType.VIDEO:
|
|
raise_for_statement(self.__media_id != None, "视频收藏夹需要 media_id")
|
|
return await get_video_favorite_list_content(
|
|
self.__media_id, page, credential=self.credential
|
|
)
|
|
else:
|
|
raise ArgsException("无法识别传入的类型")
|
|
|
|
async def get_content_ids_info(self) -> dict:
|
|
"""
|
|
获取收藏夹所有内容的 ID。
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
raise_for_statement(self.__media_id != None, "视频收藏夹需要 media_id")
|
|
|
|
api = API["info"]["list_content_id_list"]
|
|
params = {"media_id": self.__media_id}
|
|
|
|
return (
|
|
await Api(**api, credential=self.credential).update_params(**params).result
|
|
)
|
|
|
|
|
|
async def get_video_favorite_list(
|
|
uid: int,
|
|
video: Union[Video, None] = None,
|
|
credential: Union[Credential, None] = None,
|
|
) -> dict:
|
|
"""
|
|
获取视频收藏夹列表。
|
|
|
|
Args:
|
|
uid (int) : 用户 UID。
|
|
|
|
video (Video | None, optional): 视频类。若提供该参数则结果会附带该收藏夹是否存在该视频。Defaults to None.
|
|
|
|
credential (Credential | None, optional) : 凭据. Defaults to None.
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
api = API["info"]["list_list"]
|
|
params = {"up_mid": uid, "type": 2}
|
|
|
|
if video is not None:
|
|
params["rid"] = video.get_aid()
|
|
|
|
return await Api(**api, credential=credential).update_params(**params).result
|
|
|
|
|
|
async def get_video_favorite_list_content(
|
|
media_id: int,
|
|
page: int = 1,
|
|
keyword: Union[str, None] = None,
|
|
order: FavoriteListContentOrder = FavoriteListContentOrder.MTIME,
|
|
tid: int = 0,
|
|
mode: SearchFavoriteListMode = SearchFavoriteListMode.ONLY,
|
|
credential: Union[Credential, None] = None,
|
|
) -> dict:
|
|
"""
|
|
获取视频收藏夹列表内容,也可用于搜索收藏夹内容。
|
|
|
|
mode 参数见 SearchFavoriteListMode 枚举。
|
|
|
|
Args:
|
|
media_id (int) : 收藏夹 ID。
|
|
|
|
page (int, optional) : 页码. Defaults to 1.
|
|
|
|
keyword (str, optional) : 搜索关键词. Defaults to None.
|
|
|
|
order (FavoriteListContentOrder, optional): 排序方式. Defaults to FavoriteListContentOrder.MTIME.
|
|
|
|
tid (int, optional) : 分区 ID. Defaults to 0.
|
|
|
|
mode (SearchFavoriteListMode, optional) : 搜索模式,默认仅当前收藏夹.
|
|
|
|
credential (Credential, optional) : Credential. Defaults to None.
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
api = API["info"]["list_content"]
|
|
params = {
|
|
"media_id": media_id,
|
|
"pn": page,
|
|
"ps": 20,
|
|
"order": order.value,
|
|
"tid": tid,
|
|
"type": mode.value,
|
|
}
|
|
|
|
if keyword is not None:
|
|
params["keyword"] = keyword
|
|
|
|
return await Api(**api, credential=credential).update_params(**params).result
|
|
|
|
|
|
async def get_topic_favorite_list(
|
|
page: int = 1, credential: Union[None, Credential] = None
|
|
) -> dict:
|
|
"""
|
|
获取自己的话题收藏夹内容。
|
|
|
|
Args:
|
|
page (int, optional) : 页码. Defaults to 1.
|
|
|
|
credential (Credential | None, optional): Credential
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
if credential is None:
|
|
credential = Credential()
|
|
|
|
credential.raise_for_no_sessdata()
|
|
|
|
api = API["info"]["list_topics"]
|
|
params = {"page_num": page, "page_size": 16}
|
|
|
|
return await Api(**api, credential=credential).update_params(**params).result
|
|
|
|
|
|
async def get_article_favorite_list(
|
|
page: int = 1, credential: Union[None, Credential] = None
|
|
) -> dict:
|
|
"""
|
|
获取自己的专栏收藏夹内容。
|
|
|
|
Args:
|
|
page (int, optional) : 页码. Defaults to 1.
|
|
|
|
credential (Credential | None, optional): Credential. Defaults to None.
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
if credential is None:
|
|
credential = Credential()
|
|
|
|
credential.raise_for_no_sessdata()
|
|
|
|
api = API["info"]["list_articles"]
|
|
params = {"pn": page, "ps": 16}
|
|
|
|
return await Api(**api, credential=credential).update_params(**params).result
|
|
|
|
|
|
async def get_course_favorite_list(
|
|
page: int = 1, credential: Union[None, Credential] = None
|
|
) -> dict:
|
|
"""
|
|
获取自己的课程收藏夹内容。
|
|
|
|
Args:
|
|
page (int, optional) : 页码. Defaults to 1.
|
|
|
|
credential (Credential | None, optional): Credential. Defaults to None.
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
if credential is None:
|
|
credential = Credential()
|
|
|
|
credential.raise_for_no_sessdata()
|
|
|
|
api = API["info"]["list_courses"]
|
|
self_info = await user.get_self_info(credential)
|
|
params = {"pn": page, "ps": 10, "mid": self_info["mid"]}
|
|
|
|
return await Api(**api, credential=credential).update_params(**params).result
|
|
|
|
|
|
async def get_note_favorite_list(
|
|
page: int = 1, credential: Union[None, Credential] = None
|
|
) -> dict:
|
|
"""
|
|
获取自己的笔记收藏夹内容。
|
|
|
|
Args:
|
|
page (int, optional) : 页码. Defaults to 1.
|
|
|
|
credential (Credential | None, optional): Credential. Defaults to None.
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
if credential is None:
|
|
credential = Credential()
|
|
|
|
credential.raise_for_no_sessdata()
|
|
|
|
api = API["info"]["list_notes"]
|
|
params = {"pn": page, "ps": 16}
|
|
|
|
return await Api(**api, credential=credential).update_params(**params).result
|
|
|
|
|
|
async def create_video_favorite_list(
|
|
title: str,
|
|
introduction: str = "",
|
|
private: bool = False,
|
|
credential: Union[None, Credential] = None,
|
|
) -> dict:
|
|
"""
|
|
新建视频收藏夹列表。
|
|
|
|
Args:
|
|
title (str) : 收藏夹名。
|
|
|
|
introduction (str, optional) : 收藏夹简介. Defaults to ''.
|
|
|
|
private (bool, optional) : 是否为私有. Defaults to False.
|
|
|
|
credential (Credential, optional): 凭据. Defaults to None.
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
if credential is None:
|
|
credential = Credential()
|
|
|
|
credential.raise_for_no_sessdata()
|
|
credential.raise_for_no_bili_jct()
|
|
|
|
api = API["operate"]["new"]
|
|
data = {
|
|
"title": title,
|
|
"intro": introduction,
|
|
"privacy": 1 if private else 0,
|
|
"cover": "",
|
|
}
|
|
|
|
return await Api(**api, credential=credential).update_data(**data).result
|
|
|
|
|
|
async def modify_video_favorite_list(
|
|
media_id: int,
|
|
title: str,
|
|
introduction: str = "",
|
|
private: bool = False,
|
|
credential: Union[None, Credential] = None,
|
|
) -> dict:
|
|
"""
|
|
修改视频收藏夹信息。
|
|
|
|
Args:
|
|
media_id (int) : 收藏夹 ID.
|
|
|
|
title (str) : 收藏夹名。
|
|
|
|
introduction (str, optional) : 收藏夹简介. Defaults to ''.
|
|
|
|
private (bool, optional) : 是否为私有. Defaults to False.
|
|
|
|
credential (Credential, optional): Credential. Defaults to None.
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
|
|
if credential is None:
|
|
credential = Credential()
|
|
|
|
credential.raise_for_no_sessdata()
|
|
credential.raise_for_no_bili_jct()
|
|
|
|
api = API["operate"]["modify"]
|
|
data = {
|
|
"title": title,
|
|
"intro": introduction,
|
|
"privacy": 1 if private else 0,
|
|
"cover": "",
|
|
"media_id": media_id,
|
|
}
|
|
|
|
return await Api(**api, credential=credential).update_data(**data).result
|
|
|
|
|
|
async def delete_video_favorite_list(
|
|
media_ids: List[int], credential: Credential
|
|
) -> dict:
|
|
"""
|
|
删除视频收藏夹,可批量删除。
|
|
|
|
Args:
|
|
media_ids (List[int]) : 收藏夹 ID 列表。
|
|
|
|
credential (Credential): Credential.
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
|
|
credential.raise_for_no_sessdata()
|
|
credential.raise_for_no_bili_jct()
|
|
|
|
data = {"media_ids": join(",", media_ids)}
|
|
api = API["operate"]["delete"]
|
|
|
|
return await Api(**api, credential=credential).update_data(**data).result
|
|
|
|
|
|
async def copy_video_favorite_list_content(
|
|
media_id_from: int, media_id_to: int, aids: List[int], credential: Credential
|
|
) -> dict:
|
|
"""
|
|
复制视频收藏夹内容
|
|
|
|
Args:
|
|
media_id_from (int) : 要复制的源收藏夹 ID。
|
|
|
|
media_id_to (int) : 目标收藏夹 ID。
|
|
|
|
aids (List[int]) : 被复制的视频 ID 列表。
|
|
|
|
credential (Credential): 凭据
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
credential.raise_for_no_sessdata()
|
|
credential.raise_for_no_bili_jct()
|
|
api = API["operate"]["content_copy"]
|
|
|
|
self_info = await user.get_self_info(credential=credential)
|
|
|
|
data = {
|
|
"src_media_id": media_id_from,
|
|
"tar_media_id": media_id_to,
|
|
"mid": self_info["mid"],
|
|
"resources": ",".join(map(lambda x: f"{str(x)}:2", aids)),
|
|
}
|
|
|
|
return await Api(**api, credential=credential).update_data(**data).result
|
|
|
|
|
|
async def move_video_favorite_list_content(
|
|
media_id_from: int, media_id_to: int, aids: List[int], credential: Credential
|
|
) -> dict:
|
|
"""
|
|
移动视频收藏夹内容
|
|
|
|
Args:
|
|
media_id_from (int) : 要移动的源收藏夹 ID。
|
|
|
|
media_id_to (int) : 目标收藏夹 ID。
|
|
|
|
aids (List[int]) : 被移动的视频 ID 列表。
|
|
|
|
credential (Credential): 凭据
|
|
|
|
Returns:
|
|
dict: 调用 API 返回的结果
|
|
"""
|
|
credential.raise_for_no_sessdata()
|
|
credential.raise_for_no_bili_jct()
|
|
api = API["operate"]["content_move"]
|
|
|
|
data = {
|
|
"src_media_id": media_id_from,
|
|
"tar_media_id": media_id_to,
|
|
"resources": ",".join(map(lambda x: f"{str(x)}:2", aids)),
|
|
}
|
|
|
|
return await Api(**api, credential=credential).update_data(**data).result
|
|
|
|
|
|
async def delete_video_favorite_list_content(
|
|
media_id: int, aids: List[int], credential: Credential
|
|
) -> dict:
|
|
"""
|
|
删除视频收藏夹内容
|
|
|
|
Args:
|
|
media_id (int) : 收藏夹 ID。
|
|
|
|
aids (List[int]) : 被删除的视频 ID 列表。
|
|
|
|
credential (Credential): 凭据
|
|
|
|
Returns:
|
|
dict: API 调用结果。
|
|
"""
|
|
credential.raise_for_no_sessdata()
|
|
credential.raise_for_no_bili_jct()
|
|
api = API["operate"]["content_rm"]
|
|
|
|
data = {
|
|
"media_id": media_id,
|
|
"resources": ",".join(map(lambda x: f"{str(x)}:2", aids)),
|
|
}
|
|
|
|
return await Api(**api, credential=credential).update_data(**data).result
|
|
|
|
|
|
async def clean_video_favorite_list_content(
|
|
media_id: int, credential: Credential
|
|
) -> dict:
|
|
"""
|
|
清除视频收藏夹失效内容
|
|
|
|
Args:
|
|
media_id (int) : 收藏夹 ID
|
|
|
|
credential (Credential): 凭据
|
|
|
|
Returns:
|
|
dict: API 调用结果。
|
|
"""
|
|
credential.raise_for_no_sessdata()
|
|
credential.raise_for_no_bili_jct()
|
|
api = API["operate"]["content_clean"]
|
|
|
|
data = {"media_id": media_id}
|
|
|
|
return await Api(**api, credential=credential).update_data(**data).result
|
|
|
|
|
|
async def get_favorite_collected(
|
|
uid: int,
|
|
pn: int = 1,
|
|
ps: int = 20,
|
|
credential: Union[Credential, None] = None,
|
|
) -> dict:
|
|
"""
|
|
获取收藏合集列表
|
|
|
|
Args:
|
|
uid (int) : 用户 UID。
|
|
|
|
pn (int, optional) : 页码. Defaults to 1.
|
|
|
|
ps (int, optional) : 每页数据大小. Defaults to 20.
|
|
|
|
credential (Credential | None, optional) : Credential. Defaults to None.
|
|
"""
|
|
api = API["info"]["collected"]
|
|
params = {"up_mid": uid, "platform": "web", "pn": pn, "ps": ps}
|
|
return await Api(**api, credential=credential).update_params(**params).result
|
|
|