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
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::{
Connection,
SqliteConnection,
RunQueryDsl,
};
use reqwest::Error as ReqwestError;
use serde_json::Value;
pub fn conn(p: String) -> SqliteConnection {
SqliteConnection::establish(&p)
.unwrap_or_else(|_| panic!("Error connecting to {:?}", p))
}
pub struct Cache {
conn: SqliteConnection,
leetcode: LeetCode
}
impl Cache {
pub fn clean(&self) -> Result<(), Error> {
let res = diesel::sql_query(DROP_PROBLEMS).execute(&self.conn);
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 download_problems(self) -> Result<Vec<Problem>, Error> {
info!("Downloading leetcode categories...");
let mut ps: Vec<Problem> = vec![];
for i in &self.leetcode.conf.sys.categories.to_owned() {
let res = self.leetcode
.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"));
}
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 p = cfg::root().join("lc.db");
let c = conn(p.to_string_lossy().to_string());
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{
conn: c,
leetcode: LeetCode::new(),
})
}
}