mediawiki: use OnceCell instead of mut
login_token and csrf_token are internally mutable now
This commit is contained in:
parent
12450ce5a3
commit
3608838949
22
src/main.rs
22
src/main.rs
|
@ -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 mut wiki = Mediawiki::new(
|
let 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, &mut wiki)?;
|
do_cleanup(999, &today, &config, &hedgedoc, &email, &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, &mut wiki)?;
|
action.get()(delta, &plenum_day, &config, &hedgedoc, &email, &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: &mut Mediawiki,
|
_wiki: &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: &mut Mediawiki,
|
_wiki: &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: &mut Mediawiki,
|
wiki: &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);
|
||||||
|
@ -490,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: &mut Mediawiki,
|
_wiki: &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");
|
||||||
|
@ -509,7 +509,7 @@ type TransitionFunction = fn(
|
||||||
config: &KV,
|
config: &KV,
|
||||||
hedgedoc: &HedgeDoc,
|
hedgedoc: &HedgeDoc,
|
||||||
email: &SimpleEmail,
|
email: &SimpleEmail,
|
||||||
wiki: &mut Mediawiki,
|
wiki: &Mediawiki,
|
||||||
) -> Result<(), Box<dyn Error>>;
|
) -> Result<(), Box<dyn Error>>;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -556,14 +556,14 @@ impl Display for ST {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nop(
|
fn nop(
|
||||||
_: i64, _: &NaiveDate, _: &KV, _: &HedgeDoc, _: &SimpleEmail, _: &mut Mediawiki,
|
_: i64, _: &NaiveDate, _: &KV, _: &HedgeDoc, _: &SimpleEmail, _: &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: &mut Mediawiki,
|
wiki: &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)
|
||||||
|
@ -571,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: &mut Mediawiki,
|
wiki: &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)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::cell::OnceCell;
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use pandoc::{PandocError, PandocOutput};
|
use pandoc::{PandocError, PandocOutput};
|
||||||
|
@ -57,8 +58,8 @@ pub struct Mediawiki {
|
||||||
api_user: String,
|
api_user: String,
|
||||||
api_secret: String,
|
api_secret: String,
|
||||||
is_dry_run: bool,
|
is_dry_run: bool,
|
||||||
login_token: String,
|
login_token: OnceCell<String>,
|
||||||
csrf_token: String,
|
csrf_token: OnceCell<String>,
|
||||||
plenum_main_page_name: String,
|
plenum_main_page_name: String,
|
||||||
client: Client,
|
client: Client,
|
||||||
}
|
}
|
||||||
|
@ -92,13 +93,13 @@ impl Mediawiki {
|
||||||
api_user: api_user.to_string(),
|
api_user: api_user.to_string(),
|
||||||
api_secret: api_secret.to_string(),
|
api_secret: api_secret.to_string(),
|
||||||
is_dry_run,
|
is_dry_run,
|
||||||
login_token: String::new(),
|
login_token: OnceCell::new(),
|
||||||
csrf_token: String::new(),
|
csrf_token: OnceCell::new(),
|
||||||
plenum_main_page_name: plenum_main_page_name.to_string(),
|
plenum_main_page_name: plenum_main_page_name.to_string(),
|
||||||
client: Client::builder().cookie_store(true).build().unwrap(),
|
client: Client::builder().cookie_store(true).build().unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get_login_token(&self) -> Result<String, Box<dyn Error>> {
|
pub fn get_login_token(&self) -> Result<(), Box<dyn Error>> {
|
||||||
let url =
|
let url =
|
||||||
format!("{}/api.php?", self.server_url);
|
format!("{}/api.php?", self.server_url);
|
||||||
let params: Box<[(&str, &str)]> = Box::from( [
|
let params: Box<[(&str, &str)]> = Box::from( [
|
||||||
|
@ -109,20 +110,21 @@ impl Mediawiki {
|
||||||
]);
|
]);
|
||||||
let resp = self.make_request(url, params, ValidRequestTypes::Get)?;
|
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)
|
self.login_token.set(response_deserialized.query.tokens.logintoken)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn login (&self) -> Result<String, Box<dyn Error>> {
|
pub fn login (&self) -> Result<String, Box<dyn Error>> {
|
||||||
let url = format!("{}/api.php?", self.server_url);
|
let url = format!("{}/api.php?", self.server_url);
|
||||||
let params: Box<[(&str, &str)]> = Box::from([
|
let params: Box<[(&str, &str)]> = Box::from([
|
||||||
("lgname", self.api_user.as_str()),
|
("lgname", self.api_user.as_str()),
|
||||||
("lgpassword", self.api_secret.as_str()),
|
("lgpassword", self.api_secret.as_str()),
|
||||||
("lgtoken", &self.login_token),
|
("lgtoken", self.login_token.get().unwrap()),
|
||||||
("action", "login")
|
("action", "login")
|
||||||
]);
|
]);
|
||||||
let resp: Result<String, Box<dyn Error>> = self.make_request(url, params, ValidRequestTypes::Post);
|
let resp: Result<String, Box<dyn Error>> = self.make_request(url, params, ValidRequestTypes::Post);
|
||||||
Ok(resp?)
|
Ok(resp?)
|
||||||
}
|
}
|
||||||
pub fn get_csrf_token(&self) -> Result<String, Box<dyn Error>> { // HAS TO BE FIXED
|
pub fn get_csrf_token(&self) -> Result<(), Box<dyn Error>> {
|
||||||
let url =
|
let url =
|
||||||
format!("{}/api.php?", self.server_url);
|
format!("{}/api.php?", self.server_url);
|
||||||
let params: Box<[(&str, &str)]> = Box::from([
|
let params: Box<[(&str, &str)]> = Box::from([
|
||||||
|
@ -133,7 +135,8 @@ impl Mediawiki {
|
||||||
]);
|
]);
|
||||||
let resp: String = self.make_request(url, params, ValidRequestTypes::Get)?;
|
let resp: String = self.make_request(url, params, ValidRequestTypes::Get)?;
|
||||||
let response_deserialized: QueryResponseCsrf = serde_json::from_str(&resp)?;
|
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<String, Box<dyn Error>> {
|
pub fn make_request(&self, url: String, params: Box<[(&str, &str)]>, request_type: ValidRequestTypes) -> Result<String, Box<dyn Error>> {
|
||||||
|
@ -188,7 +191,7 @@ impl Mediawiki {
|
||||||
("format", "json"),
|
("format", "json"),
|
||||||
("title", page_title), // Title of the page to edit. Cannot be used together with pageid.
|
("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.
|
("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.
|
("bot", "true"), // Mark this edit as a bot edit.
|
||||||
]);
|
]);
|
||||||
let request_result = self.make_request(url, params, ValidRequestTypes::Post);
|
let request_result = self.make_request(url, params, ValidRequestTypes::Post);
|
||||||
|
@ -223,8 +226,7 @@ impl Mediawiki {
|
||||||
("page", page_title),
|
("page", page_title),
|
||||||
("formatversion", "2"),
|
("formatversion", "2"),
|
||||||
]);
|
]);
|
||||||
let resp: Result<String, Box<dyn Error>> = self.make_request(url, params, ValidRequestTypes::Get);
|
let resp = self.make_request(url, params, ValidRequestTypes::Get)?;
|
||||||
let resp = resp?;
|
|
||||||
let resp = json!(resp);
|
let resp = json!(resp);
|
||||||
Ok(resp["parse"]["wikitext"].to_string())
|
Ok(resp["parse"]["wikitext"].to_string())
|
||||||
}
|
}
|
||||||
|
@ -237,8 +239,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, ValidRequestTypes::Get);
|
let resp = self.make_request(url, params, ValidRequestTypes::Get)?;
|
||||||
let resp = resp?;
|
|
||||||
todo!()
|
todo!()
|
||||||
//let response_deserialized = serde_json::from_str(&resp)?;
|
//let response_deserialized = serde_json::from_str(&resp)?;
|
||||||
//Ok(response_deserialized["parse"])
|
//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.
|
("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
|
("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.
|
("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.
|
("bot", "true"), // Mark this edit as a bot edit.
|
||||||
]);
|
]);
|
||||||
let request_result = self.make_request(url, params, ValidRequestTypes::Post);
|
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<dyn Error>> {
|
pub fn pad_ins_wiki(old_pad_content: String, wiki: &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()?;
|
wiki.get_login_token()?;
|
||||||
wiki.login_token.clone_from(&auth_result); // Copy the login token to the struct
|
eprintln!("AUTH Done");
|
||||||
println!("AUTH Done");
|
|
||||||
let login_result = wiki.login()?;
|
let login_result = wiki.login()?;
|
||||||
println!("LOGIN Done");
|
eprintln!("LOGIN Done");
|
||||||
let csrf_token = wiki.get_csrf_token()?;
|
wiki.get_csrf_token()?;
|
||||||
println!("CSRF Done");
|
eprintln!("CSRF Done");
|
||||||
wiki.csrf_token.clone_from(&csrf_token); // Copy the csrf token to the struct
|
eprintln!("---LOGIN RESULT:---\n{:?}\n-----------", login_result);
|
||||||
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
|
||||||
let pad_converted = convert_md_to_mediawiki(old_pad_content);
|
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 = "Page Test 5";
|
||||||
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
|
|
||||||
|
|
||||||
// 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,6 +331,7 @@ fn create_title (nächster_plenumstermin: String) {
|
||||||
// the response contains two \\ characters which break the usual deserialization
|
// the response contains two \\ characters which break the usual deserialization
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct QueryResponseLogin {
|
struct QueryResponseLogin {
|
||||||
|
#[allow(dead_code)]
|
||||||
batchcomplete: String,
|
batchcomplete: String,
|
||||||
query: QueryTokensLogin,
|
query: QueryTokensLogin,
|
||||||
}
|
}
|
||||||
|
@ -359,6 +348,7 @@ struct TokensLogin {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct QueryResponseCsrf {
|
struct QueryResponseCsrf {
|
||||||
|
#[allow(dead_code)]
|
||||||
batchcomplete: bool,
|
batchcomplete: bool,
|
||||||
query: crate::mediawiki::QueryTokensCsrf,
|
query: crate::mediawiki::QueryTokensCsrf,
|
||||||
}
|
}
|
||||||
|
@ -371,4 +361,4 @@ struct QueryTokensCsrf {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct TokensCsrf {
|
struct TokensCsrf {
|
||||||
csrftoken: String,
|
csrftoken: String,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue