Skip to content

Commit

Permalink
feat: get_reaction & rm get_info_opus, prepare for module opus
Browse files Browse the repository at this point in the history
  • Loading branch information
Nemo2011 committed Jan 30, 2024
1 parent 6cff631 commit 55a51c6
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 158 deletions.
14 changes: 2 additions & 12 deletions bilibili_api/article.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ class ArticleType(Enum):
"""
专栏类型
- ARTICLE : 普通专栏,不与 opus 动态兼容
- ARTICLE : 普通专栏,不与 opus 图文兼容
- NOTE : 公开笔记
- SPECIAL_ARTICLE: 特殊专栏,采用笔记格式,且与 opus 动态完全兼容
- SPECIAL_ARTICLE: 特殊专栏,采用笔记格式,且与 opus 图文完全兼容
"""

ARTICLE = 0
Expand Down Expand Up @@ -188,16 +188,6 @@ def __init__(self, cvid: int, credential: Union[Credential, None] = None):
)
self.__dyn_id = int(initial_state[0]["readInfo"]["dyn_id_str"])

def turn_to_dynamic(self) -> "dynamic.Dynamic":
"""
对于完全与 opus 兼容的部分的特殊专栏,将 Article 对象转换为 Dynamic 对象。
Returns:
Dynamic: Dynamic 对象
"""
raise_for_statement(self.__type == ArticleType.SPECIAL_ARTICLE, "仅支持特殊专栏 (ArticleType.SPECIAL_ARTICLE)")
return dynamic.Dynamic(self.__dyn_id, credential=self.credential)

def get_cvid(self) -> int:
return self.__cvid

Expand Down
12 changes: 6 additions & 6 deletions bilibili_api/data/api/dynamic.json
Original file line number Diff line number Diff line change
Expand Up @@ -199,15 +199,15 @@
},
"comment": "动态详细信息"
},
"detail_new": {
"url": "https://api.bilibili.com/x/polymer/web-dynamic/v1/opus/detail",
"reaction": {
"url": "https://api.bilibili.com/x/polymer/web-dynamic/v1/detail/reaction",
"method": "GET",
"verify": false,
"params": {
"timezone_offset": "int: 时区偏移量",
"id": "int: 动态 ID"
},
"comment": "动态详细信息"
"web_location": "str: 333.1369",
"id": "int: 动态 ID",
"offset": "str: 空"
}
},
"dynamic_page_UPs_info": {
"url": "https://api.bilibili.com/x/polymer/web-dynamic/v1/portal",
Expand Down
35 changes: 35 additions & 0 deletions bilibili_api/data/api/opus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"info": {
"detail_new": {
"url": "https://api.bilibili.com/x/polymer/web-dynamic/v1/opus/detail",
"method": "GET",
"verify": false,
"params": {
"timezone_offset": "int: 时区偏移量",
"id": "int: 动态 ID"
},
"comment": "动态详细信息"
}
},
"operate": {
"simple_action": {
"url": "https://api.bilibili.com/x/community/cosmo/interface/simple_action",
"method": "POST",
"verify": true,
"data": {
"meta": {
"spmid": "444.42.0.0",
"from_spmid": "333.1365.0.0",
"from": "unknown"
},
"entity": {
"object_id_str": "890484395664736288",
"type": { "biz": 2 }
},
"action": 4
},
"json_body": true,
"comment": "收藏/取消收藏"
}
}
}
103 changes: 53 additions & 50 deletions bilibili_api/dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class DynamicType(Enum):
VIDEO = "video"


class SendDynmaicType(Enum):
class SendDynamicType(Enum):
"""
发送动态类型
scene 参数
Expand All @@ -58,7 +58,7 @@ class SendDynmaicType(Enum):
IMAGE = 2


class DynmaicContentType(Enum):
class DynamicContentType(Enum):
"""
动态内容类型
Expand All @@ -74,6 +74,18 @@ class DynmaicContentType(Enum):
VOTE = 4


class DynamicType(Enum):
"""
动态类型
+ NORMAL: 普通动态 (链接为 https://t.bilibili.com/***)
+ OPUS: 图文动态 (链接为 https://www.bilibili.com/opus/***)
"""

