Skip to content

Commit

Permalink
Merge pull request #403 from z0z0r4/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
z0z0r4 authored Jul 25, 2023
2 parents d79c097 + 89b8d08 commit 1d91c38
Show file tree
Hide file tree
Showing 41 changed files with 412 additions and 539 deletions.
36 changes: 22 additions & 14 deletions .github/CODING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@

**入门示例:我要贡献一个 API !**

首先你需要写入你的 API,找到 `bilibili_api/data/api` 目录,会有许多的 `json` 文件,你需要找到对应的 `json` 文件介入你的 API。举个例子:你的 API 如果和用户有关,请写入 `user.json` 文件中。<br>
首先你需要写入你的 API,找到 `bilibili_api/data/api` 目录,会有许多的 `json` 文件,你需要找到对应的 `json` 文件介入你的 API。举个例子:你的 API 如果和用户有关,请写入 `user.json` 文件中。

每一个 `json` 文件会根据 API 的作用大致分类,你只要找到对应的分类就可以了。一般 `json` 文件将分为两个分类:`info` (有关获取信息的 API) 和 `operate` (有关操作用户相关信息的 API)。当然有的时候部分 API 也会被归类到另外一个分类,如 `video.json` 中有一个分类就存放着有关弹幕的 API (`danmaku`)。除非有大量与某个东西相关的 API (如视频 API 有许多是和弹幕有关的),否则千万不要创建在 `info``operate` 以外的新的分类。<br>
~~当然有的文件因为懒什么分类都没有弄,在 API 非常少的时候你可以这么做,但是不推荐。~~<br><br>
~~当然有的文件因为懒什么分类都没有弄,在 API 非常少的时候你可以这么做,但是不推荐。~~

然后你就可以进行编写了。首先找到对应的文件 (如和视频相关的 API 的具体实现要写在 `video.py` 中),然后 (在一个类里面 ( 有的时候不用写在一个类里面 )) 新建一个异步函数,一定要记得完善参数类型和返回值类型。( 建议让你的 IDE 打开检查 `typing` 的模式,就例如 `Visual Studio Code` 里面将 `python.analysis.typeCheckingMode` 设置为 `basic``strict`)。接着你需要编写注释,像下面那样子编写:

``` python
Expand All @@ -27,7 +29,11 @@ async def get_user_real_name(self, uid: int, credential: Union[Credential, None]
"""
```

首先你要写上函数的用途,然后要写好参数的说明:名称 + 类型 + 用途。其中类型如果是多个的话,那么可以用 `|` 分隔而不是用 `Union` (写代码的时候务必要用 `Union`,需要支持 `Python3.8`),如果你的 API 需要登录的话,你要加上 `credential` 参数,类型是 `Credential | None`,描述可以用 `凭据类。`。(凭据类能传入 cookies 以保证能正常访问需要登录的 API,这里就做到了登录的作用 ) 最后要把返回值写好,一般情况下 API 返回的结果类型都是 `dict`,这个时候你的返回值说明就可以用 `调用 API 返回的结果`。<br>
首先你要写上函数的用途,然后要写好参数的说明:名称 + 类型 + 用途。其中类型如果是多个的话,那么写注释时可以用 `|` 分隔而不是用 `Union`,但写代码的时候务必要用 `Union`,需要支持 `Python3.8`

如果你的 API 需要登录的话,你要加上 `credential` 参数,类型是 `Credential | None`,描述可以用 `凭据类。`。(凭据类能传入 cookies 以保证能正常访问需要登录的 API,这里就做到了登录的作用 )

最后要把返回值写好,一般情况下 API 返回的结果类型都是 `dict`,这个时候你的返回值说明就可以用 `调用 API 返回的结果`。<br>
然后就是函数的主体了,你可以按照下面的写法来写:

``` python
Expand All @@ -40,14 +46,22 @@ async def ...(...) -> dict:
params = {
...
}
return await request("GET", api["url"], params=params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result
```

