leetcode_cli/cache/
parser.rs1use super::models::*;
3use serde_json::Value;
4
5pub fn problem(problems: &mut Vec<Problem>, v: Value) -> Option<()> {
7 let pairs = v.get("stat_status_pairs")?.as_array()?;
8 for p in pairs {
9 let stat = p.get("stat")?.as_object()?;
10 let total_acs = stat.get("total_acs")?.as_f64()? as f32;
11 let total_submitted = stat.get("total_submitted")?.as_f64()? as f32;
12
13 let fid_obj = stat.get("frontend_question_id")?;
14 let fid = match fid_obj.as_i64() {
15 Some(s) => s as i32,
17 None => fid_obj.as_str()?.split(' ').last()?.parse::<i32>().ok()?,
19 };
20
21 problems.push(Problem {
22 category: v.get("category_slug")?.as_str()?.to_string(),
23 fid,
24 id: stat.get("question_id")?.as_i64()? as i32,
25 level: p.get("difficulty")?.as_object()?.get("level")?.as_i64()? as i32,
26 locked: p.get("paid_only")?.as_bool()?,
27 name: stat.get("question__title")?.as_str()?.to_string(),
28 percent: total_acs / total_submitted * 100.0,
29 slug: stat.get("question__title_slug")?.as_str()?.to_string(),
30 starred: p.get("is_favor")?.as_bool()?,
31 status: p.get("status")?.as_str().unwrap_or("Null").to_string(),
32 desc: String::new(),
33 });
34 }
35
36 Some(())
37}
38
39pub fn desc(q: &mut Question, v: Value) -> Option<bool> {
41 let o = &v
46 .as_object()?
47 .get("data")?
48 .as_object()?
49 .get("question")?
50 .as_object()?;
51
52 if *o.get("content")? == Value::Null {
53 return Some(false);
54 }
55
56 *q = Question {
57 content: o.get("content")?.as_str().unwrap_or("").to_string(),
58 stats: serde_json::from_str(o.get("stats")?.as_str()?).ok()?,
59 defs: serde_json::from_str(o.get("codeDefinition")?.as_str()?).ok()?,
60 case: o.get("sampleTestCase")?.as_str()?.to_string(),
61 all_cases: o
62 .get("exampleTestcases")
63 .unwrap_or(o.get("sampleTestCase")?) .as_str()?
65 .to_string(),
66 metadata: serde_json::from_str(o.get("metaData")?.as_str()?).ok()?,
67 test: o.get("enableRunCode")?.as_bool()?,
68 t_content: o
69 .get("translatedContent")?
70 .as_str()
71 .unwrap_or("")
72 .to_string(),
73 };
74
75 Some(true)
76}
77
78pub fn tags(v: Value) -> Option<Vec<String>> {
80 trace!("Parse tags...");
81 let tag = v.as_object()?.get("data")?.as_object()?.get("topicTag")?;
82
83 if tag.is_null() {
84 return Some(vec![]);
85 }
86
87 let arr = tag.as_object()?.get("questions")?.as_array()?;
88
89 let mut res: Vec<String> = vec![];
90 for q in arr.iter() {
91 res.push(q.as_object()?.get("questionId")?.as_str()?.to_string())
92 }
93
94 Some(res)
95}
96
97pub fn daily(v: Value) -> Option<i32> {
99 trace!("Parse daily...");
100 let v_obj = v.as_object()?.get("data")?.as_object()?;
101 match v_obj.get("activeDailyCodingChallengeQuestion") {
102 Some(v) => v,
104 None => v_obj.get("todayRecord")?.as_array()?.first()?,
106 }
107 .as_object()?
108 .get("question")?
109 .as_object()?
110 .get("questionFrontendId")?
111 .as_str()?
112 .parse()
113 .ok()
114}
115
116pub fn user(v: Value) -> Option<Option<(String, bool)>> {
118 let user = v.as_object()?.get("data")?.as_object()?.get("user")?;
122 if *user == Value::Null {
123 return Some(None);
124 }
125 let user = user.as_object()?;
126 Some(Some((
127 user.get("username")?.as_str()?.to_owned(),
128 user.get("isCurrentUserPremium")?.as_bool()?,
129 )))
130}
131
132pub use ss::ssr;
133mod ss {
135 use serde::{de, Deserialize, Deserializer};
136 use std::fmt;
137 use std::marker::PhantomData;
138
139 pub fn ssr<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
141 where
142 D: Deserializer<'de>,
143 {
144 struct StringOrVec(PhantomData<Vec<String>>);
145
146 impl<'de> de::Visitor<'de> for StringOrVec {
147 type Value = Vec<String>;
148
149 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
150 formatter.write_str("string or list of strings")
151 }
152
153 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
154 where
155 E: de::Error,
156 {
157 Ok(vec![value.to_owned()])
158 }
159
160 fn visit_seq<S>(self, visitor: S) -> Result<Self::Value, S::Error>
161 where
162 S: de::SeqAccess<'de>,
163 {
164 Deserialize::deserialize(de::value::SeqAccessDeserializer::new(visitor))
165 }
166 }
167
168 deserializer.deserialize_any(StringOrVec(PhantomData))
169 }
170}