Clean up key/value store, add convenience wrapper.
This commit is contained in:
		
							parent
							
								
									08878169bc
								
							
						
					
					
						commit
						19be226f11
					
				
					 2 changed files with 116 additions and 79 deletions
				
			
		
							
								
								
									
										139
									
								
								src/key_value.rs
									
										
									
									
									
								
							
							
						
						
									
										139
									
								
								src/key_value.rs
									
										
									
									
									
								
							| 
						 | 
					@ -1,12 +1,23 @@
 | 
				
			||||||
use rusqlite::{params, Connection, Result};
 | 
					use rusqlite::{Connection, Result, params};
 | 
				
			||||||
// use std::collections::HashMap;
 | 
					use std::ops::Index;
 | 
				
			||||||
 | 
					use std::cell::Cell;
 | 
				
			||||||
 | 
					use std::collections::HashSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Simple SQLite-backed key/value store.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// All failing writes will log a message, any errors will set `has_errors`.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// There's `Index` support for convenience (`&kvstore["foo"]`),
 | 
				
			||||||
 | 
					/// but **it will leak data.**  
 | 
				
			||||||
 | 
					/// (That's perfectly fine when used for getting data once for the duration of
 | 
				
			||||||
 | 
					/// the program, just use `.get()` for stuff that changes.)
 | 
				
			||||||
pub struct KeyValueStore {
 | 
					pub struct KeyValueStore {
 | 
				
			||||||
    conn: Connection,
 | 
					    conn: Connection,
 | 
				
