Skip to content

Commit

Permalink
Refactor response parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
pophilpo committed Jul 22, 2024
1 parent 389685f commit 0722820
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 43 deletions.
8 changes: 4 additions & 4 deletions src/project_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::errors::{GetResponseError, ProjectGeneratorError};
use crate::html;
use crate::project_templates::{PYTHON_TEMPLATE, RUST_TEMPLATE};
use crate::queries;
use crate::response_types::Response;
use crate::response_types::{ContentResponse, EditorResponse, ProblemSetResponse, Response};

#[derive(strum_macros::Display, strum_macros::VariantNames)]
pub enum ProjectType {
Expand Down Expand Up @@ -86,12 +86,12 @@ impl Generator {
#[allow(dead_code)]
pub fn get_problem_set(&self) -> Result<Response, GetResponseError> {
let query = queries::GraphQLPayload::problem_set_query();
query.get_response()
query.get_response::<ProblemSetResponse>()
}

fn get_problem_content(&self) -> Result<String, ProjectGeneratorError> {
let query = queries::GraphQLPayload::content_query(self.project_title.clone());
let response = query.get_response()?;
let response = query.get_response::<ContentResponse>()?;

// FIXME: pass lang heere
let content = response.get_content(String::from("rust"));
Expand All @@ -100,7 +100,7 @@ impl Generator {

fn get_editor_code(&self, project_lang: String) -> Result<String, ProjectGeneratorError> {
let query = queries::GraphQLPayload::editor_data_query(self.project_title.clone());
let response = query.get_response()?;
let response = query.get_response::<EditorResponse>()?;
let content = response.get_content(project_lang);

Ok(content.unwrap())
Expand Down
9 changes: 6 additions & 3 deletions src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::Serialize;
use serde_json::{Map, Value};

use crate::errors::GetResponseError;
use crate::response_types::Response;
use crate::response_types::{Response, ResponseHandler};

const PROBLEM_SET_QUERY: &str = r#"
query problemsetQuestionList($categorySlug: String, $limit: Int, $skip: Int, $filters: QuestionListFilterInput) {
Expand Down Expand Up @@ -91,14 +91,17 @@ impl GraphQLPayload {
}
}

pub fn get_response(&self) -> Result<Response, GetResponseError> {
pub fn get_response<T>(&self) -> Result<Response, GetResponseError>
where
T: ResponseHandler,
{
let client = Client::new();
let response = client
.post("https://leetcode.com/graphql")
.header("Content-Type", "application/json")
.json(&self)
.send()?;

Response::from_response(response)
T::parse_response(response)
}
}
68 changes: 32 additions & 36 deletions src/response_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,50 @@ pub enum Response {
Editor(EditorResponse),
ProblemSet(ProblemSetResponse),
}
impl Response {
pub fn from_response(response: ReqwestResponse) -> Result<Self, GetResponseError> {

pub trait ResponseHandler {
fn parse_response(response: ReqwestResponse) -> Result<Response, GetResponseError>;
}

impl ResponseHandler for ContentResponse {
fn parse_response(response: ReqwestResponse) -> Result<Response, GetResponseError> {
let body = response.text()?;

if let Ok(content_response) = serde_json::from_str::<ContentResponse>(&body) {
return Ok(Response::Content(content_response));
Ok(Response::Content(content_response))
} else {
Err(GetResponseError::ParseError(serde_json::Error::custom("Failed to deserialize response")))
}
}
}

impl ResponseHandler for EditorResponse {
fn parse_response(response: ReqwestResponse) -> Result<Response, GetResponseError> {
let body = response.text()?;

if let Ok(editor_response) = serde_json::from_str::<EditorResponse>(&body) {
return Ok(Response::Editor(editor_response));
Ok(Response::Editor(editor_response))
} else {
Err(GetResponseError::ParseError(serde_json::Error::custom("Failed to deserialize response")))
}
}
}


impl ResponseHandler for ProblemSetResponse {
fn parse_response(response: ReqwestResponse) -> Result<Response, GetResponseError> {
let body = response.text()?;

if let Ok(problem_set_response) = serde_json::from_str::<ProblemSetResponse>(&body) {
return Ok(Response::ProblemSet(problem_set_response));
Ok(Response::ProblemSet(problem_set_response))
} else {
Err(GetResponseError::ParseError(serde_json::Error::custom("Failed to deserialize response")))
}

Err(GetResponseError::ParseError(serde_json::Error::custom(
"Failed to deserialize response",
)))
}
}


impl Response {
pub fn get_content(&self, lang: String) -> Option<String> {
// Get markdown or code text based on the response type

Expand Down Expand Up @@ -71,11 +94,6 @@ pub struct QuestionData {
#[derive(Deserialize, Debug)]
pub struct Question {
pub content: String,
#[serde(rename = "dataSchemas")]
pub data_schemas: Vec<String>,

#[serde(rename = "mysqlSchemas")]
pub mysql_schemas: Vec<String>,
}

#[derive(Deserialize, Debug)]
Expand All @@ -90,35 +108,13 @@ pub struct EditorData {

#[derive(Deserialize, Debug)]
pub struct EditorQuestion {
#[serde(rename = "questionId")]
pub question_id: String,

#[serde(rename = "questionFrontendId")]
pub question_frontend_id: String,

#[serde(rename = "codeSnippets")]
pub code_snippets: Vec<CodeSnippet>,

#[serde(rename = "envInfo")]
pub env_info: String,

#[serde(rename = "enableRunCode")]
pub enable_run_code: bool,

#[serde(rename = "hasFrontendPreview")]
pub has_frontend_preview: bool,

#[serde(rename = "frontendPreviews")]
pub frontend_previews: String,
}

#[derive(Deserialize, Debug)]
pub struct CodeSnippet {
pub lang: String,

#[serde(rename = "langSlug")]
pub lang_slug: String,

pub code: String,
}

Expand Down

0 comments on commit 0722820

Please sign in to comment.