首先如果函数要传入凭据类,那么你要添加 `credential = credential if credential else Credential()` 以确保 `credential` 参数不会是 `None` 类型,~~当然不这么做也不会报错,但是你好歹要走个形式啊!~~。接着我们声明 `api` 变量,它是字典 `API` 的一部分,这里的字典 `API` 就是你写入 API 的那个 `json` 文件的内容。所以你的 API 也在里面,你只需要补充好字典的键值就可以了。接着就是可选的 `params` 或 `data`,如果你的 API 需要传入参数的话不要忘记创建它们。最后你只需要返回已经封装好了的函数 `request` 得到的结果就可以了。`request` 函数的第一个参数是访问 `API` 的方法,一般是 `GET`/`POST`/`PUT`/`DELETE`/`PATCH`,第二个参数是 `API` 的链接,你只需要填入 `api["url"]` 就可以了 ( 前提是你的键值没有输错 ),下面的参数最好要指定名称传参,最后不要忘记了:如果这个接口需要登录,那么你得要把凭据类传入进去!( 如果你的函数是在一个类里面,通常每一个类都有一个属性 `credential`,就是创建这个类的时候会传入的,这个时候你只需要传入 `self.credential` 就可以了。当然参数里面不用再写 `credential` 参数了!! )<br><br>
1. 首先如果函数要传入凭据类,那么你应该创建变量 `credential = credential if credential else Credential()` 以确保 `credential` 参数不会是 `None` 类型,~~当然不这么做也不会报错,但是你好歹要走个形式啊!~~

2. 接着我们声明 `api` 变量,它是字典 `API` 的一部分,这里的字典 `API` 就是你写入 API 的那个 `json` 文件的内容。
所以你的 API 也在里面,你只需要补充好字典的键值就可以了。接着就是可选的 `params``data`,如果你的 API 需要传入参数的话不要忘记传入它们。

3. 最后你只需要返回已经封装好了的函数 `Api` 得到的结果就可以了。`Api` 函数的第一个参数是 `**api`,通常里面包括 HTTP 方法、URL 等信息,`params`/`data`/`headers`/`files`参数应该通过 `Api().update()`/`Api().update_headers()` 等传入。

4. 不要忘记了:如果这个接口需要登录,那么你得把凭据类传入进去!( 如果你的函数是在一个类里面,通常每一个类都有一个属性 `credential`,就是创建这个类的时候会传入的,这个时候你只需要传入 `self.credential` 就可以了。当然参数里面不用再写 `credential` 参数了!! )<br><br>

恭喜你完成了代码的编写!你可以先进行一次新功能的提交:

``` bash
$ git commit -am "feat(user.User): 新增一个狗都不用的接口"
$ git commit -am "feat(user.User): 新增一个 ### 的接口"
```

然后你还需要干两件事情:文档 & 测试。这里不详细说明了,因为这里不会提及除了写代码以外的任何事情。SO...
Expand All @@ -56,13 +70,7 @@ $ git commit -am "feat(user.User): 新增一个狗都不用的接口"

当然,除了这个指南举的简单 API 样例,你还可以学习更加高级的功能,例如新建一个模块、事件监听器、`protobuf` 数据等等,这里~~因为懒~~先不写了,你可以查看这些功能的样例进行学习。

所以做完功能不要忘记提交到线上仓库! (**PR 记得向 `dev` 分之提交!!!**)

<details>
<summary>看不见我</summary>
所以做完功能不要忘记提交到 Github 仓库!

``` bash
$ git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;git push origin dev;
```
**PR 记得向 `dev` 分支提交!!! `git push origin dev`**

</details>
13 changes: 13 additions & 0 deletions CHANGELOGS/v15.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# 15.5.2 2023/7/25
- fix: 修改新请求函数为 Api 方法 by @Drelf2018 in https://github.com/Nemo2011/bilibili-api/pull/364
- fix: 尝试修复发送图片私信的问题 by @Drelf2018 in https://github.com/Nemo2011/bilibili-api/pull/367
- fix: 修复 params 中有汉字时计算 w_rid 错误的漏洞以及弹幕用户名打码问题 by @Drelf2018 in https://github.com/Nemo2011/bilibili-api/pull/373
- fix: update get_followings by @z0z0r4 in https://github.com/Nemo2011/bilibili-api/pull/381
- rechore: login term and tk by @z0z0r4 in https://github.com/Nemo2011/bilibili-api/pull/383
* fix: import by @Nemo2011 https://github.com/Nemo2011/bilibili-api/commit/dacefba0d909a5dbbc9213100267b84bc54581d5
* style: by @Nemo2011 https://github.com/Nemo2011/bilibili-api/commit/9ca10d2bb534a216e6dabadb1fb0c5093548b11d
* feat: settings.wbi_retry_times by @Nemo2011 https://github.com/Nemo2011/bilibili-api/commit/54087564b9a68cac800664d00846abf35b3d204e
* fix: testing & login by @Nemo2011 https://github.com/Nemo2011/bilibili-api/commit/b329fe6d16022981c89ffa2bec8738ce96881afd
* fix: buvid3 by @z0z0r4 in https://github.com/Nemo2011/bilibili-api/pull/391
* rechore: 将 `request` 换到 `Api` by @z0z0r4 https://github.com/Nemo2011/bilibili-api/pull/403

# 15.5.1 2023/6/24

