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::{
community::GetCommunity,
community::{GetCommunity, GetCommunityResponse},
lemmy_db_schema::newtypes::CommunityId,
person::{Login, LoginResponse},
sensitive::Sensitive,
};
use reqwest::Client;
use serde_json::Value;
use std::fmt;
static API_VERSION: i32 = 3;
@ -31,17 +30,13 @@ pub fn api_url(suffix: &str) -> String {
}
#[derive(Debug)]
pub enum WordleError {
ParseFailed,
LoginFailed,
NoNewPostId,
}
struct LoginFailedError;
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 {
write!(f, "Oh no, something bad went down")
write!(f, "Login failed.")
}
}
@ -59,19 +54,8 @@ pub async fn get_community_id(
.query(&params)
.send()
.await?;
let text = response.text().await?;
// 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))
let data = response.json::<GetCommunityResponse>().await?;
Ok(data.community_view.community.id)
}
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);
}
Err(Box::new(WordleError::LoginFailed))
Err(Box::new(LoginFailedError))
}

View File

@ -1,11 +1,10 @@
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 serde::Deserialize;
use serde_json::Value;
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)]
struct WordleData {
@ -21,21 +20,16 @@ async fn get_current_nyt_wordle_data() -> Result<WordleData, Box<dyn std::error:
.await?;
// Did it work?
response.error_for_status_ref()?;
let text = response.text().await?;
let data: WordleData = serde_json::from_str(&text)?;
let data = response.json::<WordleData>().await?;
println!("{:?}", 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);
let client = Client::new();
let auth = lemmy_login(&client).await?;
// 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();
@ -61,7 +55,7 @@ async fn post_to_lemmy(data: &WordleData) -> Result<(), Box<dyn std::error::Erro
community_id,
name: title,
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,
..Default::default()
};
@ -71,22 +65,19 @@ async fn post_to_lemmy(data: &WordleData) -> Result<(), Box<dyn std::error::Erro
.json(&params)
.send()
.await?;
let data = response.json::<Value>().await?;
// 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(())
let data = response.json::<PostResponse>().await?;
Ok(data.post_view.post.id)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
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?;
post_to_lemmy(&data).await?;
let id = post_to_lemmy(&data, &client, auth).await?;
println!("New post ID: {}", id);
Ok(())
}