			||||||
 | 
					    has_write_errors: Cell<bool>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl KeyValueStore {
 | 
					impl KeyValueStore {
 | 
				
			||||||
    // Initialize the database and create the table if it doesn't exist
 | 
					    /// Open or create a DB with a `kv_store` table storing all tuples.
 | 
				
			||||||
    pub fn new(db_path: &str) -> Result<Self> {
 | 
					    pub fn new(db_path: &str) -> Result<Self> {
 | 
				
			||||||
        let conn = Connection::open(db_path)?;
 | 
					        let conn = Connection::open(db_path)?;
 | 
				
			||||||
        conn.execute(
 | 
					        conn.execute(
 | 
				
			||||||
| 
						 | 
					@ -16,73 +27,95 @@ impl KeyValueStore {
 | 
				
			||||||
              )",
 | 
					              )",
 | 
				
			||||||
            [],
 | 
					            [],
 | 
				
			||||||
        )?;
 | 
					        )?;
 | 
				
			||||||
        Ok(KeyValueStore { conn })
 | 
					        Ok(Self { conn, has_write_errors: Cell::new(false), })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Insert or update a key-value pair
 | 
					    /// Report if any write errors occurred.
 | 
				
			||||||
    pub fn set(&self, key: &str, value: &str) -> Result<()> {
 | 
					    pub fn has_errors(&self) -> bool {
 | 
				
			||||||
        self.conn.execute(
 | 
					        self.has_write_errors.get()
 | 
				
			||||||
            "INSERT INTO kv_store (key, value) VALUES (?1, ?2)
 | 
					 | 
				
			||||||
             ON CONFLICT(key) DO UPDATE SET value = excluded.value",
 | 
					 | 
				
			||||||
            params![key, value],
 | 
					 | 
				
			||||||
        )?;
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn default(&self, key: &str, value: &str) {
 | 
					    /// Get value at `key`.  (Use `.unwrap_or(default)` & friends to work with the Result.)
 | 
				
			||||||
        self.conn.execute(
 | 
					    pub fn get(&self, key: &str) -> Result<String> {
 | 
				
			||||||
            "INSERT INTO kv_store (key, value) VALUES (?1, ?2)
 | 
					 | 
				
			||||||
             ON CONFLICT(key) DO NOTHING",
 | 
					 | 
				
			||||||
            params![key, value],
 | 
					 | 
				
			||||||
        ).ok();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Retrieve a value by key
 | 
					 | 
				
			||||||
    pub fn get(&self, key: &str) -> Result<Option<String>> {
 | 
					 | 
				
			||||||
        let mut stmt = self.conn.prepare("SELECT value FROM kv_store WHERE key = ?1")?;
 | 
					        let mut stmt = self.conn.prepare("SELECT value FROM kv_store WHERE key = ?1")?;
 | 
				
			||||||
        let mut rows = stmt.query(params![key])?;
 | 
					        let mut rows = stmt.query(params![key])?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some(row) = rows.next()? {
 | 
					        if let Some(row) = rows.next()? {
 | 
				
			||||||
            let value: String = row.get(0)?;
 | 
					            let result = row.get(0)?;
 | 
				
			||||||
            Ok(Some(value))
 | 
					            Ok(result)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Ok(None)
 | 
					            Err(rusqlite::Error::QueryReturnedNoRows)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Delete a key-value pair
 | 
					    /// If `key` is absent from the DB, write `key`/`value` pair (else leave unchanged).
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Will panic on error. (The idea is to call this a bunch of times at boot,
 | 
				
			||||||
 | 
					    /// to populate the DB if missing / newly created, and not use it after.)
 | 
				
			||||||
 | 
					    pub fn default(&self, key: &str, value: &str) {
 | 
				
			||||||
 | 
					        self.conn.execute(
 | 
				
			||||||
 | 
					            "INSERT INTO kv_store (key, value) VALUES (?1, ?2)
 | 
				
			||||||
 | 
					                 ON CONFLICT(key) DO NOTHING",
 | 
				
			||||||
 | 
					            params![key, value],
 | 
				
			||||||
 | 
					        ).expect(&format!("Failed to write default at key: {}", key));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Write a `key`/`value` pair to the DB.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Errors log the failed write and set `has_errors`.
 | 
				
			||||||
 | 
					    pub fn set(&self, key: &str, value: &str) -> Result<()> {
 | 
				
			||||||
 | 
					        match self.conn.execute(
 | 
				
			||||||
 | 
					            "INSERT INTO kv_store (key, value) VALUES (?1, ?2)
 | 
				
			||||||
 | 
					             ON CONFLICT(key) DO UPDATE SET value = excluded.value",
 | 
				
			||||||
 | 
					            params![key, value],
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            Ok(_) => Ok(()),
 | 
				
			||||||
 | 
					            Err(e) => {
 | 
				
			||||||
 | 
					                eprintln!("Failed DB write: ({}, {})", key, value);
 | 
				
			||||||
 | 
					                self.has_write_errors.set(true);
 | 
				
			||||||
 | 
					                Err(e)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Delete the key-value pair associated with `key`.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Errors log the failed write and set `has_errors`.
 | 
				
			||||||
    pub fn delete(&self, key: &str) -> Result<()> {
 | 
					    pub fn delete(&self, key: &str) -> Result<()> {
 | 
				
			||||||
        self.conn.execute("DELETE FROM kv_store WHERE key = ?1", params![key])?;
 | 
					        match self.conn.execute("DELETE FROM kv_store WHERE key = ?1", params![key]) {
 | 
				
			||||||
 | 
					            Ok(_) => Ok(()),
 | 
				
			||||||
 | 
					            Err(e) => {
 | 
				
			||||||
 | 
					                eprintln!("Failed DB write: ({}, NULL)", key);
 | 
				
			||||||
 | 
					                self.has_write_errors.set(true);
 | 
				
			||||||
 | 
					                Err(e)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Dump the current DB contents to stderr.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// For all keys listed in `redacted_keys`, no value is printed, only the presence is reported.
 | 
				
			||||||
 | 
					    pub fn dump_redacting(&self, redacted_keys: &[&str]) -> Result<()> {
 | 
				
			||||||
 | 
					        let exclude_set: HashSet<&str> = redacted_keys.iter().cloned().collect();
 | 
				
			||||||
 | 
					        let mut stmt = self.conn.prepare("SELECT key, value FROM kv_store")?;
 | 
				
			||||||
 | 
					        let mut rows = stmt.query(params![])?;
 | 
				
			||||||
 | 
					        while let Some(row) = rows.next()? {
 | 
				
			||||||
 | 
					            let key: String = row.get(0)?;
 | 
				
			||||||
 | 
					            if exclude_set.contains(key.as_str()) {
 | 
				
			||||||
 | 
					                eprintln!("{} = REDACTED", key);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                let value: String = row.get(1)?;
 | 
				
			||||||
 | 
					                eprintln!("{} = {}", key, value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Index<&str> for KeyValueStore {
 | 
				
			||||||
 | 
					    type Output = str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					    fn index(&self, key: &str) -> &Self::Output {
 | 
				
			||||||
fn main() -> Result<()> {
 | 
					        Box::leak(Box::new(self.get(key).unwrap())).as_str()
 | 
				
			||||||
    let kv_store = KeyValueStore::new("kv_store.db")?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Set some key-value pairs
 | 
					 | 
				
			||||||
    kv_store.set("last_week_pad", "pad_id_123")?;
 | 
					 | 
				
			||||||
    kv_store.set("email_id", "email_id_456")?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Retrieve and print values
 | 
					 | 
				
			||||||
    if let Some(value) = kv_store.get("last_week_pad")? {
 | 
					 | 
				
			||||||
        println!("Last week's pad ID: {}", value);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        println!("Key not found");
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if let Some(value) = kv_store.get("email_id")? {
 | 
					 | 
				
			||||||
        println!("Email ID: {}", value);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        println!("Key not found");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Delete a key-value pair
 | 
					 | 
				
			||||||
    kv_store.delete("last_week_pad")?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Ok(())
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
							
								
								
									
										56
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										56
									
								
								src/main.rs
									
										
									
									
									
								
							| 
						 | 
					@ -28,7 +28,7 @@ mod create_new_pads;
 | 
				
			||||||
pub mod variables_and_settings;
 | 
					pub mod variables_and_settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use chrono::{Datelike, Local, NaiveDate, Weekday};
 | 
					use chrono::{Datelike, Local, NaiveDate, Weekday};
 | 
				
			||||||
use regex::{Regex};
 | 
					use regex::Regex;
 | 
				
			||||||
use uuid::Uuid;
 | 
					use uuid::Uuid;
 | 
				
			||||||
use reqwest::Client;
 | 
					use reqwest::Client;
 | 
				
			||||||
use std::error::Error;
 | 
					use std::error::Error;
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,6 @@ use pandoc;
 | 
				
			||||||
// MAIL START
 | 
					// MAIL START
 | 
				
			||||||
use lettre::{Message, SmtpTransport, Transport};
 | 
					use lettre::{Message, SmtpTransport, Transport};
 | 
				
			||||||
use lettre::message::{header, SinglePart};
 | 
					use lettre::message::{header, SinglePart};
 | 
				
			||||||
use lettre::message::header::MessageId;
 | 
					 | 
				
			||||||
use lettre::transport::smtp::authentication::Credentials;
 | 
					use lettre::transport::smtp::authentication::Credentials;
 | 
				
			||||||
// MAIL END
 | 
					// MAIL END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,20 +55,25 @@ const PLENUM_TEMPLATE_URL: &str = variables_and_settings::PLENUM_TEMPLATE_URL;
 | 
				
			||||||
const FALLBACK_TEMPLATE: &str = variables_and_settings::FALLBACK_TEMPLATE;
 | 
					const FALLBACK_TEMPLATE: &str = variables_and_settings::FALLBACK_TEMPLATE;
 | 
				
			||||||
const TESTING_MODE: EMailOperationStates = EMailOperationStates::Test;
 | 
					const TESTING_MODE: EMailOperationStates = EMailOperationStates::Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn kv_defaults (kv: &KV) {
 | 
					fn kv_defaults (kv: &KV) {
 | 
				
			||||||
    kv.default("template-url", "https://md.berlin.ccc.de/plenum-template");
 | 
					    kv.default("hedgedoc-server-url","https://md.berlin.ccc.de/");
 | 
				
			||||||
 | 
					    kv.default("hedgedoc-template-name","plenum-template");
 | 
				
			||||||
 | 
					    // hedgedoc-last-id, hedgedoc-next-id have no defaults
 | 
				
			||||||
 | 
					    kv.default("email-server","mail.berlin.ccc.de");
 | 
				
			||||||
 | 
					    kv.default("email-user","plenum-bot@berlin.ccc.de");
 | 
				
			||||||
 | 
					    kv.default("email-name","Plenumsbot");
 | 
				
			||||||
 | 
					    // add email-pass and email-to manually
 | 
				
			||||||
 | 
					    // email-last-message-id has no default
 | 
				
			||||||
    kv.default("email-signature", "\n\n[Diese Nachricht wurde automatisiert vom Plenumsbot erstellt und ist daher ohne Unterschrift gültig.]");
 | 
					    kv.default("email-signature", "\n\n[Diese Nachricht wurde automatisiert vom Plenumsbot erstellt und ist daher ohne Unterschrift gültig.]");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#[tokio::main]
 | 
					#[tokio::main]
 | 
				
			||||||
async fn main() {
 | 
					async fn main() -> Result<(), Box<dyn Error>> {
 | 
				
			||||||
    // BEGIN ANKÜNDIGUNGSSCRIPT
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // config
 | 
					    // config
 | 
				
			||||||
    let config = KV::new("plenum_config.sqlite").unwrap();
 | 
					    let config = KV::new("plenum_config.sqlite").unwrap();
 | 
				
			||||||
    kv_defaults(&config);
 | 
					    kv_defaults(&config);
 | 
				
			||||||
    println!("[BEGINNING] Aktuelle Situation der Datenbank: \"current_pad_link\": https://md.berlin.ccc.de/{}, \"zukünftiges-plenumspad\" https://md.berlin.ccc.de/{}", config.get("aktuelles-plenumspad").unwrap().unwrap(), config.get("zukünftiges-plenumspad").unwrap_or_else(|error|Option::from(String::from("error"))).unwrap_or(String::from("error")));
 | 
					    let hedgedoc_server = &config["hedgedoc-server-url"];
 | 
				
			||||||
 | 
					    println!("[START]\nAktueller Zustand der DB:");
 | 
				
			||||||
 | 
					    config.dump_redacting(&["email-pass","matrix-pass"]).ok();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Dienstage diesen Monat
 | 
					    // Dienstage diesen Monat
 | 
				
			||||||
    let all_tuesdays: Vec<Option<NaiveDate>> = get_tuesdays(0);
 | 
					    let all_tuesdays: Vec<Option<NaiveDate>> = get_tuesdays(0);
 | 
				
			||||||
| 
						 | 
					@ -110,21 +114,21 @@ async fn main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Der Code muss nur für vor dem 2. und vor dem 4. Dienstag gebaut werden, weil im nächsten Monat der Code frühestens 7 Tage vor dem Plenum wieder passt.
 | 
					    // Der Code muss nur für vor dem 2. und vor dem 4. Dienstag gebaut werden, weil im nächsten Monat der Code frühestens 7 Tage vor dem Plenum wieder passt.
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    let in_1_day_is_plenum: bool = check_if_plenum(nächster_plenumtermin.clone(), in_1_day);
 | 
					    let in_1_day_is_plenum: bool = check_if_plenum(nächster_plenumtermin.clone(), in_1_day);
 | 
				
			||||||
    let in_3_days_is_plenum: bool = check_if_plenum(nächster_plenumtermin.clone(), in_3_days);
 | 
					    let in_3_days_is_plenum: bool = check_if_plenum(nächster_plenumtermin.clone(), in_3_days);
 | 
				
			||||||
    let yesterday_was_plenum: bool = check_if_plenum(nächster_plenumtermin.clone(), yesterday);
 | 
					    let yesterday_was_plenum: bool = check_if_plenum(nächster_plenumtermin.clone(), yesterday);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    // Pad-Links aus der Datenbank laden:
 | 
					    // Pad-Links aus der Datenbank laden:
 | 
				
			||||||
    let pad_id: String = config.get("aktuelles-plenumspad").unwrap().unwrap();
 | 
					    let pad_id = &config["aktuelles-plenumspad"];
 | 
				
			||||||
    let current_pad_link: String = format!("https://md.berlin.ccc.de/{}", pad_id);
 | 
					    let current_pad_link: String = format!("{}{}", hedgedoc_server, pad_id);
 | 
				
			||||||
    let future_pad_id:String = config.get("zukünftiges-plenumspad").unwrap_or_else(|error|Option::from(String::from("error"))).unwrap_or(String::from("error"));
 | 
					    let future_pad_id = &config["zukünftiges-plenumspad"];
 | 
				
			||||||
    let future_pad_link: String = format!("https://md.berlin.ccc.de/{}", future_pad_id);
 | 
					    let future_pad_link: String = format!("{}{}", hedgedoc_server, future_pad_id);
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    let mut message_id: String = String::from("FEHLER"); // message id initialisieren
 | 
					    let mut message_id: String = String::from("FEHLER"); // message id initialisieren
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    // let in_3_days_is_plenum = true;
 | 
					    // let in_3_days_is_plenum = true;
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    let top_anzahl: i32 = 0; // Muss noch gecodet werden
 | 
					    let top_anzahl: i32 = 0; // Muss noch gecodet werden
 | 
				
			||||||
    let in_1_day_is_plenum = true;
 | 
					    let in_1_day_is_plenum = true;
 | 
				
			||||||
    if in_1_day_is_plenum {
 | 
					    if in_1_day_is_plenum {
 | 
				
			||||||
| 
						 | 
					@ -183,10 +187,10 @@ async fn main() {
 | 
				
			||||||
        message_id = mail_versenden(message, betreff).expect("Mail mit Plenumsprotokoll wurde versucht zu senden, konnte aber nicht gesendet werden!");
 | 
					        message_id = mail_versenden(message, betreff).expect("Mail mit Plenumsprotokoll wurde versucht zu senden, konnte aber nicht gesendet werden!");
 | 
				
			||||||
        pad_ins_wiki(old_pad_content_without_top_instructions);
 | 
					        pad_ins_wiki(old_pad_content_without_top_instructions);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    println!("[END] Aktuelle Situation der Datenbank: \"current_pad_link\": https://md.berlin.ccc.de/{}, \"zukünftiges-plenumspad\" https://md.berlin.ccc.de/{}", config.get("aktuelles-plenumspad").unwrap().unwrap(), config.get("zukünftiges-plenumspad").unwrap_or_else(|error|Option::from(String::from("error"))).unwrap_or(String::from("error")));
 | 
					    println!("[ENDE]\nAktueller Zustand der DB:");
 | 
				
			||||||
    
 | 
					    config.dump_redacting(&["email-pass","matrix-pass"]).ok();
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    if config.has_errors() { Err("There were errors.".into()) } else { Ok(()) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -197,7 +201,7 @@ async fn download_and_return_pad(pad_link: String) -> Result<String, Box<dyn std
 | 
				
			||||||
        .text()
 | 
					        .text()
 | 
				
			||||||
        .await?;
 | 
					        .await?;
 | 
				
			||||||
    //println!("{}", pad_content);
 | 
					    //println!("{}", pad_content);
 | 
				
			||||||
    Ok(pad_content) 
 | 
					    Ok(pad_content)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn get_tuesdays(month_offset: u32) -> Vec<Option<NaiveDate>>{
 | 
					fn get_tuesdays(month_offset: u32) -> Vec<Option<NaiveDate>>{
 | 
				
			||||||
| 
						 | 
					@ -256,7 +260,7 @@ fn mail_versenden(inhalt: String, betreff: String) -> std::result::Result<String
 | 
				
			||||||
    let message_id: String = Uuid::new_v4().to_string() + &String::from("@berlin.ccc.de");
 | 
					    let message_id: String = Uuid::new_v4().to_string() + &String::from("@berlin.ccc.de");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mail_to: &str = if TESTING_MODE == EMailOperationStates::Test { "Marek Krug <mail@marekkrug.de>"} else {"CCCB Intern <intern@berlin.ccc.de>"};
 | 
					    let mail_to: &str = if TESTING_MODE == EMailOperationStates::Test { "Marek Krug <mail@marekkrug.de>"} else {"CCCB Intern <intern@berlin.ccc.de>"};
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    let email = Message::builder()
 | 
					    let email = Message::builder()
 | 
				
			||||||
        // Set the sender's name and email address
 | 
					        // Set the sender's name and email address
 | 
				
			||||||
        .from("Plenum Bot <plenum-bot@berlin.ccc.de>".parse().unwrap())
 | 
					        .from("Plenum Bot <plenum-bot@berlin.ccc.de>".parse().unwrap())
 | 
				
			||||||
| 
						 | 
					@ -320,7 +324,7 @@ fn replace_placeholders(template: &str, übernächster_plenumtermin: String, üb
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn rotate (future_pad_id: &str, kv: &KV) {
 | 
					fn rotate (future_pad_id: &str, kv: &KV) {
 | 
				
			||||||
    let next_plenum_pad = kv.get("zukünftiges-plenumspad").unwrap_or_else(|error | None);
 | 
					    let next_plenum_pad = kv.get("zukünftiges-plenumspad").ok();
 | 
				
			||||||
    if next_plenum_pad == None {
 | 
					    if next_plenum_pad == None {
 | 
				
			||||||
        kv.set("zukünftiges-plenumspad", &future_pad_id).expect("Fehler beim Beschreiben der Datenbank mit neuem Plenumslink!"); // Beispiel: aktuelles-plenumspad: Ok(Some("eCH24zXGS9S8Stg5xI3aRg"))
 | 
					        kv.set("zukünftiges-plenumspad", &future_pad_id).expect("Fehler beim Beschreiben der Datenbank mit neuem Plenumslink!"); // Beispiel: aktuelles-plenumspad: Ok(Some("eCH24zXGS9S8Stg5xI3aRg"))
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
| 
						 | 
					@ -339,7 +343,7 @@ fn try_to_remove_top_instructions (pad_content: String) -> String {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn pad_ins_wiki(old_pad_content: String) {
 | 
					fn pad_ins_wiki(old_pad_content: String) {
 | 
				
			||||||
    //Convert Markdown into Mediawiki
 | 
					    //Convert Markdown into Mediawiki
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    let pandoc_parsed = old_pad_content; // MUSS GEÄNDERT WERDEN
 | 
					    let pandoc_parsed = old_pad_content; // MUSS GEÄNDERT WERDEN
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue