1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
mod prelude {
pub use reqwest::{Client, Response, StatusCode};
pub use serde::de::DeserializeOwned;
pub use std::{future::Future, pin::Pin};
pub use crate::{Error, Result};
pub(super) use super::BiliResponseExt;
pub use super::{Request, RequestResponse};
}
use prelude::*;
#[derive(Debug, Deserialize)]
struct BiliResponse<T> {
code: i64,
message: String,
#[serde(bound(deserialize = "T: serde::Deserialize<'de>"))]
#[serde(default = "Option::default")]
data: Option<T>,
}
impl<T: DeserializeOwned> BiliResponse<T> {
#[allow(unused)]
pub fn into_data(self) -> Option<T> {
self.data
}
pub async fn from_response(response: Response) -> Result<T> {
if response.status() != StatusCode::OK {
return Err(Error::StatusCode(response.status()));
}
let response_text = response.text().await?;
let this: Self = serde_json::from_str(&response_text)?;
if this.code != 0 {
return Err(Error::BiliCustom {
code: this.code,
message: this.message,
});
}
match this.data {
Some(data) => Ok(data),
None => Err(Error::DataNotFound),
}
}
}
pub trait BiliResponseExt<T: DeserializeOwned> {
fn bili_data(self) -> Pin<Box<dyn Future<Output = Result<T>> + Send>>;
}
impl<T: DeserializeOwned> BiliResponseExt<T> for Response {
fn bili_data(self) -> Pin<Box<dyn Future<Output = Result<T>> + Send>> {
Box::pin(async move { BiliResponse::<T>::from_response(self).await })
}
}
pub trait Request: DeserializeOwned {
type Args;
fn request(client: &Client, args: Self::Args) -> RequestResponse<Self>;
}
pub type RequestResponse<T> = Pin<Box<dyn Future<Output = Result<T>> + Send>>;
mod room_info;
pub use room_info::{InfoByRoom, RoomInfo};
mod danmu_info;
pub use danmu_info::{DanmuInfo, DanmuServer};