diff --git a/src/main.rs b/src/main.rs index 3e92654..cee6b2b 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 wiki = Mediawiki::new( + let mut 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, &wiki)?; + do_cleanup(999, &today, &config, &hedgedoc, &email, &mut 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, &wiki)?; + action.get()(delta, &plenum_day, &config, &hedgedoc, &email, &mut 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: &Mediawiki, + _wiki: &mut 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: &Mediawiki, + _wiki: &mut 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: &Mediawiki, + wiki: &mut Mediawiki, ) -> Result<(), Box> { NYI!("trace/verbose annotations"); let (current_pad_id, pad_content, toc, n_topics) = get_pad_info(config, hedgedoc); @@ -476,6 +476,7 @@ fn do_protocol( ); let _message_id = send_email(&subject, &body, email, config)?; NYI!("convert to mediawiki"); + mediawiki::pad_ins_wiki(pad_content, wiki)?; NYI!("add to wiki"); config.set("state-name", &ProgramState::Logged.to_string()).ok(); } else { @@ -489,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: &Mediawiki, + _wiki: &mut Mediawiki, ) -> Result<(), Box> { NYI!("trace/verbose annotations"); config.delete("state-toc"); @@ -508,7 +509,7 @@ type TransitionFunction = fn( config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, - wiki: &Mediawiki, + wiki: &mut Mediawiki, ) -> Result<(), Box>; #[rustfmt::skip] @@ -555,14 +556,14 @@ impl Display for ST { } fn nop( - _: i64, _: &NaiveDate, _: &KV, _: &HedgeDoc, _: &SimpleEmail, _: &Mediawiki, + _: i64, _: &NaiveDate, _: &KV, _: &HedgeDoc, _: &SimpleEmail, _: &mut Mediawiki, ) -> Result<(), Box> { Ok(()) } fn do_clean_announcement( ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, - wiki: &Mediawiki, + wiki: &mut Mediawiki, ) -> Result<(), Box> { do_cleanup(ttp, plenum_day, config, hedgedoc, email, wiki)?; do_announcement(ttp, plenum_day, config, hedgedoc, email, wiki) @@ -570,7 +571,7 @@ fn do_clean_announcement( fn do_clean_reminder( ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, - wiki: &Mediawiki, + wiki: &mut 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 1de7a41..82b067f 100644 --- a/src/mediawiki.rs +++ b/src/mediawiki.rs @@ -6,6 +6,7 @@ use colored::Colorize; use pandoc::{PandocError, PandocOutput}; use reqwest::blocking::Client; use serde::Deserialize; +use serde_json::json; use crate::config_spec::{CfgField, CfgGroup}; @@ -74,7 +75,7 @@ impl std::fmt::Debug for Mediawiki { } } -pub enum RequestType { +pub enum ValidRequestTypes { Get, Post, PostForEditing @@ -106,7 +107,7 @@ impl Mediawiki { ("type", "login"), ("action", "query") ]); - let resp = self.make_request(url, params, RequestType::Get).unwrap(); + let resp = self.make_request(url, params, ValidRequestTypes::Get)?; let response_deserialized: QueryResponseLogin = serde_json::from_str(&resp)?; Ok(response_deserialized.query.tokens.logintoken) } @@ -118,8 +119,8 @@ impl Mediawiki { ("lgtoken", &self.login_token), ("action", "login") ]); - let resp: Result> = self.make_request(url, params, RequestType::Post); - Ok(resp.unwrap()) + let resp: Result> = self.make_request(url, params, ValidRequestTypes::Post); + Ok(resp?) } pub fn get_csrf_token(&self) -> Result> { // HAS TO BE FIXED let url = @@ -130,16 +131,15 @@ impl Mediawiki { ("formatversion", "2"), ("action", "query") ]); - let resp: Result> = self.make_request(url, params, RequestType::Get); - let resp = resp.unwrap(); + 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) } - pub fn make_request(&self, url: String, params: Box<[(&str, &str)]>, request_type: RequestType) -> Result> { + pub fn make_request(&self, url: String, params: Box<[(&str, &str)]>, request_type: ValidRequestTypes) -> Result> { let resp: Result> = match match request_type { - RequestType::Get => { + ValidRequestTypes::Get => { self .client .get(url) @@ -147,7 +147,7 @@ impl Mediawiki { .query(¶ms) .send() } - RequestType::Post | RequestType::PostForEditing => { + ValidRequestTypes::Post | ValidRequestTypes::PostForEditing => { self .client .post(url) @@ -160,8 +160,8 @@ impl Mediawiki { Ok(response) => { if response.status().is_success() { match request_type { - RequestType::PostForEditing => Ok(response.text().unwrap()), - _ => Ok(response.text().unwrap()) + ValidRequestTypes::PostForEditing => Ok(response.text()?), + _ => Ok(response.text()?) } } else { @@ -191,7 +191,7 @@ impl Mediawiki { ("token", self.csrf_token.as_str()), // 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, RequestType::Post); + let request_result = self.make_request(url, params, ValidRequestTypes::Post); self.update_plenum_page(page_title)?; @@ -223,10 +223,10 @@ impl Mediawiki { ("page", page_title), ("formatversion", "2"), ]); - let resp: Result> = self.make_request(url, params, RequestType::Get); + let resp: Result> = self.make_request(url, params, ValidRequestTypes::Get); let resp = resp?; - let response_deserialized: ParseResponse = serde_json::from_str(&resp)?; - Ok(response_deserialized.parse.wikitext) + let resp = json!(resp); + Ok(resp["parse"]["wikitext"].to_string()) } pub fn get_page_section_title (&self, page_title: &str, section_number: &str) -> Result> { let url = @@ -237,7 +237,7 @@ impl Mediawiki { ("format", "json"), ("page", page_title), ]); - let resp: Result> = self.make_request(url, params, RequestType::Get); + let resp: Result> = self.make_request(url, params, ValidRequestTypes::Get); let resp = resp?; todo!() //let response_deserialized = serde_json::from_str(&resp)?; @@ -255,80 +255,22 @@ impl Mediawiki { ("token", self.csrf_token.as_str()), // 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, RequestType::Post); + let request_result = self.make_request(url, params, ValidRequestTypes::Post); request_result } } -#[derive(Deserialize)] -struct QueryResponseLogin { - batchcomplete: String, - query: QueryTokensLogin, -} - -#[derive(Deserialize)] -struct QueryTokensLogin { - tokens: TokensLogin, -} - -#[derive(Deserialize)] -struct TokensLogin { - logintoken: String, -} - -#[derive(Deserialize)] -struct QueryResponseCsrf { - batchcomplete: bool, - query: crate::mediawiki::QueryTokensCsrf, -} - -#[derive(Deserialize)] -struct QueryTokensCsrf { - tokens: crate::mediawiki::TokensCsrf, -} - -#[derive(Deserialize)] -struct TokensCsrf { - csrftoken: String, -} -// For get_page_content: -#[derive(Deserialize)] -struct ParseResponse { - parse: ParseContent, -} - -#[derive(Deserialize)] -struct ParseContent { - wikitext: String, -} -// For get_page_section: -/* -#[derive(Deserialize)] -struct ParseSectionResponse { - parse: ParseSectionContent, -} -#[derive(Deserialize)] -struct ParseSectionContent { - sections: , -} - - */ - pub fn pad_ins_wiki(old_pad_content: String, wiki: &mut 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); - println!("AUTH Success"); + wiki.login_token.clone_from(&auth_result); // Copy the login token to the struct + println!("AUTH Done"); let login_result = wiki.login()?; - println!("LOGIN Success"); - let csrf_token = wiki.get_csrf_token(); - let csrf_token = csrf_token.unwrap_or_else(|e| { - println!("Error while trying to get csrf: {:?}", e); - String::new() - }); - println!("CSRF Success"); - wiki.csrf_token.clone_from(&csrf_token); + 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); // Convert to mediawiki and make new page @@ -338,7 +280,6 @@ pub fn pad_ins_wiki(old_pad_content: String, wiki: &mut Mediawiki) -> Result<(), 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) @@ -397,3 +338,37 @@ fn create_title (nächster_plenumstermin: String) { } */ + +// This has to be defined that way, because both in the login and csrf token, +// the response contains two \\ characters which break the usual deserialization +#[derive(Deserialize)] +struct QueryResponseLogin { + batchcomplete: String, + query: QueryTokensLogin, +} + +#[derive(Deserialize)] +struct QueryTokensLogin { + tokens: TokensLogin, +} + +#[derive(Deserialize)] +struct TokensLogin { + logintoken: String, +} + +#[derive(Deserialize)] +struct QueryResponseCsrf { + batchcomplete: bool, + query: crate::mediawiki::QueryTokensCsrf, +} + +#[derive(Deserialize)] +struct QueryTokensCsrf { + tokens: crate::mediawiki::TokensCsrf, +} + +#[derive(Deserialize)] +struct TokensCsrf { + csrftoken: String, +} \ No newline at end of file