diff --git a/src/main.rs b/src/main.rs index cee6b2b..a351283 100644 --- a/src/main.rs +++ b/src/main.rs @@ -164,7 +164,7 @@ fn main() -> Result<(), Box> { config.get("email-in-reply-to").ok(), ); trace_var_!(email); - let mut wiki = Mediawiki::new( + let wiki = Mediawiki::new( &config["wiki-server-url"], &config["wiki-http-user"], &config["wiki-http-password"], @@ -191,7 +191,7 @@ fn main() -> Result<(), Box> { if !matches!(last_state, ProgramState::Normal) { eprintln!("WARNING: last run was a long time ago, resetting state."); last_state = ProgramState::Normal; - do_cleanup(999, &today, &config, &hedgedoc, &email, &mut wiki)?; + do_cleanup(999, &today, &config, &hedgedoc, &email, &wiki)?; // reset will have cleared in-reply-to if it existed let (base, from, to, _) = email.into_parts(); email = SimpleEmail::from_parts(base, from, to, config.get("email-in-reply-to").ok()); @@ -241,7 +241,7 @@ fn main() -> Result<(), Box> { let action: &ST = &TRANSITION_LUT[last_state as usize][intended_state as usize]; verboseln!("Notewendige Aktionen: {}", action.to_string().cyan()); // run action, which is responsible for updating the state as needed - action.get()(delta, &plenum_day, &config, &hedgedoc, &email, &mut wiki)?; + action.get()(delta, &plenum_day, &config, &hedgedoc, &email, &wiki)?; // shutdown config.set("state-last-run", &today.to_string())?; @@ -372,7 +372,7 @@ fn get_pad_info(config: &KV, hedgedoc: &HedgeDoc) -> (String, String, String, us fn do_announcement( ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, - _wiki: &mut Mediawiki, + _wiki: &Mediawiki, ) -> Result<(), Box> { NYI!("trace/verbose annotations"); // fetch current pad contents & summarize @@ -405,7 +405,7 @@ fn do_announcement( fn do_reminder( ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, - _wiki: &mut Mediawiki, + _wiki: &Mediawiki, ) -> Result<(), Box> { NYI!("trace/verbose annotations"); // fetch current pad contents & summarize @@ -459,7 +459,7 @@ fn do_reminder( #[allow(unused_variables)] fn do_protocol( ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, - wiki: &mut Mediawiki, + wiki: &Mediawiki, ) -> Result<(), Box> { NYI!("trace/verbose annotations"); let (current_pad_id, pad_content, toc, n_topics) = get_pad_info(config, hedgedoc); @@ -490,7 +490,7 @@ fn do_protocol( #[allow(unused_must_use)] fn do_cleanup( _ttp: i64, _plenum_day: &NaiveDate, config: &KV, _hedgedoc: &HedgeDoc, _email: &SimpleEmail, - _wiki: &mut Mediawiki, + _wiki: &Mediawiki, ) -> Result<(), Box> { NYI!("trace/verbose annotations"); config.delete("state-toc"); @@ -509,7 +509,7 @@ type TransitionFunction = fn( config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, - wiki: &mut Mediawiki, + wiki: &Mediawiki, ) -> Result<(), Box>; #[rustfmt::skip] @@ -556,14 +556,14 @@ impl Display for ST { } fn nop( - _: i64, _: &NaiveDate, _: &KV, _: &HedgeDoc, _: &SimpleEmail, _: &mut Mediawiki, + _: i64, _: &NaiveDate, _: &KV, _: &HedgeDoc, _: &SimpleEmail, _: &Mediawiki, ) -> Result<(), Box> { Ok(()) } fn do_clean_announcement( ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, - wiki: &mut Mediawiki, + wiki: &Mediawiki, ) -> Result<(), Box> { do_cleanup(ttp, plenum_day, config, hedgedoc, email, wiki)?; do_announcement(ttp, plenum_day, config, hedgedoc, email, wiki) @@ -571,7 +571,7 @@ fn do_clean_announcement( fn do_clean_reminder( ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, - wiki: &mut Mediawiki, + wiki: &Mediawiki, ) -> Result<(), Box> { do_cleanup(ttp, plenum_day, config, hedgedoc, email, wiki)?; do_reminder(ttp, plenum_day, config, hedgedoc, email, wiki) diff --git a/src/mediawiki.rs b/src/mediawiki.rs index 82b067f..ccf33b3 100644 --- a/src/mediawiki.rs +++ b/src/mediawiki.rs @@ -1,6 +1,7 @@ use std::error::Error; use std::fs::File; use std::io::Read; +use std::cell::OnceCell; use colored::Colorize; use pandoc::{PandocError, PandocOutput}; @@ -57,8 +58,8 @@ pub struct Mediawiki { api_user: String, api_secret: String, is_dry_run: bool, - login_token: String, - csrf_token: String, + login_token: OnceCell, + csrf_token: OnceCell, plenum_main_page_name: String, client: Client, } @@ -92,13 +93,13 @@ impl Mediawiki { api_user: api_user.to_string(), api_secret: api_secret.to_string(), is_dry_run, - login_token: String::new(), - csrf_token: String::new(), + login_token: OnceCell::new(), + csrf_token: OnceCell::new(), plenum_main_page_name: plenum_main_page_name.to_string(), client: Client::builder().cookie_store(true).build().unwrap(), } } - pub fn get_login_token(&self) -> Result> { + pub fn get_login_token(&self) -> Result<(), Box> { let url = format!("{}/api.php?", self.server_url); let params: Box<[(&str, &str)]> = Box::from( [ @@ -109,20 +110,21 @@ impl Mediawiki { ]); let resp = self.make_request(url, params, ValidRequestTypes::Get)?; let response_deserialized: QueryResponseLogin = serde_json::from_str(&resp)?; - Ok(response_deserialized.query.tokens.logintoken) + self.login_token.set(response_deserialized.query.tokens.logintoken)?; + Ok(()) } pub fn login (&self) -> Result> { let url = format!("{}/api.php?", self.server_url); let params: Box<[(&str, &str)]> = Box::from([ ("lgname", self.api_user.as_str()), ("lgpassword", self.api_secret.as_str()), - ("lgtoken", &self.login_token), + ("lgtoken", self.login_token.get().unwrap()), ("action", "login") ]); let resp: Result> = self.make_request(url, params, ValidRequestTypes::Post); Ok(resp?) } - pub fn get_csrf_token(&self) -> Result> { // HAS TO BE FIXED + pub fn get_csrf_token(&self) -> Result<(), Box> { let url = format!("{}/api.php?", self.server_url); let params: Box<[(&str, &str)]> = Box::from([ @@ -133,7 +135,8 @@ impl Mediawiki { ]); let resp: String = self.make_request(url, params, ValidRequestTypes::Get)?; let response_deserialized: QueryResponseCsrf = serde_json::from_str(&resp)?; - Ok(response_deserialized.query.tokens.csrftoken) + self.csrf_token.set(response_deserialized.query.tokens.csrftoken)?; + Ok(()) } pub fn make_request(&self, url: String, params: Box<[(&str, &str)]>, request_type: ValidRequestTypes) -> Result> { @@ -188,7 +191,7 @@ impl Mediawiki { ("format", "json"), ("title", page_title), // Title of the page to edit. Cannot be used together with pageid. ("text", page_content), // Add this text to the end of the page or section. Overrides text. - ("token", self.csrf_token.as_str()), // A "csrf" token retrieved from action=query&meta=tokens + ("token", self.csrf_token.get().unwrap()), // A "csrf" token retrieved from action=query&meta=tokens ("bot", "true"), // Mark this edit as a bot edit. ]); let request_result = self.make_request(url, params, ValidRequestTypes::Post); @@ -223,8 +226,7 @@ impl Mediawiki { ("page", page_title), ("formatversion", "2"), ]); - let resp: Result> = self.make_request(url, params, ValidRequestTypes::Get); - let resp = resp?; + let resp = self.make_request(url, params, ValidRequestTypes::Get)?; let resp = json!(resp); Ok(resp["parse"]["wikitext"].to_string()) } @@ -237,8 +239,7 @@ impl Mediawiki { ("format", "json"), ("page", page_title), ]); - let resp: Result> = self.make_request(url, params, ValidRequestTypes::Get); - let resp = resp?; + let resp = self.make_request(url, params, ValidRequestTypes::Get)?; todo!() //let response_deserialized = serde_json::from_str(&resp)?; //Ok(response_deserialized["parse"]) @@ -252,7 +253,7 @@ impl Mediawiki { ("title", page_title), // Title of the page to edit. Cannot be used together with pageid. ("section", section_number), // Section identifier. 0 for the top section, new for a new section. Often a positive integer, but can also be non-numeric ("prependtext", text_to_prepend), // Add this text to the end of the page or section. Overrides text. - ("token", self.csrf_token.as_str()), // A "csrf" token retrieved from action=query&meta=tokens + ("token", self.csrf_token.get().unwrap()), // A "csrf" token retrieved from action=query&meta=tokens ("bot", "true"), // Mark this edit as a bot edit. ]); let request_result = self.make_request(url, params, ValidRequestTypes::Post); @@ -261,36 +262,23 @@ impl Mediawiki { } } -pub fn pad_ins_wiki(old_pad_content: String, wiki: &mut Mediawiki) -> Result<(), Box> { +pub fn pad_ins_wiki(old_pad_content: String, wiki: &Mediawiki) -> Result<(), Box> { // Login to Wiki and get required tokens for logging in and writing - let auth_result = wiki.get_login_token()?; - wiki.login_token.clone_from(&auth_result); // Copy the login token to the struct - println!("AUTH Done"); + wiki.get_login_token()?; + eprintln!("AUTH Done"); let login_result = wiki.login()?; - println!("LOGIN Done"); - let csrf_token = wiki.get_csrf_token()?; - println!("CSRF Done"); - wiki.csrf_token.clone_from(&csrf_token); // Copy the csrf token to the struct - println!("---AUTH RESULT:---\n{}\n---LOGIN RESULT:---\n{:?}\n---CSRF RESULT:---\n{}\n-----------", auth_result, login_result, csrf_token); + eprintln!("LOGIN Done"); + wiki.get_csrf_token()?; + eprintln!("CSRF Done"); + eprintln!("---LOGIN RESULT:---\n{:?}\n-----------", login_result); // Convert to mediawiki and make new page let pad_converted = convert_md_to_mediawiki(old_pad_content); - println!("Das kommt ins Wiki: {}", pad_converted); + eprintln!("Das kommt ins Wiki: {}", pad_converted); let page_title = "Page Test 5"; let page_title = format!("{}/{}", wiki.plenum_main_page_name, page_title); // Example: Plenum/13._August_2024 wiki.new_wiki_page(&page_title, &pad_converted)?; - // Textdatei wieder einlesen - - // Passwörter aus Datenbank lesen (ToBeDone) - /* - let plenum_bot_user = String::from("PlenumBot@PlenumBot-PW1"); - let plenum_bot_pw = String::from("**OLD_API_PW_REMOVED**"); - let login_token = login_to_mediawiki(plenum_bot_user.clone(), plenum_bot_pw.clone()) - .expect("Fehler beim Einloggen!"); - println!("plenum_bot_user: {plenum_bot_user}, plenum_bot_pw: {plenum_bot_pw}, login_token: {login_token}") - - */ Ok(()) } @@ -343,6 +331,7 @@ fn create_title (nächster_plenumstermin: String) { // the response contains two \\ characters which break the usual deserialization #[derive(Deserialize)] struct QueryResponseLogin { + #[allow(dead_code)] batchcomplete: String, query: QueryTokensLogin, } @@ -359,6 +348,7 @@ struct TokensLogin { #[derive(Deserialize)] struct QueryResponseCsrf { + #[allow(dead_code)] batchcomplete: bool, query: crate::mediawiki::QueryTokensCsrf, } @@ -371,4 +361,4 @@ struct QueryTokensCsrf { #[derive(Deserialize)] struct TokensCsrf { csrftoken: String, -} \ No newline at end of file +}