diff --git a/src/main.rs b/src/main.rs index c4c8326..f5aacd0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,74 +61,21 @@ enum ErrorResponse { InternalError(String), } -#[get("//feed.rss?")] -async fn syndication_rss_route( - project: &str, - page: Option, -) -> Result { - let page = page.unwrap_or(0); - let project_url = format!("{}{}", COHOST_ACCOUNT_API_URL, project); - let posts_url = cohost_posts_api_url(project, page); - - let client = match Client::builder().user_agent(user_agent()).build() { - Ok(v) => v, - Err(e) => { - let err = format!("Couldn't build a reqwest client: {:?}", e); - eprintln!("{}", err); - return Err(ErrorResponse::InternalError(err)); - } - }; - - eprintln!("making request to {}", project_url); - let project_data: CohostAccount = match client.get(project_url).send().await { - Ok(v) => match v.status() { - StatusCode::OK => match v.json::().await { - Ok(a) => a, - Err(e) => { - let err = format!("Couldn't deserialize Cohost project '{}': {:?}", project, e); - eprintln!("{}", err); - return Err(ErrorResponse::InternalError(err)); - } - }, - // TODO NORA: Handle possible redirects - s => { - let err = format!( - "Didn't receive status code 200 for Cohost project '{}'; got {:?} instead.", - project, s - ); - eprintln!("{}", err); - return Err(ErrorResponse::NotFound(err)); - } - }, - Err(e) => { - let err = format!( - "Error making request to Cohost for project '{}': {:?}", - project, e - ); - eprintln!("{}", err); - return Err(ErrorResponse::InternalError(err)); - } - }; - +async fn get_page_data( + client: &mut Client, + project_id: &str, + page: u64, +) -> Result { + let posts_url = cohost_posts_api_url(project_id, page); eprintln!("making request to {}", posts_url); match client.get(posts_url).send().await { Ok(v) => match v.status() { StatusCode::OK => match v.json::().await { - Ok(page_data) => { - return Ok(RssResponse { - inner: syndication::channel_for_posts_page( - project, - page, - project_data, - page_data, - ) - .to_string(), - }); - } + Ok(page_data) => Ok(page_data), Err(e) => { let err = format!( "Couldn't deserialize Cohost posts page for '{}': {:?}", - project, e + project_id, e ); eprintln!("{}", err); return Err(ErrorResponse::InternalError(err)); @@ -144,66 +91,104 @@ async fn syndication_rss_route( Err(e) => { let err = format!( "Error making request to Cohost for posts for project '{}': {:?}", - project, e + project_id, e ); eprintln!("{}", err); return Err(ErrorResponse::InternalError(err)); } - }; + } } -#[get("/.well-known/webfinger?")] -async fn webfinger_route(params: HashMap) -> Option> { - if params.len() != 1 { - eprintln!( - "Too may or too few parameters. Expected 1, got {}", - params.len() - ); - return None; +#[get("//feed.rss?")] +async fn syndication_rss_route( + project: &str, + page: Option, +) -> Result { + let page = page.unwrap_or(0); + let mut client = get_client()?; + + let project_data = get_project_data(&mut client, project).await?; + let page_data = get_page_data(&mut client, project, page).await?; + Ok(RssResponse { + inner: syndication::channel_for_posts_page(project, page, project_data, page_data) + .to_string(), + }) +} + +async fn get_project_data( + client: &mut Client, + project_id: &str, +) -> Result { + let project_url = format!("{}{}", COHOST_ACCOUNT_API_URL, project_id); + eprintln!("making request to {}", project_url); + match client.get(project_url).send().await { + Ok(v) => match v.status() { + StatusCode::OK => match v.json::().await { + Ok(a) => Ok(a), + Err(e) => { + let err = format!( + "Couldn't deserialize Cohost project '{}': {:?}", + project_id, e + ); + eprintln!("{}", err); + Err(ErrorResponse::InternalError(err)) + } + }, + // TODO NORA: Handle possible redirects + s => { + let err = format!( + "Didn't receive status code 200 for Cohost project '{}'; got {:?} instead.", + project_id, s + ); + eprintln!("{}", err); + Err(ErrorResponse::NotFound(err)) + } + }, + Err(e) => { + let err = format!( + "Error making request to Cohost for project '{}': {:?}", + project_id, e + ); + eprintln!("{}", err); + Err(ErrorResponse::InternalError(err)) + } } - let client = match Client::builder().user_agent(user_agent()).build() { - Ok(v) => v, +} + +fn get_client() -> Result { + match Client::builder().user_agent(user_agent()).build() { + Ok(v) => Ok(v), Err(e) => { let err = format!("Couldn't build a reqwest client: {:?}", e); eprintln!("{}", err); - return None; + Err(ErrorResponse::InternalError(err)) } - }; - if let Some(param) = params.iter().next() { - let url = format!("{}{}", COHOST_ACCOUNT_API_URL, param.0); - eprintln!("making request to {}", url); - match client.get(url).send().await { - Ok(v) => { - match v.status() { - StatusCode::OK => match v.json::().await { - Ok(_v) => { - return Some(Json(CohostWebfingerResource::new( - param.0.as_str(), - &ARGS.domain, - &ARGS.base_url, - ))); - } - Err(e) => { - eprintln!("Couldn't deserialize Cohost project '{}': {:?}", param.0, e); - } - }, - // TODO NORA: Handle possible redirects - s => { - eprintln!("Didn't receive status code 200 for Cohost project '{}'; got {:?} instead.", param.0, s); - return None; - } - } - } - Err(e) => { - eprintln!( - "Error making request to Cohost for project '{}': {:?}", - param.0, e - ); - return None; - } - }; } - None +} + +#[get("/.well-known/webfinger?")] +async fn webfinger_route( + params: HashMap, +) -> Result, ErrorResponse> { + if params.len() != 1 { + let err = format!( + "Too may or too few parameters. Expected 1, got {}", + params.len() + ); + eprintln!("{}", err); + return Err(ErrorResponse::InternalError(err)); + } + let mut client = get_client()?; + if let Some(param) = params.iter().next() { + let _project_data = get_project_data(&mut client, param.0.as_str()).await?; + Ok(Json(CohostWebfingerResource::new( + param.0.as_str(), + &ARGS.domain, + &ARGS.base_url, + ))) + } else { + Err(ErrorResponse::NotFound("No project ID provided.".into())) + } } #[rocket::main]