- fix: credential 刷新异步问题 (https://github.com/Nemo2011/bilibili-api/issues/351) (https://github.com/Nemo2011/bilibili-api/issues/358)
Expand Down
2 changes: 1 addition & 1 deletion bilibili_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
interactive_video,
)

BILIBILI_API_VERSION = "15.5.1.b0"
BILIBILI_API_VERSION = "15.5.2"

# 如果系统为 Windows,则修改默认策略,以解决代理报错问题
if "windows" in platform.system().lower():
Expand Down
14 changes: 7 additions & 7 deletions bilibili_api/album.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .utils.picture import Picture
from .exceptions import ArgsException
from .utils.credential import Credential
from .utils.network_httpx import request
from .utils.network_httpx import Api

API = get_api("album")

Expand Down Expand Up @@ -73,7 +73,7 @@ async def get_info(self) -> dict:
"""
api = API["info"]["detail"]
params = {"doc_id": self.get_doc_id()}
resp = await request("GET", api["url"], params=params)
resp = await Api(**api).update_params(**params).result
self.__info = resp
return resp

Expand Down Expand Up @@ -142,14 +142,14 @@ async def get_painter() -> dict:
if order != AlbumOrder.RECOMMEND:
raise ArgsException("摄影相簿暂不支持以热度/以时间排序。")
params = {"type": order.value, "page_num": page_num, "page_size": page_size}
return await request("GET", api["url"], params=params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result

async def get_photos() -> dict:
api = API["info"]["homepage_photos_albums_list"]
if order != AlbumOrder.RECOMMEND:
raise ArgsException("摄影相簿暂不支持以热度/以时间排序。")
params = {"type": order.value, "page_num": page_num, "page_size": page_size}
return await request("GET", api["url"], params=params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result

if category == AlbumCategory.PAINTS:
return await get_painter()
Expand Down Expand Up @@ -184,12 +184,12 @@ async def get_homepage_recommend_uppers(
async def get_painters() -> dict:
api = API["info"]["homepage_recommended_painters"]
params = {"num": numbers}
return await request("GET", api["url"], params=params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result

async def get_photos_uppers() -> dict:
api = API["info"]["homepage_recommended_photos_uppers"]
params = {"num": numbers}
return await request("GET", api["url"], params=params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result

if category == AlbumCategory.PAINTS:
return await get_painters()
Expand Down Expand Up @@ -235,4 +235,4 @@ async def get_user_albums(
"page_num": page_num,
"page_size": page_size,
}
return await request("GET", api["url"], params=params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result
6 changes: 3 additions & 3 deletions bilibili_api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from .utils.utils import get_api
from .utils.credential import Credential
from .utils.network_httpx import request
from .utils.network_httpx import Api

API = get_api("app")

Expand Down Expand Up @@ -56,7 +56,7 @@ async def get_loading_images(
"width": width,
"birth": birth,
}
return await request("GET", api["url"], params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result


async def get_loading_images_special(
Expand Down Expand Up @@ -120,4 +120,4 @@ async def get_loading_images_special(
"ts": ts,
"sign": sign,
}
return await request("GET", api["url"], params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result
17 changes: 7 additions & 10 deletions bilibili_api/article.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from .note import Note, NoteType
from .utils.utils import get_api
from .utils.credential import Credential
from .utils.network_httpx import request, get_session
from .utils.network_httpx import Api, get_session
from .exceptions.NetworkException import ApiException, NetworkException

API = get_api("article")
Expand Down Expand Up @@ -107,7 +107,7 @@ async def get_article_rank(
"""
api = API["info"]["rank"]
params = {"cid": rank_type.value}
return await request("GET", api["url"], params=params)
return await Api(**api).update_params(**params).result


class ArticleList:
Expand Down Expand Up @@ -142,7 +142,7 @@ async def get_content(self) -> dict:

api = API["info"]["list"]
params = {"id": self.__rlid}
return await request("GET", api["url"], params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result


class Article:
Expand Down Expand Up @@ -601,10 +601,7 @@ async def get_info(self) -> dict:

api = API["info"]["view"]
params = {"id": self.__cvid}
resp = await request(
"GET", api["url"], params=params, credential=self.credential
)
return resp
return await Api(**api, credential=self.credential).update_params(**params).result

async def get_all(self) -> dict:
"""
Expand Down Expand Up @@ -647,7 +644,7 @@ async def set_like(self, status: bool = True) -> dict:

api = API["operate"]["like"]
data = {"id": self.__cvid, "type": 1 if status else 2}
return await request("POST", api["url"], data=data, credential=self.credential)
return await Api(**api, credential=self.credential).update_data(**data).result

async def set_favorite(self, status: bool = True) -> dict:
"""
Expand All @@ -666,7 +663,7 @@ async def set_favorite(self, status: bool = True) -> dict:
)

