1use crate::{ BilibiliRequest, BpiClient, BpiError, BpiResponse };
6use serde::{ Deserialize, Serialize };
7
8#[derive(Debug, Clone, Serialize)]
12pub struct ClockInMakeupRequest {
13 pub r#type: i32,
15 pub date: String,
17}
18
19#[derive(Debug, Serialize, Clone, Deserialize)]
21pub struct PointInfo {
22 pub point: i32,
24 pub origin_point: i32,
26 pub is_activity: bool,
28 pub title: String,
30}
31
32#[derive(Debug, Serialize, Clone, Deserialize)]
34pub struct ClockInInfoData {
35 pub day_count: i32,
37 pub status: i32,
39 pub points: Vec<i32>,
41 pub credit_icon: String,
43 pub sign_before_icon: String,
45 pub sign_today_icon: String,
47 pub breathe_icon: String,
49 #[serde(default)]
51 pub new_credit_x_icon: String,
52 #[serde(default)]
54 pub coupon_pic: String,
55 pub point_infos: Vec<PointInfo>,
57}
58
59pub type ClockInInfoResponse = BpiResponse<ClockInInfoData>;
60
61impl BpiClient {
64 pub async fn manga_clock_in(&self) -> Result<BpiResponse<serde_json::Value>, BpiError> {
68 let params = [("platform", "android")];
69 self
70 .post("https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn")
71 .form(¶ms)
72 .send_bpi("漫画签到").await
73 }
74
75 pub async fn manga_clock_in_makeup(
85 &self,
86 date: &str
87 ) -> Result<BpiResponse<serde_json::Value>, BpiError> {
88 let params = ClockInMakeupRequest {
89 r#type: 0,
90 date: date.to_string(),
91 };
92 self
93 .post("https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn?platform=android")
94 .json(¶ms)
95 .send_bpi("漫画补签").await
96 }
97
98 pub async fn manga_clock_in_info(&self) -> Result<ClockInInfoResponse, BpiError> {
102 self
103 .post("https://manga.bilibili.com/twirp/activity.v1.Activity/GetClockInInfo")
104 .send_bpi("获取漫画签到信息").await
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[tokio::test]
113 async fn test_manga_clock_in() -> Result<(), Box<BpiError>> {
114 let bpi = BpiClient::new();
115
116 let result = bpi.manga_clock_in().await;
117 match result {
118 Ok(_) => tracing::info!("签到成功"),
119 Err(error) => tracing::error!("{:#?}", error),
120 }
121
122 Ok(())
123 }
124
125 #[tokio::test]
126 async fn test_get_manga_clock_in_info() -> Result<(), Box<BpiError>> {
127 let bpi = BpiClient::new();
128
129 let result = bpi.manga_clock_in_info().await?;
130
131 let data = result.into_data()?;
132
133 assert!(data.day_count >= 0);
134 assert!(data.status == 0 || data.status == 1);
135 assert_eq!(data.points.len(), 7); assert!(!data.point_infos.is_empty());
137
138 Ok(())
139 }
140}