Skip to content

Raise Error::CookieError more often #67

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 43 additions & 17 deletions src/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ use self::sql::*;
use crate::{cfg, err::Error, plugins::LeetCode};
use colored::Colorize;
use diesel::prelude::*;
use serde::de::DeserializeOwned;
use serde_json::Value;
use std::collections::HashMap;
use reqwest::Response;

/// sqlite connection
pub fn conn(p: String) -> SqliteConnection {
Expand Down Expand Up @@ -58,6 +60,34 @@ impl Cache {
Ok(())
}

async fn get_user_info(&self) -> Result<(String,bool), Error> {
let user = parser::user(
self.clone().0
.get_user_info().await?
.json().await?
);
match user {
None => Err(Error::NoneError),
Some(None) => Err(Error::CookieError),
Some(Some((s,b))) => Ok((s,b))
}
}

async fn is_session_bad(&self) -> bool {
// i.e. self.get_user_info().contains_err(Error::CookieError)
match self.get_user_info().await {
Err(Error::CookieError) => true,
_ => false
}
}

async fn resp_to_json<T: DeserializeOwned>(&self, resp: Response) -> Result<T, Error> {
let maybe_json: Result<T,_> = resp.json().await;
if maybe_json.is_err() && self.is_session_bad().await {
Err(Error::CookieError)
} else { Ok(maybe_json?) }
}

/// Download leetcode problems to db
pub async fn download_problems(self) -> Result<Vec<Problem>, Error> {
info!("Fetching leetcode problems...");
Expand All @@ -69,7 +99,7 @@ impl Cache {
.clone()
.get_category_problems(i)
.await?
.json()
.json() // does not require LEETCODE_SESSION
.await?;
parser::problem(&mut ps, json).ok_or(Error::NoneError)?;
}
Expand Down Expand Up @@ -100,7 +130,7 @@ impl Cache {
.0
.get_question_daily()
.await?
.json()
.json() // does not require LEETCODE_SESSION
.await?
).ok_or(Error::NoneError)
}
Expand Down Expand Up @@ -265,30 +295,20 @@ impl Cache {

/// TODO: The real delay
async fn recur_verify(&self, rid: String) -> Result<VerifyResult, Error> {
use serde_json::{from_str, Error as SJError};
use std::time::Duration;

trace!("Run veriy recursion...");
std::thread::sleep(Duration::from_micros(3000));

// debug resp raw text
let debug_raw = self
let json: VerifyResult = self.resp_to_json(
self
.clone()
.0
.verify_result(rid.clone())
.await?
.text()
.await?;
debug!("debug resp raw text: \n{:#?}", &debug_raw);
if debug_raw.is_empty() {
return Err(Error::CookieError);
}

// debug json deserializing
let debug_json: Result<VerifyResult, SJError> = from_str(&debug_raw);
debug!("debug json deserializing: \n{:#?}", &debug_json);
).await?;

Ok(debug_json?)
Ok(json)
}

/// Exec problem filter —— Test or Submit
Expand All @@ -307,10 +327,16 @@ impl Cache {
.clone()
.run_code(json.clone(), url.clone(), refer.clone())
.await?
.json()
.json() // does not require LEETCODE_SESSION (very oddly)
.await?;
trace!("Run code result {:#?}", run_res);

// Check if leetcode accepted the Run request
if match run {
Run::Test => run_res.interpret_id.is_empty(),
Run::Submit => run_res.submission_id == 0
} { return Err(Error::CookieError) }

let mut res: VerifyResult = VerifyResult::default();
while res.state != "SUCCESS" {
res = match run {
Expand Down
15 changes: 15 additions & 0 deletions src/cache/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@ pub fn daily(v: Value) -> Option<i32> {
.parse().ok()
}

/// user parser
pub fn user(v: Value) -> Option<Option<(String,bool)>> {
// None => error while parsing
// Some(None) => User not found
// Some("...") => username
let user = v.as_object()?.get("data")?
.as_object()?.get("user")?;
if *user == Value::Null { return Some(None) }
let user = user.as_object()?;
Some(Some((
user.get("username")?.as_str()?.to_owned(),
user.get("isCurrentUserPremium")?.as_bool()?
)))
}

pub use ss::ssr;
/// string or squence
mod ss {
Expand Down
28 changes: 28 additions & 0 deletions src/plugins/leetcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,34 @@ impl LeetCode {
.await
}

pub async fn get_user_info(self) -> Result<Response, Error> {
trace!("Requesting user info...");
let url = &self.conf.sys.urls.get("graphql").ok_or(Error::NoneError)?;
let mut json: Json = HashMap::new();
json.insert("operationName", "a".to_string());
json.insert(
"query",
"query a {
user {
username
isCurrentUserPremium
}
}".to_owned()
);

Req {
default_headers: self.default_headers,
refer: None,
info: false,
json: Some(json),
mode: Mode::Post,
name: "get_user_info",
url: (*url).to_string(),
}
.send(&self.client)
.await
}

/// Get daily problem
pub async fn get_question_daily(self) -> Result<Response, Error> {
trace!("Requesting daily problem...");
Expand Down