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 parser;
mod sql;
pub mod models;
pub mod schemas;
use self::models::*;
use self::schemas::problems::dsl::*;
use self::sql::*;
use crate::{cfg, err::Error, plugins::LeetCode};
use diesel::prelude::*;
use serde_json::Value;
use colored::Colorize;
pub fn conn(p: String) -> SqliteConnection {
SqliteConnection::establish(&p)
.unwrap_or_else(|_| panic!("Error connecting to {:?}", p))
}
#[derive(Clone)]
pub struct Cache(pub LeetCode);
impl Cache {
fn conn(&self) -> SqliteConnection {
conn(self.0.conf.storage.cache())
}
pub fn clean(&self) -> Result<(), Error> {
Ok(std::fs::remove_file(&self.0.conf.storage.cache())?)
}
pub fn update(self) -> Result<(), Error> {
let c = conn((&self.0.conf.storage.cache()).to_owned());
let ps = self.download_problems()?;
for i in ps.into_iter() {
let target = problems.filter(id.eq(i.id));
diesel::update(target).set(i.to_owned()).execute(&c)?;
}
Ok(())
}
pub fn download_problems(self) -> Result<Vec<Problem>, Error> {
info!("Fetching leetcode problems...");
let mut ps: Vec<Problem> = vec![];
for i in &self.0.conf.sys.categories.to_owned() {
let json = self.0.clone().get_category_problems(&i)?.json()?;
parser::problem(&mut ps, json)?;
}
let count = self.get_problems()?.len();
if count == 0 {
ps.sort_by(|a, b| b.id.partial_cmp(&a.id).unwrap_or(std::cmp::Ordering::Equal));
diesel::insert_into(problems).values(&ps).execute(&self.conn())?;
}
Ok(ps)
}
pub fn get_desc(&self, rfid: i32) -> Result<Question, Error> {
let target: Problem = problems
.filter(fid.eq(rfid))
.first(&self.conn())?;
let ids = match target.level {
1 => target.fid.to_string().green(),
2 => target.fid.to_string().yellow(),
3 => target.fid.to_string().red(),
_ => target.fid.to_string().dimmed(),
};
println!(
"\n[{}] {} {}\n\n",
&ids,
&target.name.bold().underline(),
"is on the run...".dimmed()
);
if target.category != "algorithms".to_string() {
return Err(Error::FeatureError(
"Not support database and shell questions for now".to_string()
));
}
if target.locked {
return Err(Error::FeatureError(
"Not support premium question for now".to_string()
));
}
let mut rdesc = Question::default();
if target.desc.len() > 0 {
rdesc = serde_json::from_str(&target.desc)?;
} else {
let json: Value = self.0.clone().get_question_detail(&target.slug)?.json()?;
parser::desc(&mut rdesc, json)?;
let sdesc = serde_json::to_string(&rdesc)?;
diesel::update(&target).set(desc.eq(sdesc)).execute(&self.conn())?;
}
Ok(rdesc)
}
pub fn get_problems(&self) -> Result<Vec<Problem>, Error> {
Ok(problems.load::<Problem>(&self.conn())?)
}
pub fn new() -> Result<Self, Error> {
let conf = cfg::locate();
let c = conn(conf.storage.cache());
diesel::sql_query(CREATE_PROBLEMS_IF_NOT_EXISTS).execute(&c)?;
Ok(Cache(LeetCode::new()))
}
}