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
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
@@ -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 {
@@ -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...");
@@ -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)?;
}
@@ -100,7 +130,7 @@ impl Cache {
.0
.get_question_daily()
.await?
.json()
.json() // does not require LEETCODE_SESSION
.await?
).ok_or(Error::NoneError)
}
@@ -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
@@ -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 {
15 changes: 15 additions & 0 deletions src/cache/parser.rs
Original file line number Diff line number Diff line change
@@ -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 {
28 changes: 28 additions & 0 deletions src/plugins/leetcode.rs
Original file line number Diff line number Diff line change
@@ -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...");