NORMAL = "normal"
OPUS = "opus"


async def _parse_at(text: str) -> Tuple[str, str, str]:
"""
@人格式:“@用户名 ”(注意最后有空格)
Expand Down Expand Up @@ -243,7 +255,7 @@ def upload_image_sync(
return return_info


class BuildDynmaic:
class BuildDynamic:
"""
构建动态内容. 提供两种 API.
Expand Down Expand Up @@ -276,7 +288,7 @@ def empty():
"""
新建空的动态以链式逐步构建
"""
return BuildDynmaic()
return BuildDynamic()

@staticmethod
def create_by_args(
Expand All @@ -303,7 +315,7 @@ def create_by_args(
send_time (datetime | None, optional): 发送时间. Defaults to None.
"""
dyn = BuildDynmaic()
dyn = BuildDynamic()
dyn.add_text(text)
dyn.add_image(pics)
if topic_id != -1:
Expand All @@ -316,19 +328,19 @@ def create_by_args(
dyn.set_send_time(send_time)
return dyn

def add_plain_text(self, text: str) -> "BuildDynmaic":
def add_plain_text(self, text: str) -> "BuildDynamic":
"""
添加纯文本
Args:
text (str): 文本内容
"""
self.contents.append(
{"biz_id": "", "type": DynmaicContentType.TEXT.value, "raw_text": text}
{"biz_id": "", "type": DynamicContentType.TEXT.value, "raw_text": text}
)
return self

def add_at(self, uid: Union[int, user.User]) -> "BuildDynmaic":
def add_at(self, uid: Union[int, user.User]) -> "BuildDynamic":
"""
添加@用户,支持传入 User 类或 UID
Expand All @@ -339,11 +351,11 @@ def add_at(self, uid: Union[int, user.User]) -> "BuildDynmaic":
uid = uid.__uid
name = user.User(uid).get_user_info_sync().get("name")
self.contents.append(
{"biz_id": uid, "type": DynmaicContentType.AT.value, "raw_text": f"@{name}"}
{"biz_id": uid, "type": DynamicContentType.AT.value, "raw_text": f"@{name}"}
)
return self

def add_emoji(self, emoji_id: int) -> "BuildDynmaic":
def add_emoji(self, emoji_id: int) -> "BuildDynamic":
"""
添加表情
Expand All @@ -359,24 +371,24 @@ def add_emoji(self, emoji_id: int) -> "BuildDynmaic":
self.contents.append(
{
"biz_id": "",
"type": DynmaicContentType.EMOJI.value,
"type": DynamicContentType.EMOJI.value,
"raw_text": emote_info[str(emoji_id)],
}
)
return self

def add_vote(self, vote: vote.Vote) -> "BuildDynmaic":
def add_vote(self, vote: vote.Vote) -> "BuildDynamic":
vote.get_info_sync()
self.contents.append(
{
"biz_id": str(vote.get_vote_id()),
"type": DynmaicContentType.VOTE.value,
"type": DynamicContentType.VOTE.value,
"raw_text": vote.title,
}
)
return self

def add_image(self, image: Union[List[Picture], Picture]) -> "BuildDynmaic":
def add_image(self, image: Union[List[Picture], Picture]) -> "BuildDynamic":
"""
添加图片
Expand All @@ -388,7 +400,7 @@ def add_image(self, image: Union[List[Picture], Picture]) -> "BuildDynmaic":
self.pics += image
return self

def add_text(self, text: str) -> "BuildDynmaic":
def add_text(self, text: str) -> "BuildDynamic":
"""
添加文本 (可包括 at, 表情包)
Expand Down Expand Up @@ -500,21 +512,21 @@ def base_split(texts: List[str], at_and_emoji: List, last_length: int):
self.contents.append(
{
"biz_id": piece["uid"],
"type": DynmaicContentType.AT.value,
"type": DynamicContentType.AT.value,
"raw_text": piece["text"],
}
)
else:
self.contents.append(
{
"biz_id": "",
"type": DynmaicContentType.EMOJI.value,
"type": DynamicContentType.EMOJI.value,
"raw_text": piece["text"],
}
)
return self

def set_attach_card(self, oid: int) -> "BuildDynmaic":
def set_attach_card(self, oid: int) -> "BuildDynamic":
"""
设置直播预约
Expand All @@ -531,7 +543,7 @@ def set_attach_card(self, oid: int) -> "BuildDynmaic":
}
return self

def set_topic(self, topic_id: int) -> "BuildDynmaic":
def set_topic(self, topic_id: int) -> "BuildDynamic":
"""
设置话题
Expand All @@ -543,7 +555,7 @@ def set_topic(self, topic_id: int) -> "BuildDynmaic":

def set_options(
self, up_choose_comment: bool = False, close_comment: bool = False
) -> "BuildDynmaic":
) -> "BuildDynamic":
"""
设置选项
Expand All @@ -568,10 +580,10 @@ def set_send_time(self, time: datetime):
self.time = time
return self

def get_dynamic_type(self) -> SendDynmaicType:
def get_dynamic_type(self) -> SendDynamicType:
if len(self.pics) != 0:
return SendDynmaicType.IMAGE
return SendDynmaicType.TEXT
return SendDynamicType.IMAGE
return SendDynamicType.TEXT

def get_contents(self) -> list:
return self.contents
Expand All @@ -589,12 +601,12 @@ def get_options(self) -> dict:
return self.options


async def send_dynamic(info: BuildDynmaic, credential: Credential):
async def send_dynamic(info: BuildDynamic, credential: Credential):
"""
发送动态
Args:
info (BuildDynmaic): 动态内容
info (BuildDynamic): 动态内容
credential (Credential): 凭据
Expand Down Expand Up @@ -738,42 +750,33 @@ def __init__(
"""
self.__dynamic_id = dynamic_id
self.credential = credential if credential is not None else Credential()
api = API["info"]["detail_new"]

api = API["info"]["detail"]
params = {
"id": self.__dynamic_id,
"timezone_offset": -480,
"features": "itemOpusStyle",
}
data = (
Api(**api, credential=self.credential).update_params(**params).result_sync
)
self.__special_article = data["item"]["type"] == 1
self.__rid_str = int(data["item"]["basic"]["rid_str"])

def is_special_article(self) -> bool:
"""
是否为部分的特殊专栏。此部分专栏与动态完全兼容。
Returns:
bool: 是否为特殊专栏
"""
return self.__special_article
self.__opus = data["item"]["basic"]["comment_type"] == 11

def get_dynamic_id(self) -> int:
return self.__dynamic_id

def turn_to_article(self) -> "article.Article":
def get_dynamic_type(self) -> DynamicType:
"""
对于部分的特殊专栏,将 Dynamic 对象转换为 Article 对象。
获取动态类型
Returns:
Article: Article 对象
DynamicType: 动态类型
"""
raise_for_statement(self.__special_article, "仅支持特殊专栏")
return article.Article(self.__rid_str, credential=self.credential)
return DynamicType.OPUS if self.__opus else DynamicType.NORMAL

async def get_info(self, features: str = "itemOpusStyle") -> dict:
"""
(不建议使用此旧版 API,请转到新版 get_info_opus)
(对 Opus 动态,获取动态内容建议使用 Opus.get_detail())
获取动态信息
Expand All @@ -795,19 +798,19 @@ async def get_info(self, features: str = "itemOpusStyle") -> dict:
)
return data

async def get_info_opus(self) -> dict:
async def get_reaction(self, offset: str = "") -> dict:
"""
新版获取动态信息
获取点赞、转发
Args:
offset (str, optional): 偏移值(下一页的第一个动态 ID,为该请求结果中的 offset 键对应的值),类似单向链表. Defaults to ""
Returns:
dict: 调用 API 返回的结果
"""

api = API["info"]["detail_new"]
params = {
"id": self.__dynamic_id,
"timezone_offset": -480,
}
api = API["info"]["reaction"]
params = {"web_location": "333.1369", "offset": "", "id": self.get_dynamic_id()}
return (
await Api(**api, credential=self.credential).update_params(**params).result
)
Expand Down
Loading

0 comments on commit 55a51c6

Please sign in to comment.