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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
//! 提供了某一学期的详细信息
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use serde_with::{serde_as, serde_conv};
use super::CQUSession;
use crate::{
errors::mycqu::MyCQUResult,
mycqu::utils::mycqu_request_handler,
session::{Client, Session},
utils::{
ApiModel,
consts::{
MYCQU_API_ALL_SESSION_INFO_URL, MYCQU_API_CURR_SESSION_INFO_URL,
MYCQU_API_SESSION_INFO_DETAIL_URL,
},
response_json_map,
},
};
/// 重庆大学某一学期的详细信息
#[serde_as]
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
pub struct CQUSessionInfo {
/// 对应的学期
#[serde(flatten)]
#[serde_as(
deserialize_as = "serde_with::PickFirst<(_, CQUSessionHelper, serde_with::DisplayFromStr)>"
)]
pub session: CQUSession,
/// 学期开始日期字符串("yyyy-MM-dd"格式),对于[fetch_detail]方法,格式为"yyyy-MM-dd HH:mm:ss"
#[serde(alias = "beginDate")]
pub begin_date_str: Option<String>,
/// 学期结束日期字符串("yyyy-MM-dd"格式),对于[fetch_detail]方法,格式为"yyyy-MM-dd HH:mm:ss"
#[serde(alias = "endDate")]
pub end_date_str: Option<String>,
/// 该学期是否为活跃学期(当前学期)
#[serde_as(deserialize_as = "serde_with::PickFirst<(_, ActiveHelper)>")]
pub active: bool,
}
serde_conv!(
ActiveHelper,
bool,
|active: &bool| if *active { "Y" } else { "N" },
|active: String| -> Result<bool, &'static str> {
match active.as_str() {
"Y" => Ok(true),
"N" => Ok(false),
_ => Err("Invalid active string"),
}
}
);
serde_conv!(
CQUSessionHelper,
CQUSession,
|session: &CQUSession| {
let season = if session.is_autumn { "秋" } else { "春" };
let name = format!("{}{}", session.year, season);
HashMap::<String, Value>::from_iter(
vec![
("name".to_string(), name.into()),
(
"id".to_string(),
session
.id
.map(|id| id.to_string().into())
.unwrap_or(Value::Null),
),
]
.into_iter(),
)
},
|session: HashMap<String, Value>| -> Result<CQUSession, &'static str> {
let year = session
.get("year")
.and_then(|year| year.as_str().map(|year| year.parse::<u16>().ok()).flatten())
.ok_or("year not found")?;
let term = session
.get("term")
.and_then(|term| term.as_str().map(|term| term.chars().next()))
.flatten();
let id = session
.get("id")
.and_then(|id| id.as_str().map(|id| id.parse::<u16>().ok()).flatten());
let session = CQUSession {
id,
year,
is_autumn: term == Some('秋'),
};
Ok(CQUSession { id, ..session })
}
);
impl CQUSessionInfo {
/// 通过具有教务网权限的会话([`Session`]),从教务网获取全部包括了ID的详细学期信息([`CQUSessionInfo`])
///
/// 返回的所有详细学期信息`begin_date_str`和`end_date_str`字段通常不为None
///
/// # Examples
/// ```rust, no_run
/// # use rsmycqu::mycqu::access_mycqu;
/// # use rsmycqu::mycqu::course::CQUSessionInfo;
/// # use rsmycqu::sso::login;
/// # use rsmycqu::session::{Client, Session};
/// # async fn async_fetch_all_cqu_session_info() {
/// # let client = Client::default();
/// # let mut session = Session::new();
/// login(&client, &mut session, "your_auth", "your_password", false).await.unwrap();
/// access_mycqu(&client, &mut session).await.unwrap();
/// let cqu_session_infos = CQUSessionInfo::fetch_all(&client, &session);
/// # }
/// ```
pub async fn fetch_all(client: &Client, session: &Session) -> MyCQUResult<Vec<Self>> {
let response = mycqu_request_handler(client, session, |client| {
client.get(MYCQU_API_ALL_SESSION_INFO_URL)
})
.await?;
let (mut res, raw_response) = response_json_map(response).await?;
Self::extract_array(&mut res, "sessionVOList", &raw_response)
}
/// 通过具有教务网权限的会话([`Session`]),从教务网获取包括了ID的当前学期详细信息([`CQUSessionInfo`])
///
/// 返回的当前学期详细信息`begin_date_str`和`end_date_str`字段通常为None
///
/// # Examples
/// ```rust, no_run
/// # use rsmycqu::mycqu::access_mycqu;
/// # use rsmycqu::mycqu::course::CQUSessionInfo;
/// # use rsmycqu::sso::login;
/// # use rsmycqu::session::{Client, Session};
/// # async fn async_fetch_all_cqu_session_info() {
/// # let client = Client::default();
/// # let mut session = Session::new();
/// login(&client, &mut session, "your_auth", "your_password", false).await.unwrap();
/// access_mycqu(&client, &mut session).await.unwrap();
/// let curr_cqu_session_info = CQUSessionInfo::fetch_curr(&client, &session);
/// # }
/// ```
pub async fn fetch_curr(client: &Client, session: &Session) -> MyCQUResult<Self> {
let response = mycqu_request_handler(client, session, |client| {
client.get(MYCQU_API_CURR_SESSION_INFO_URL)
})
.await?;
let (mut res, raw_response) = response_json_map(response).await?;
Self::extract_object(&mut res, "data", &raw_response)
}
/// 通过具有教务网权限的会话([`Session`]),从教务网查询某一学期ID对应的学期具体信息([`CQUSessionInfo`])
///
/// # Examples
/// ```rust, no_run
/// # use rsmycqu::mycqu::access_mycqu;
/// # use rsmycqu::mycqu::course::CQUSessionInfo;
/// # use rsmycqu::sso::login;
/// # use rsmycqu::session::{Client, Session};
/// # async fn async_fetch_cqu_session_detail_info() {
/// # let client = Client::default();
/// # let mut session = Session::new();
/// login(&client, &mut session, "your_auth", "your_password", false).await.unwrap();
/// access_mycqu(&client, &mut session).await.unwrap();
/// let cqu_session_info = CQUSessionInfo::fetch_detail(&client, &session, 1059);
/// # }
pub async fn fetch_detail(
client: &Client,
session: &Session,
session_id: u32,
) -> MyCQUResult<Self> {
let response = mycqu_request_handler(client, session, |client| {
client.get(format!(
"{}/{}",
MYCQU_API_SESSION_INFO_DETAIL_URL, session_id
))
})
.await?;
let (mut res, raw_response) = response_json_map(response).await?;
Self::extract_object(&mut res, "data", &raw_response)
}
}
impl ApiModel for CQUSessionInfo {}