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