bpi_rs/manga/
point_shop.rs1use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
6use serde::{ Deserialize, Serialize };
7
8#[derive(Debug, Serialize, Clone, Deserialize)]
11pub struct UserPointData {
12 pub point: String,
14}
15
16pub type UserPointResponse = BpiResponse<UserPointData>;
17
18#[derive(Debug, Serialize, Clone, Deserialize)]
19pub struct ProductLimit {
20 #[serde(rename = "type")]
22 pub limit_type: i32,
23 pub id: i64,
25 pub title: String,
27}
28
29#[derive(Debug, Serialize, Clone, Deserialize)]
30pub struct Product {
31 pub id: i64,
33 pub r#type: i32,
35 pub title: String,
37 pub image: String,
39 pub amount: i32,
41 pub cost: i32,
43 pub real_cost: i32,
45 pub remain_amount: i32,
47 pub comic_id: i64,
49 pub limits: Vec<ProductLimit>,
51 pub discount: i32,
53 pub product_type: i32,
55 pub pendant_url: String,
57 pub pendant_expire: i32,
59 pub exchange_limit: i32,
61 pub address_deadline: String,
63 pub act_type: i32,
65 pub has_exchanged: bool,
67 pub main_coupon_deadline: String,
69 pub deadline: String,
71 pub point: String,
73}
74
75pub type ProductListResponse = BpiResponse<Vec<Product>>;
76
77#[derive(Debug, Clone, Serialize)]
78pub struct ExchangeRequest {
79 pub product_id: String,
81 pub product_num: i32,
83 pub point: i32,
85}
86
87pub type ExchangeResponse = BpiResponse<serde_json::Value>;
88
89impl BpiClient {
92 pub async fn manga_user_point(&self) -> Result<UserPointResponse, BpiError> {
97 self
98 .post("https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/GetUserPoint")
99 .send_bpi("获取当前持有点数").await
100 }
101
102 pub async fn manga_point_products(&self) -> Result<ProductListResponse, BpiError> {
107 self
108 .post("https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/ListProduct")
109 .send_bpi("获取兑换奖品列表").await
110 }
111
112 pub async fn manga_point_exchange(
125 &self,
126 product_id: i64,
127 product_num: i32,
128 point: i32
129 ) -> Result<ExchangeResponse, BpiError> {
130 let req = ExchangeRequest {
131 product_id: product_id.to_string(),
132 product_num,
133 point,
134 };
135
136 self
137 .post("https://manga.bilibili.com/twirp/pointshop.v1.Pointshop/Exchange")
138 .form(&req)
139 .send_bpi("兑换物品").await
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[tokio::test]
148 async fn test_list_product() -> Result<(), Box<BpiError>> {
149 let bpi = BpiClient::new();
150 let resp = bpi.manga_point_products().await?;
151
152 let data = resp.into_data()?;
153 assert!(!data.is_empty());
154 Ok(())
155 }
156
157 #[tokio::test]
158 async fn test_get_user_point() -> Result<(), Box<BpiError>> {
159 let bpi = BpiClient::new();
160
161 let resp = bpi.manga_user_point().await?;
162 let data = resp.into_data()?;
163
164 tracing::info!("User point: {}", data.point);
165 Ok(())
166 }
167}