bangumi_api/module/person/
service.rs

1use anyhow::Result;
2use bytes::Bytes;
3use reqwest::Method;
4
5use crate::{
6    common::model::BangumiClient,
7    module::model::{Paged, SimpleImageType},
8};
9
10use super::model::{PersonCharacter, PersonDetail, PersonSearch, PersonSubject};
11
12impl BangumiClient {
13    /// 搜索人物
14    ///
15    /// 支持按关键词搜索人物,并可通过筛选条件和分页参数控制结果范围
16    ///
17    /// # 参数
18    /// - `limit`: 可选,每页返回的结果数量
19    /// - `offset`: 可选,结果偏移量(用于分页,从0开始)
20    /// - `payload`: 可选,搜索条件,包含关键词和职业筛选等信息
21    ///
22    /// # 返回
23    /// 返回包含人物详细信息的分页结果
24    pub async fn search_persons(
25        &self,
26        limit: Option<u32>,
27        offset: Option<u32>,
28        payload: Option<PersonSearch>,
29    ) -> Result<Paged<PersonDetail>> {
30        // 构建人物搜索接口URL
31        let url = format!("{}/v0/search/persons", self.base_path);
32
33        // 创建POST请求构建器
34        let mut request_builder = self.request_builder(Method::POST, &url);
35
36        // 添加分页参数
37        if let Some(ref param_value) = limit {
38            request_builder = request_builder.query(&[("limit", &param_value)]);
39        }
40        if let Some(ref param_value) = offset {
41            request_builder = request_builder.query(&[("offset", &param_value)]);
42        }
43        // 添加搜索条件请求体
44        request_builder = request_builder.json(&payload);
45
46        // 发送请求并解析分页的人物详情结果
47        let res = self.request_send(request_builder).await?.json().await?;
48
49        Ok(res)
50    }
51
52    /// 获取人物详细信息
53    ///
54    /// 根据人物ID查询完整的人物信息,包括基本资料、职业、统计数据等
55    ///
56    /// # 参数
57    /// - `person_id`: 人物ID(必需,指定要查询的人物)
58    ///
59    /// # 返回
60    /// 返回包含人物完整信息的`PersonDetail`结构体
61    pub async fn get_person(&self, person_id: u32) -> Result<PersonDetail> {
62        // 构建人物详情接口URL
63        let url = format!("{}/v0/persons/{person_id}", self.base_path);
64
65        // 创建GET请求构建器
66        let request_builder = self.request_builder(Method::GET, &url);
67
68        // 发送请求并解析人物详情
69        let res = self.request_send(request_builder).await?.json().await?;
70
71        Ok(res)
72    }
73
74    /// 获取人物图片
75    ///
76    /// 根据人物ID和图片类型获取人物图片的二进制数据
77    ///
78    /// # 参数
79    /// - `person_id`: 人物ID(必需,指定目标人物)
80    /// - `r#type`: 图片类型(如原图、缩略图等,通过`SimpleImageType`指定)
81    ///
82    /// # 返回
83    /// 返回图片的二进制数据(`Bytes`类型)
84    pub async fn get_person_image(&self, person_id: u32, r#type: SimpleImageType) -> Result<Bytes> {
85        // 构建人物图片接口URL
86        let url = format!("{}/v0/persons/{person_id}/image", self.base_path);
87
88        // 创建GET请求构建器并添加图片类型参数
89        let mut request_builder = self.request_builder(Method::GET, &url);
90        request_builder = request_builder.query(&[("type", &r#type)]);
91
92        // 发送请求并获取图片二进制数据
93        let res = self.request_send(request_builder).await?.bytes().await?;
94
95        Ok(res)
96    }
97
98    /// 获取人物参与的条目列表
99    ///
100    /// 查询指定人物参与制作的所有作品(条目),包含人物在作品中的职位信息
101    ///
102    /// # 参数
103    /// - `person_id`: 人物ID(必需,指定目标人物)
104    ///
105    /// # 返回
106    /// 返回包含人物参与条目的列表(`PersonSubject`结构体数组)
107    pub async fn get_person_subjects(&self, person_id: u32) -> Result<Vec<PersonSubject>> {
108        // 构建人物参与条目接口URL
109        let url = format!("{}/v0/persons/{person_id}/subjects", self.base_path);
110
111        // 创建GET请求构建器
112        let request_builder = self.request_builder(Method::GET, &url);
113
114        // 发送请求并解析条目列表
115        let res = self.request_send(request_builder).await?.json().await?;
116
117        Ok(res)
118    }
119
120    /// 获取人物关联的角色列表
121    ///
122    /// 查询指定人物参与配音或创作的角色,包含角色所属作品信息
123    ///
124    /// # 参数
125    /// - `person_id`: 人物ID(必需,指定目标人物)
126    ///
127    /// # 返回
128    /// 返回包含人物关联角色的列表(`PersonCharacter`结构体数组)
129    pub async fn get_person_characters(&self, person_id: u32) -> Result<Vec<PersonCharacter>> {
130        // 构建人物关联角色接口URL
131        let url = format!("{}/v0/persons/{person_id}/characters", self.base_path);
132
133        // 创建GET请求构建器
134        let request_builder = self.request_builder(Method::GET, &url);
135
136        // 发送请求并解析角色列表
137        let res = self.request_send(request_builder).await?.json().await?;
138
139        Ok(res)
140    }
141
142    /// 收藏人物
143    ///
144    /// 将指定人物添加到当前用户的收藏列表(需认证,依赖`access_token`)
145    ///
146    /// # 参数
147    /// - `person_id`: 人物ID(必需,指定要收藏的人物)
148    ///
149    /// # 返回
150    /// 操作成功返回空结果,失败返回错误
151    pub async fn collect_person(&self, person_id: u32) -> Result<()> {
152        // 构建人物收藏接口URL
153        let url = format!("{}/v0/persons/{person_id}/collect", self.base_path);
154
155        // 创建POST请求构建器
156        let request_builder = self.request_builder(Method::POST, &url);
157
158        // 发送请求并忽略响应内容
159        let _res = self.request_send(request_builder).await?;
160
161        Ok(())
162    }
163
164    /// 取消收藏人物
165    ///
166    /// 将指定人物从当前用户的收藏列表中移除(需认证,依赖`access_token`)
167    ///
168    /// # 参数
169    /// - `person_id`: 人物ID(必需,指定要取消收藏的人物)
170    ///
171    /// # 返回
172    /// 操作成功返回空结果,失败返回错误
173    pub async fn uncollect_person(&self, person_id: u32) -> Result<()> {
174        // 构建取消人物收藏接口URL
175        let url = format!("{}/v0/persons/{person_id}/collect", self.base_path);
176
177        // 创建DELETE请求构建器
178        let request_builder = self.request_builder(Method::DELETE, &url);
179
180        // 发送请求并忽略响应内容
181        let _res = self.request_send(request_builder).await?;
182
183        Ok(())
184    }
185}