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
pub mod models;
mod parser;
mod sql;
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 reqwest::Error as ReqwestError;
pub fn conn(p: String) -> SqliteConnection {
SqliteConnection::establish(&p)
.unwrap_or_else(|_| panic!("Error connecting to {:?}", p))
}
pub struct Cache(pub LeetCode);
impl Cache {
fn conn(&self) -> SqliteConnection {
conn(self.0.conf.storage.cache())
}
pub fn clean(&self) -> Result<(), Error> {
let res = std::fs::remove_file(&self.0.conf.storage.cache());
if res.is_err() {
let err = res.err().unwrap();
error!("{:?}", Error::CacheError(format!("clean local cache failed -> {}", &err)));
return Err(Error::CacheError(format!("clean local cache failed -> {}", &err)));
}
Ok(())
}
pub fn update(self) -> Result<(), Error> {
let c = conn((&self.0.conf.storage.cache()).to_owned());
let res = self.download_problems();
if res.is_err() {
return Err(res.err().unwrap());
}
for i in res.unwrap().into_iter() {
let target = problems.filter(id.eq(i.id));
let u_res = diesel::update(target).set(i.to_owned()).execute(&c);
if u_res.is_err() {
let err = u_res.err().unwrap();
error!("{:?}", Error::CacheError(format!("Update cache failed -> {}", &err)));
return Err(Error::CacheError(format!("Update cache failed -> {}", &err)));
}
}
Ok(())
}
pub fn download_problems(self) -> Result<Vec<Problem>, Error> {
info!("Downloading leetcode problems...");
let mut ps: Vec<Problem> = vec![];
for i in &self.0.conf.sys.categories.to_owned() {
let res = self.0.clone().get_category_problems(&i);
if res.is_err() {
return Err(res.err().unwrap());
}
let json: Result<Value, ReqwestError> = res.unwrap().json();
if json.is_err() {
error!("{:?}", Error::DownloadError(format!("category {}", &i)));
return Err(Error::DownloadError(format!("category {}", &i)));
}
let res = parser::parse_problem(&mut ps, json.unwrap());
if res.is_err() {
error!("{:?}", Error::DownloadError(format!("category {}", &i)));
return Err(Error::DownloadError(format!("category {}", &i)));
}
}
let j = serde_json::to_string(&ps);
if j.is_err() {
error!("{:?}", Error::ParseError("data from cache"));
return Err(Error::ParseError("data from cache"));
}
let count = self.get_problems().unwrap().len();
if count == 0 {
ps.sort_by(|a, b| b.id.partial_cmp(&a.id).unwrap());
let res = diesel::insert_into(problems).values(&ps).execute(&self.conn());
if res.is_err() {
let err = res.err().unwrap();
error!("{:?}", Error::CacheError(format!("Save to cache failed -> {}", &err)));
return Err(Error::CacheError(format!("Save to cache failed -> {}", &err)));
}
}
Ok(ps)
}
pub fn get_problems(&self) -> Result<Vec<Problem>, Error> {
let res = problems.load::<Problem>(&self.conn());
if res.is_err() {
let err = res.err().unwrap();
warn!("Select problems from cache failed -> {:?} -> try downloading", &err);
return Err(Error::CacheError(
format!("Select problems from cache failed -> {:?} -> try downloading", &err)
));
}
Ok(res.unwrap())
}
pub fn new() -> Result<Self, Error> {
let conf = cfg::locate();
let c = conn(conf.storage.cache());
let r = diesel::sql_query(CREATE_PROBLEMS_IF_NOT_EXISTS).execute(&c);
if r.is_err() {
let err = r.err().unwrap();
error!("{:?}", Error::CacheError(format!("Create local cache failed -> {}", &err)));
return Err(Error::CacheError(format!("Create local cache failed -> {}", &err)));
}
Ok(Cache(LeetCode::new()))
}
}