Prevent duplicate posts

This commit is contained in:
prcrst 2023-07-07 22:44:11 +02:00
parent 04fdd8908f
commit 4219b1d5d8
2 changed files with 77 additions and 21 deletions

View File

@ -58,11 +58,11 @@ pub async fn get_community_id(
Ok(data.community_view.community.id) Ok(data.community_view.community.id)
} }
pub async fn lemmy_login(client: &Client) -> Result<Sensitive<String>, Box<dyn std::error::Error>> { pub async fn lemmy_login(client: &Client, user: &Sensitive<String>, password: &Sensitive<String>) -> Result<Sensitive<String>, Box<dyn std::error::Error>> {
println!("Logging in"); println!("Logging in");
let params = Login { let params = Login {
username_or_email: lemmy_user(), username_or_email: user.clone(),
password: lemmy_password()?, password: password.clone(),
..Default::default() ..Default::default()
}; };

View File

@ -1,16 +1,27 @@
use chrono::{Datelike, Month, Utc}; use chrono::{Datelike, Month, Utc};
use lemmy_api_common::{post::{CreatePost, PostResponse}, sensitive::Sensitive, lemmy_db_schema::newtypes::PostId}; use lemmy_api_common::{
lemmy_db_schema::{newtypes::PostId, source::post::Post, SortType},
person::{GetPersonDetails, GetPersonDetailsResponse},
post::{CreatePost, PostResponse},
sensitive::Sensitive,
};
use reqwest::{Client, Url}; use reqwest::{Client, Url};
use serde::Deserialize; use serde::Deserialize;
mod helper; mod helper;
use crate::helper::{get_community_id, lemmy_community, lemmy_login}; use crate::helper::{get_community_id, lemmy_community, lemmy_login, lemmy_password, lemmy_user};
#[derive(Debug, Deserialize, Default)] #[derive(Debug, Deserialize, Default)]
struct WordleData { struct WordleData {
days_since_launch: i64, days_since_launch: i64,
} }
impl std::fmt::Display for WordleData {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.days_since_launch)
}
}
async fn get_current_nyt_wordle_data() -> Result<WordleData, Box<dyn std::error::Error>> { async fn get_current_nyt_wordle_data() -> Result<WordleData, Box<dyn std::error::Error>> {
println!("Fetching NYT wordle data"); println!("Fetching NYT wordle data");
let now = Utc::now(); let now = Utc::now();
@ -21,27 +32,22 @@ async fn get_current_nyt_wordle_data() -> Result<WordleData, Box<dyn std::error:
// Did it work? // Did it work?
response.error_for_status_ref()?; response.error_for_status_ref()?;
let data = response.json::<WordleData>().await?; let data = response.json::<WordleData>().await?;
println!("{:?}", data); println!("Wordle number: {}", data);
Ok(data) Ok(data)
} }
async fn post_to_lemmy(data: &WordleData, client: &Client, auth: Sensitive<String>) -> Result<PostId, Box<dyn std::error::Error>> { async fn post_to_lemmy(
println!("Posting to lemmy: {:?}", data); data: &WordleData,
client: &Client,
auth: Sensitive<String>,
date: &chrono::DateTime<Utc>,
) -> Result<PostId, Box<dyn std::error::Error>> {
println!("Posting number {} to lemmy", data);
// 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 title = make_title(data, date)?;
let month = Month::try_from(now.month() as u8)?;
let title = format!(
"Wordle #{} - {} {} {} {}",
data.days_since_launch,
now.weekday(),
now.day(),
month.name(),
now.year()
);
let url = Url::parse( let url = Url::parse(
format!( format!(
"https://www.nytimes.com/games/wordle/index.html#{}", "https://www.nytimes.com/games/wordle/index.html#{}",
@ -69,14 +75,64 @@ async fn post_to_lemmy(data: &WordleData, client: &Client, auth: Sensitive<Strin
Ok(data.post_view.post.id) Ok(data.post_view.post.id)
} }
fn make_title(
data: &WordleData,
date: &chrono::DateTime<Utc>,
) -> Result<String, Box<dyn std::error::Error>> {
let month = Month::try_from(date.month() as u8)?;
Ok(format!(
"Wordle #{} - {} {} {} {}",
data.days_since_launch,
date.weekday(),
date.day(),
month.name(),
date.year()
))
}
async fn get_latest_post(
client: &Client,
user: &Sensitive<String>,
) -> Result<Option<Post>, Box<dyn std::error::Error>> {
let params = GetPersonDetails {
username: Some(user.to_string()),
sort: Some(SortType::New),
..Default::default()
};
let response = client
.get(helper::api_url("user"))
.query(&params)
.send()
.await?;
// let data = response.text().await?;
let data = response.json::<GetPersonDetailsResponse>().await?;
if let Some(postview) = data.posts.first() {
return Ok(Some(postview.post.clone()));
}
Ok(None)
}
#[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 now = Utc::now();
let user = lemmy_user();
let password = lemmy_password()?;
let client = Client::new(); let client = Client::new();
let auth = lemmy_login(&client).await?; let auth = lemmy_login(&client, &user, &password).await?;
let data = get_current_nyt_wordle_data().await?; let data = get_current_nyt_wordle_data().await?;
let id = post_to_lemmy(&data, &client, auth).await?; if let Some(latest_post) = get_latest_post(&client, &user).await? {
if latest_post.name == make_title(&data, &now)? {
println!("The current wordle has already been posted.");
return Ok(());
}
}
let id = post_to_lemmy(&data, &client, auth, &now).await?;
println!("New post ID: {}", id); println!("New post ID: {}", id);
Ok(()) Ok(())