diff --git a/Cargo.lock b/Cargo.lock index a7b1a62..ad28b31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,6 +100,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", + "strum_macros 0.25.0", "url", ] @@ -666,7 +667,7 @@ dependencies = [ "serde", "serde_json", "strum", - "strum_macros", + "strum_macros 0.24.3", "tokio", "url", "uuid", @@ -683,7 +684,7 @@ dependencies = [ "futures", "serde", "strum", - "strum_macros", + "strum_macros 0.24.3", "tokio", "tracing", "tracing-error", @@ -1216,6 +1217,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "strum_macros" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9f3bd7d2e45dcc5e265fbb88d6513e4747d8ef9444cf01a533119bce28a157" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.18", +] + [[package]] name = "syn" version = "1.0.109" diff --git a/Cargo.toml b/Cargo.toml index a6c106b..787256d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,5 @@ reqwest = { version = "0.11.18", features = ["blocking", "json"] } serde = "1.0.164" serde_derive = "1.0.164" serde_json = "1.0.97" +strum_macros = "0.25.0" url = "2.4.0" diff --git a/src/config/mod.rs b/src/config/mod.rs index 1399c31..82fce95 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -5,7 +5,7 @@ use serde_derive::{Deserialize, Serialize}; macro_rules! pub_struct { ($name:ident {$($field:ident: $t:ty,)*}) => { - #[derive(Serialize, Deserialize, Clone)] + #[derive(Serialize, Deserialize, Clone, PartialEq)] pub(crate) struct $name { $(pub(crate) $field: $t), * } @@ -33,7 +33,7 @@ impl Secrets { } } -#[derive(Serialize, Deserialize, Clone)] +#[derive(Serialize, Deserialize, Clone, PartialEq)] pub(crate) struct LemmyLogin { pub(crate) username: String, password: String @@ -49,7 +49,7 @@ impl LemmyLogin { } } -#[derive(Serialize, Deserialize, Clone)] +#[derive(Serialize, Deserialize, Clone, PartialEq)] pub(crate) struct RedditLogin { pub(crate) app_id: String, app_secret: String, @@ -94,7 +94,7 @@ pub_struct!(FeedCommunities { volume: LemmyCommunities, }); -#[derive(Serialize, Deserialize, Clone)] +#[derive(Serialize, Deserialize, Clone, PartialEq, strum_macros::Display)] #[allow(non_camel_case_types)] pub(crate) enum LemmyCommunities { aobwebnovel, diff --git a/src/main.rs b/src/main.rs index 6a21857..8c8114c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,9 @@ use chrono::Utc; -use config::{Config, PrevPost, Secrets}; +use config::{Config, PrevPost, Secrets, LemmyCommunities}; use lemmy_api_common::{ person::{Login, LoginResponse}, post::{CreatePost, GetPosts, GetPostsResponse}, - sensitive::Sensitive, + sensitive::Sensitive, community::{ListCommunities, ListCommunitiesResponse}, }; use lemmy_db_schema::{ newtypes::{CommunityId, LanguageId}, @@ -30,6 +30,7 @@ struct Bot { secrets: Secrets, config: Config, post_history: Vec, + community_ids: CommunitiesVector, auth: Sensitive, } @@ -39,6 +40,7 @@ impl Bot { secrets: Secrets::load(), config: Config::load(), post_history: PrevPost::load(), + community_ids: CommunitiesVector::new(), auth: Sensitive::new("".to_string()), } } @@ -94,12 +96,61 @@ fn list_posts(auth: &Sensitive) -> GetPostsResponse { return serde_json::from_str(&res).unwrap(); } +struct CommunitiesVector { + ids: Vec<(CommunityId, String)>, +} + +impl CommunitiesVector { + fn new() -> CommunitiesVector { + CommunitiesVector{ids: vec![]} + } + + fn load(&mut self, auth: &Sensitive) { + let params = ListCommunities { + auth: Some(auth.clone()), + ..Default::default() + }; + + let res = CLIENT + .get("https://lemmy.neshweb.net/api/v3/community/list") + .query(¶ms) + .send() + .unwrap() + .text() + .unwrap(); + + let site_data: ListCommunitiesResponse = serde_json::from_str(&res).unwrap(); + + let mut ids = [].to_vec(); + + site_data.communities.iter().for_each(|entry| { + let new_id = (entry.community.id, entry.community.name.clone()); + ids.push(new_id); + }); + + self.ids = ids; + } + + fn find(&self, name: &LemmyCommunities) -> CommunityId { + let mut ret_id = CommunityId(0); + + self.ids.iter().for_each(|id| { + let id_name = &id.1; + if &name.to_string() == id_name { + ret_id = id.0; + } + }); + return ret_id; + } +} + fn main() { // Get all needed auth tokens at the start let mut old = Utc::now().time(); let mut this = Bot::new(); println!("{}", this.secrets.lemmy.username); this.login(); + this.community_ids.load(&this.auth); // Create empty eTag list println!("TODO: Etag list"); @@ -108,11 +159,16 @@ fn main() { loop { let start = Utc::now(); print!("\x1B[2J\x1B[1;1H"); - println!("Started loop at {} {}", start.format("%H:%M:%S"), start.timezone()); + println!( + "Started loop at {} {}", + start.format("%H:%M:%S"), + start.timezone() + ); if start.time() - old > chrono::Duration::seconds(6) { old = start.time(); this.config = Config::load(); + this.community_ids.load(&this.auth); } // Start the polling process @@ -144,14 +200,14 @@ fn main() { let item = &data.items[0]; let new_post = CreatePost { name: item.title.clone(), - community_id: CommunityId(3), // TODO get community id by using community name at the start, save it in a list, planned refresh once a day + community_id: this.community_ids.find(&feed.communities.chapter), url: Some(Url::parse(&item.url).unwrap()), body: Some( "[Reddit](https://reddit.com)\n\n[Discord](https://discord.com)".into(), ), honeypot: None, nsfw: Some(false), - language_id: Some(LanguageId(0)), // TODO get English language id by api (at the start) + language_id: Some(LanguageId(37)), // TODO get this id once every few hours per API request, the ordering of IDs suggests that the EN Id might change in the future auth: this.auth.clone(), }; post_queue.push(new_post); @@ -171,7 +227,7 @@ fn main() { PrevPost::save(&this.post_history); post_queue.iter().for_each(|post| { - println!("Posted: {}", post.name); + println!("Posting: {}", post.name); this.post(post.clone()); });