data = {"id": self.__cvid}
return await request("POST", api["url"], data=data, credential=self.credential)
return await Api(**api, credential=self.credential).update_data(**data).result

async def add_coins(self) -> dict:
"""
Expand All @@ -680,7 +677,7 @@ async def add_coins(self) -> dict:
upid = (await self.get_info())["mid"]
api = API["operate"]["coin"]
data = {"aid": self.__cvid, "multiply": 1, "upid": upid, "avtype": 2}
return await request("POST", api["url"], data=data, credential=self.credential)
return await Api(**api, credential=self.credential).update_data(**data).result

# TODO: 专栏上传/编辑/删除

Expand Down
4 changes: 2 additions & 2 deletions bilibili_api/article_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from typing import List, Tuple, Optional

from .utils.utils import get_api
from .utils.network_httpx import request
from .utils.network_httpx import Api

API = get_api("article-category")

Expand Down Expand Up @@ -148,4 +148,4 @@ async def get_category_recommend_articles(
"""
api = API["info"]["recommends"]
params = {"cid": category_id, "sort": order.value, "pn": page_num, "ps": page_size}
return await request("GET", api["url"], params=params)
return await Api(**api).update_params(**params).result
20 changes: 10 additions & 10 deletions bilibili_api/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from .utils.utils import get_api
from .utils.credential import Credential
from .utils.network_httpx import request
from .utils.network_httpx import Api

API = get_api("audio")

Expand Down Expand Up @@ -45,7 +45,7 @@ async def get_info(self) -> dict:

api = API["audio_info"]["info"]
params = {"sid": self.__auid}
return await request("GET", api["url"], params, credential=self.credential)
return await Api(**api, credential=self.credential).update_params(**params).result

async def get_tags(self) -> dict:
"""
Expand All @@ -56,7 +56,7 @@ async def get_tags(self) -> dict:
"""
api = API["audio_info"]["tag"]
params = {"sid": self.__auid}
return await request("GET", api["url"], params, credential=self.credential)
return await Api(**api, credential=self.credential).update_params(**params).result

async def get_download_url(self) -> dict:
"""
Expand All @@ -67,7 +67,7 @@ async def get_download_url(self) -> dict:
"""
api = API["audio_info"]["download_url"]
params = {"sid": self.__auid, "privilege": 2, "quality": 2}
return await request("GET", api["url"], params, credential=self.credential)
return await Api(**api, credential=self.credential).update_params(**params).result

async def add_coins(self, num: int = 2) -> dict:
"""
Expand All @@ -84,7 +84,7 @@ async def add_coins(self, num: int = 2) -> dict:
api = API["audio_operate"]["coin"]
data = {"sid": self.__auid, "multiply": num}

return await request("POST", api["url"], data=data, credential=self.credential)
return await Api(**api, credential=self.credential).update_data(**data).result

# TODO: 音频编辑

Expand Down Expand Up @@ -120,7 +120,7 @@ async def get_info(self) -> dict:

api = API["list_info"]["info"]
params = {"sid": self.__amid}
return await request("GET", api["url"], params, credential=self.credential)
return await Api(**api, credential=self.credential).update_params(**params).result

async def get_tags(self) -> dict:
"""
Expand All @@ -132,7 +132,7 @@ async def get_tags(self) -> dict:

api = API["list_info"]["tag"]
params = {"sid": self.__amid}
return await request("GET", api["url"], params, credential=self.credential)
return await Api(**api, credential=self.credential).update_params(**params).result

async def get_song_list(self, pn: int = 1) -> dict:
"""
Expand All @@ -147,7 +147,7 @@ async def get_song_list(self, pn: int = 1) -> dict:
api = API["list_info"]["song_list"]
params = {"sid": self.__amid, "pn": pn, "ps": 100}

return await request("GET", api["url"], params, credential=self.credential)
return await Api(**api, credential=self.credential).update_params(**params).result

# TODO: 歌单编辑

Expand All @@ -167,7 +167,7 @@ async def get_user_stat(uid: int, credential: Union[Credential, None] = None) ->
credential = credential if credential is not None else Credential()
api = API["audio_info"]["user"]
params = {"uid": uid}
return await request("GET", api["url"], params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result


async def get_hot_song_list(
Expand All @@ -187,4 +187,4 @@ async def get_hot_song_list(
credential = credential if credential is not None else Credential()
api = API["list_info"]["hot"]
params = {"pn": pn, "ps": 100}
return await request("GET", api["url"], params, credential=credential)
return await Api(**api, credential=credential).update_params(**params).result
Loading

0 comments on commit 1d91c38

Please sign in to comment.