mediawiki mutable in main.rs, less unwrap in mediawiki.rs

This commit is contained in:
murmeldin 2024-08-25 18:15:03 +02:00
parent 2da4a149c9
commit 12450ce5a3
2 changed files with 69 additions and 93 deletions

View file

@ -164,7 +164,7 @@ fn main() -> Result<(), Box<dyn Error>> {
config.get("email-in-reply-to").ok(), config.get("email-in-reply-to").ok(),
); );
trace_var_!(email); trace_var_!(email);
let wiki = Mediawiki::new( let mut wiki = Mediawiki::new(
&config["wiki-server-url"], &config["wiki-server-url"],
&config["wiki-http-user"], &config["wiki-http-user"],
&config["wiki-http-password"], &config["wiki-http-password"],
@ -191,7 +191,7 @@ fn main() -> Result<(), Box<dyn Error>> {
if !matches!(last_state, ProgramState::Normal) { if !matches!(last_state, ProgramState::Normal) {
eprintln!("WARNING: last run was a long time ago, resetting state."); eprintln!("WARNING: last run was a long time ago, resetting state.");
last_state = ProgramState::Normal; 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 // reset will have cleared in-reply-to if it existed
let (base, from, to, _) = email.into_parts(); let (base, from, to, _) = email.into_parts();
email = SimpleEmail::from_parts(base, from, to, config.get("email-in-reply-to").ok()); email = SimpleEmail::from_parts(base, from, to, config.get("email-in-reply-to").ok());
@ -241,7 +241,7 @@ fn main() -> Result<(), Box<dyn Error>> {
let action: &ST = &TRANSITION_LUT[last_state as usize][intended_state as usize]; let action: &ST = &TRANSITION_LUT[last_state as usize][intended_state as usize];
verboseln!("Notewendige Aktionen: {}", action.to_string().cyan()); verboseln!("Notewendige Aktionen: {}", action.to_string().cyan());
// run action, which is responsible for updating the state as needed // 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 // shutdown
config.set("state-last-run", &today.to_string())?; 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( fn do_announcement(
ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail,
_wiki: &Mediawiki, _wiki: &mut Mediawiki,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
NYI!("trace/verbose annotations"); NYI!("trace/verbose annotations");
// fetch current pad contents & summarize // fetch current pad contents & summarize
@ -405,7 +405,7 @@ fn do_announcement(
fn do_reminder( fn do_reminder(
ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail,
_wiki: &Mediawiki, _wiki: &mut Mediawiki,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
NYI!("trace/verbose annotations"); NYI!("trace/verbose annotations");
// fetch current pad contents & summarize // fetch current pad contents & summarize
@ -459,7 +459,7 @@ fn do_reminder(
#[allow(unused_variables)] #[allow(unused_variables)]
fn do_protocol( fn do_protocol(
ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail,
wiki: &Mediawiki, wiki: &mut Mediawiki,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
NYI!("trace/verbose annotations"); NYI!("trace/verbose annotations");
let (current_pad_id, pad_content, toc, n_topics) = get_pad_info(config, hedgedoc); 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)?; let _message_id = send_email(&subject, &body, email, config)?;
NYI!("convert to mediawiki"); NYI!("convert to mediawiki");
mediawiki::pad_ins_wiki(pad_content, wiki)?;
NYI!("add to wiki"); NYI!("add to wiki");
config.set("state-name", &ProgramState::Logged.to_string()).ok(); config.set("state-name", &ProgramState::Logged.to_string()).ok();
} else { } else {
@ -489,7 +490,7 @@ fn do_protocol(
#[allow(unused_must_use)] #[allow(unused_must_use)]
fn do_cleanup( fn do_cleanup(
_ttp: i64, _plenum_day: &NaiveDate, config: &KV, _hedgedoc: &HedgeDoc, _email: &SimpleEmail, _ttp: i64, _plenum_day: &NaiveDate, config: &KV, _hedgedoc: &HedgeDoc, _email: &SimpleEmail,
_wiki: &Mediawiki, _wiki: &mut Mediawiki,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
NYI!("trace/verbose annotations"); NYI!("trace/verbose annotations");
config.delete("state-toc"); config.delete("state-toc");
@ -508,7 +509,7 @@ type TransitionFunction = fn(
config: &KV, config: &KV,
hedgedoc: &HedgeDoc, hedgedoc: &HedgeDoc,
email: &SimpleEmail, email: &SimpleEmail,
wiki: &Mediawiki, wiki: &mut Mediawiki,
) -> Result<(), Box<dyn Error>>; ) -> Result<(), Box<dyn Error>>;
#[rustfmt::skip] #[rustfmt::skip]
@ -555,14 +556,14 @@ impl Display for ST {
} }
fn nop( fn nop(
_: i64, _: &NaiveDate, _: &KV, _: &HedgeDoc, _: &SimpleEmail, _: &Mediawiki, _: i64, _: &NaiveDate, _: &KV, _: &HedgeDoc, _: &SimpleEmail, _: &mut Mediawiki,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())
} }
fn do_clean_announcement( fn do_clean_announcement(
ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail,
wiki: &Mediawiki, wiki: &mut Mediawiki,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
do_cleanup(ttp, plenum_day, config, hedgedoc, email, wiki)?; do_cleanup(ttp, plenum_day, config, hedgedoc, email, wiki)?;
do_announcement(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( fn do_clean_reminder(
ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail, ttp: i64, plenum_day: &NaiveDate, config: &KV, hedgedoc: &HedgeDoc, email: &SimpleEmail,
wiki: &Mediawiki, wiki: &mut Mediawiki,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
do_cleanup(ttp, plenum_day, config, hedgedoc, email, wiki)?; do_cleanup(ttp, plenum_day, config, hedgedoc, email, wiki)?;
do_reminder(ttp, plenum_day, config, hedgedoc, email, wiki) do_reminder(ttp, plenum_day, config, hedgedoc, email, wiki)

View file

@ -6,6 +6,7 @@ use colored::Colorize;
use pandoc::{PandocError, PandocOutput}; use pandoc::{PandocError, PandocOutput};
use reqwest::blocking::Client; use reqwest::blocking::Client;
use serde::Deserialize; use serde::Deserialize;
use serde_json::json;
use crate::config_spec::{CfgField, CfgGroup}; use crate::config_spec::{CfgField, CfgGroup};
@ -74,7 +75,7 @@ impl std::fmt::Debug for Mediawiki {
} }
} }
pub enum RequestType { pub enum ValidRequestTypes {
Get, Get,
Post, Post,
PostForEditing PostForEditing
@ -106,7 +107,7 @@ impl Mediawiki {
("type", "login"), ("type", "login"),
("action", "query") ("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)?; let response_deserialized: QueryResponseLogin = serde_json::from_str(&resp)?;
Ok(response_deserialized.query.tokens.logintoken) Ok(response_deserialized.query.tokens.logintoken)
} }
@ -118,8 +119,8 @@ impl Mediawiki {
("lgtoken", &self.login_token), ("lgtoken", &self.login_token),
("action", "login") ("action", "login")
]); ]);
let resp: Result<String, Box<dyn Error>> = self.make_request(url, params, RequestType::Post); let resp: Result<String, Box<dyn Error>> = self.make_request(url, params, ValidRequestTypes::Post);
Ok(resp.unwrap()) Ok(resp?)
} }
pub fn get_csrf_token(&self) -> Result<String, Box<dyn Error>> { // HAS TO BE FIXED pub fn get_csrf_token(&self) -> Result<String, Box<dyn Error>> { // HAS TO BE FIXED
let url = let url =
@ -130,16 +131,15 @@ impl Mediawiki {
("formatversion", "2"), ("formatversion", "2"),
("action", "query") ("action", "query")
]); ]);
let resp: Result<String, Box<dyn Error>> = self.make_request(url, params, RequestType::Get); let resp: String = self.make_request(url, params, ValidRequestTypes::Get)?;
let resp = resp.unwrap();
let response_deserialized: QueryResponseCsrf = serde_json::from_str(&resp)?; let response_deserialized: QueryResponseCsrf = serde_json::from_str(&resp)?;
Ok(response_deserialized.query.tokens.csrftoken) Ok(response_deserialized.query.tokens.csrftoken)
} }
pub fn make_request(&self, url: String, params: Box<[(&str, &str)]>, request_type: RequestType) -> Result<String, Box<dyn Error>> { pub fn make_request(&self, url: String, params: Box<[(&str, &str)]>, request_type: ValidRequestTypes) -> Result<String, Box<dyn Error>> {
let resp: Result<String, Box<dyn Error>> = match let resp: Result<String, Box<dyn Error>> = match
match request_type { match request_type {
RequestType::Get => { ValidRequestTypes::Get => {
self self
.client .client
.get(url) .get(url)
@ -147,7 +147,7 @@ impl Mediawiki {
.query(&params) .query(&params)
.send() .send()
} }
RequestType::Post | RequestType::PostForEditing => { ValidRequestTypes::Post | ValidRequestTypes::PostForEditing => {
self self
.client .client
.post(url) .post(url)
@ -160,8 +160,8 @@ impl Mediawiki {
Ok(response) => { Ok(response) => {
if response.status().is_success() { if response.status().is_success() {
match request_type { match request_type {
RequestType::PostForEditing => Ok(response.text().unwrap()), ValidRequestTypes::PostForEditing => Ok(response.text()?),
_ => Ok(response.text().unwrap()) _ => Ok(response.text()?)
} }
} }
else { else {
@ -191,7 +191,7 @@ impl Mediawiki {
("token", self.csrf_token.as_str()), // A "csrf" token retrieved from action=query&meta=tokens ("token", self.csrf_token.as_str()), // A "csrf" token retrieved from action=query&meta=tokens
("bot", "true"), // Mark this edit as a bot edit. ("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)?; self.update_plenum_page(page_title)?;
@ -223,10 +223,10 @@ impl Mediawiki {
("page", page_title), ("page", page_title),
("formatversion", "2"), ("formatversion", "2"),
]); ]);
let resp: Result<String, Box<dyn Error>> = self.make_request(url, params, RequestType::Get); let resp: Result<String, Box<dyn Error>> = self.make_request(url, params, ValidRequestTypes::Get);
let resp = resp?; let resp = resp?;
let response_deserialized: ParseResponse = serde_json::from_str(&resp)?; let resp = json!(resp);
Ok(response_deserialized.parse.wikitext) Ok(resp["parse"]["wikitext"].to_string())
} }
pub fn get_page_section_title (&self, page_title: &str, section_number: &str) -> Result<String, Box<dyn Error>> { pub fn get_page_section_title (&self, page_title: &str, section_number: &str) -> Result<String, Box<dyn Error>> {
let url = let url =
@ -237,7 +237,7 @@ impl Mediawiki {
("format", "json"), ("format", "json"),
("page", page_title), ("page", page_title),
]); ]);
let resp: Result<String, Box<dyn Error>> = self.make_request(url, params, RequestType::Get); let resp: Result<String, Box<dyn Error>> = self.make_request(url, params, ValidRequestTypes::Get);
let resp = resp?; let resp = resp?;
todo!() todo!()
//let response_deserialized = serde_json::from_str(&resp)?; //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 ("token", self.csrf_token.as_str()), // A "csrf" token retrieved from action=query&meta=tokens
("bot", "true"), // Mark this edit as a bot edit. ("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 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<dyn Error>> { pub fn pad_ins_wiki(old_pad_content: String, wiki: &mut Mediawiki) -> Result<(), Box<dyn Error>> {
// Login to Wiki and get required tokens for logging in and writing // Login to Wiki and get required tokens for logging in and writing
let auth_result = wiki.get_login_token()?; let auth_result = wiki.get_login_token()?;
wiki.login_token.clone_from(&auth_result); wiki.login_token.clone_from(&auth_result); // Copy the login token to the struct
println!("AUTH Success"); println!("AUTH Done");
let login_result = wiki.login()?; let login_result = wiki.login()?;
println!("LOGIN Success"); println!("LOGIN Done");
let csrf_token = wiki.get_csrf_token(); let csrf_token = wiki.get_csrf_token()?;
let csrf_token = csrf_token.unwrap_or_else(|e| { println!("CSRF Done");
println!("Error while trying to get csrf: {:?}", e); wiki.csrf_token.clone_from(&csrf_token); // Copy the csrf token to the struct
String::new()
});
println!("CSRF Success");
wiki.csrf_token.clone_from(&csrf_token);
println!("---AUTH RESULT:---\n{}\n---LOGIN RESULT:---\n{:?}\n---CSRF RESULT:---\n{}\n-----------", auth_result, login_result, csrf_token); 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 // 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 let page_title = format!("{}/{}", wiki.plenum_main_page_name, page_title); // Example: Plenum/13._August_2024
wiki.new_wiki_page(&page_title, &pad_converted)?; wiki.new_wiki_page(&page_title, &pad_converted)?;
// Textdatei wieder einlesen // Textdatei wieder einlesen
// Passwörter aus Datenbank lesen (ToBeDone) // 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,
}