Refactor code to use API struct deserialization

The deserialization errors have been fixed in 0.18.1
This commit is contained in:
prcrst 2023-07-07 17:33:38 +02:00
parent 164bd37987
commit 04fdd8908f
2 changed files with 21 additions and 46 deletions

View File

@ -1,11 +1,10 @@
use lemmy_api_common::{ use lemmy_api_common::{
community::GetCommunity, community::{GetCommunity, GetCommunityResponse},
lemmy_db_schema::newtypes::CommunityId, lemmy_db_schema::newtypes::CommunityId,
person::{Login, LoginResponse}, person::{Login, LoginResponse},
sensitive::Sensitive, sensitive::Sensitive,
}; };
use reqwest::Client; use reqwest::Client;
use serde_json::Value;
use std::fmt; use std::fmt;
static API_VERSION: i32 = 3; static API_VERSION: i32 = 3;
@ -31,17 +30,13 @@ pub fn api_url(suffix: &str) -> String {
} }
#[derive(Debug)] #[derive(Debug)]
pub enum WordleError { struct LoginFailedError;
ParseFailed,
LoginFailed,
NoNewPostId,
}
impl std::error::Error for WordleError {} impl std::error::Error for LoginFailedError {}
impl fmt::Display for WordleError { impl fmt::Display for LoginFailedError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Oh no, something bad went down") write!(f, "Login failed.")
} }
} }
@ -59,19 +54,8 @@ pub async fn get_community_id(
.query(&params) .query(&params)
.send() .send()
.await?; .await?;
let text = response.text().await?; let data = response.json::<GetCommunityResponse>().await?;
Ok(data.community_view.community.id)
// Deserializing from GetCommunityResponse would fail with missing field `followers_url` in Community
let data = serde_json::from_str::<Value>(text.as_str())?;
if let Some(id) = data["community_view"]["community"]
.get("id")
.and_then(|v| v.as_i64())
{
return Ok(CommunityId(i32::try_from(id)?));
}
Err(Box::new(WordleError::ParseFailed))
} }
pub async fn lemmy_login(client: &Client) -> Result<Sensitive<String>, Box<dyn std::error::Error>> { pub async fn lemmy_login(client: &Client) -> Result<Sensitive<String>, Box<dyn std::error::Error>> {
@ -95,5 +79,5 @@ pub async fn lemmy_login(client: &Client) -> Result<Sensitive<String>, Box<dyn s
return Ok(jwt); return Ok(jwt);
} }
Err(Box::new(WordleError::LoginFailed)) Err(Box::new(LoginFailedError))
} }

View File

@ -1,11 +1,10 @@
use chrono::{Datelike, Month, Utc}; use chrono::{Datelike, Month, Utc};
use lemmy_api_common::post::CreatePost; use lemmy_api_common::{post::{CreatePost, PostResponse}, sensitive::Sensitive, lemmy_db_schema::newtypes::PostId};
use reqwest::{Client, Url}; use reqwest::{Client, Url};
use serde::Deserialize; use serde::Deserialize;
use serde_json::Value;
mod helper; mod helper;
use crate::helper::{get_community_id, lemmy_community, lemmy_login, WordleError}; use crate::helper::{get_community_id, lemmy_community, lemmy_login};
#[derive(Debug, Deserialize, Default)] #[derive(Debug, Deserialize, Default)]
struct WordleData { struct WordleData {
@ -21,21 +20,16 @@ async fn get_current_nyt_wordle_data() -> Result<WordleData, Box<dyn std::error:
.await?; .await?;
// Did it work? // Did it work?
response.error_for_status_ref()?; response.error_for_status_ref()?;
let text = response.text().await?; let data = response.json::<WordleData>().await?;
let data: WordleData = serde_json::from_str(&text)?;
println!("{:?}", data); println!("{:?}", data);
Ok(data) Ok(data)
} }
async fn post_to_lemmy(data: &WordleData) -> Result<(), Box<dyn std::error::Error>> { async fn post_to_lemmy(data: &WordleData, client: &Client, auth: Sensitive<String>) -> Result<PostId, Box<dyn std::error::Error>> {
println!("Posting to lemmy: {:?}", data); println!("Posting to lemmy: {:?}", data);
let client = Client::new();
let auth = lemmy_login(&client).await?;
// Get the community id // Get the community id
let community_id = get_community_id(&client, lemmy_community()).await?; let community_id = get_community_id(client, lemmy_community()).await?;
let now = Utc::now(); let now = Utc::now();
@ -61,7 +55,7 @@ async fn post_to_lemmy(data: &WordleData) -> Result<(), Box<dyn std::error::Erro
community_id, community_id,
name: title, name: title,
url: Some(url), url: Some(url),
body: Some("Post your results and discuss your guesses. Have fun!\nNote: there might be spoilers in the thread.".to_owned()), body: Some("Post your results and discuss your guesses. Have fun! \nNote: there might be spoilers in the thread.".to_owned()),
auth, auth,
..Default::default() ..Default::default()
}; };
@ -71,22 +65,19 @@ async fn post_to_lemmy(data: &WordleData) -> Result<(), Box<dyn std::error::Erro
.json(&params) .json(&params)
.send() .send()
.await?; .await?;
let data = response.json::<Value>().await?; let data = response.json::<PostResponse>().await?;
Ok(data.post_view.post.id)
// Again, deserializing using the api struct did not work due to missing fields
if let Some(new_id) = data["post_view"]["post"].get("id") {
println!("New post id: {}", new_id);
} else {
return Err(Box::new(WordleError::NoNewPostId));
}
Ok(())
} }
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("A wordle a day keeps the doctor away!"); println!("A wordle a day keeps the doctor away!");
let client = Client::new();
let auth = lemmy_login(&client).await?;
let data = get_current_nyt_wordle_data().await?; let data = get_current_nyt_wordle_data().await?;
post_to_lemmy(&data).await?; let id = post_to_lemmy(&data, &client, auth).await?;
println!("New post ID: {}", id);
Ok(()) Ok(())
} }