Compare commits

..

No commits in common. "b3c4d8a38c5766ad336b5d63254a1d5ee7174dfd" and "055bad3a46e383bf15245a8b0b4a75bf21064e93" have entirely different histories.

12 changed files with 117 additions and 329 deletions

223
Cargo.lock generated
View File

@ -275,14 +275,13 @@ dependencies = [
"dirs", "dirs",
"env_logger", "env_logger",
"futures", "futures",
"html2text",
"indoc", "indoc",
"itertools", "itertools",
"log", "log",
"matrix-sdk", "matrix-sdk",
"memmem", "memmem",
"nom", "nom",
"phf 0.7.24", "phf",
"rand 0.7.3", "rand 0.7.3",
"serde", "serde",
"sled", "sled",
@ -543,16 +542,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "futf"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b"
dependencies = [
"mac",
"new_debug_unreachable",
]
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.12" version = "0.3.12"
@ -778,31 +767,6 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "html2text"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26379dcb715e237b96102a12b505c553e2bffa74bae2e54658748d298660ef1"
dependencies = [
"html5ever",
"markup5ever_rcdom",
"unicode-width",
]
[[package]]
name = "html5ever"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aafcf38a1a36118242d29b92e1b08ef84e67e4a5ed06e0a80be20e6a32bfed6b"
dependencies = [
"log",
"mac",
"markup5ever",
"proc-macro2 1.0.24",
"quote 1.0.8",
"syn 1.0.60",
]
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.3" version = "0.2.3"
@ -920,7 +884,7 @@ checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"js-sys", "js-sys",
"time 0.2.25", "time",
"wasm-bindgen", "wasm-bindgen",
"web-sys", "web-sys",
] ]
@ -1007,47 +971,12 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
] ]
[[package]]
name = "mac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]] [[package]]
name = "maplit" name = "maplit"
version = "1.0.2" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "markup5ever"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae38d669396ca9b707bfc3db254bc382ddb94f57cc5c235f34623a669a01dab"
dependencies = [
"log",
"phf 0.8.0",
"phf_codegen",
"serde",
"serde_derive",
"serde_json",
"string_cache",
"string_cache_codegen",
"tendril",
]
[[package]]
name = "markup5ever_rcdom"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f015da43bcd8d4f144559a3423f4591d69b8ce0652c905374da7205df336ae2b"
dependencies = [
"html5ever",
"markup5ever",
"tendril",
"xml5ever",
]
[[package]] [[package]]
name = "matches" name = "matches"
version = "0.1.8" version = "0.1.8"
@ -1206,12 +1135,6 @@ dependencies = [
"tempfile", "tempfile",
] ]
[[package]]
name = "new_debug_unreachable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]] [[package]]
name = "nom" name = "nom"
version = "5.1.2" version = "5.1.2"
@ -1362,26 +1285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
dependencies = [ dependencies = [
"phf_macros", "phf_macros",
"phf_shared 0.7.24", "phf_shared",
]
[[package]]
name = "phf"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
dependencies = [
"phf_shared 0.8.0",
]
[[package]]
name = "phf_codegen"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
dependencies = [
"phf_generator 0.8.0",
"phf_shared 0.8.0",
] ]
[[package]] [[package]]
@ -1390,28 +1294,18 @@ version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
dependencies = [ dependencies = [
"phf_shared 0.7.24", "phf_shared",
"rand 0.6.5", "rand 0.6.5",
] ]
[[package]]
name = "phf_generator"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
dependencies = [
"phf_shared 0.8.0",
"rand 0.7.3",
]
[[package]] [[package]]
name = "phf_macros" name = "phf_macros"
version = "0.7.24" version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdb45e833315153371697760dad1831da99ce41884162320305e4f123ca3fe37" checksum = "bdb45e833315153371697760dad1831da99ce41884162320305e4f123ca3fe37"
dependencies = [ dependencies = [
"phf_generator 0.7.24", "phf_generator",
"phf_shared 0.7.24", "phf_shared",
"proc-macro2 0.4.30", "proc-macro2 0.4.30",
"quote 0.6.13", "quote 0.6.13",
"syn 0.15.44", "syn 0.15.44",
@ -1423,16 +1317,7 @@ version = "0.7.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
dependencies = [ dependencies = [
"siphasher 0.2.3", "siphasher",
]
[[package]]
name = "phf_shared"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
dependencies = [
"siphasher 0.3.3",
] ]
[[package]] [[package]]
@ -1520,12 +1405,6 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "0.1.5" version = "0.1.5"
@ -1603,7 +1482,7 @@ dependencies = [
"rand_isaac", "rand_isaac",
"rand_jitter", "rand_jitter",
"rand_os", "rand_os",
"rand_pcg 0.1.2", "rand_pcg",
"rand_xorshift", "rand_xorshift",
"winapi", "winapi",
] ]
@ -1619,7 +1498,6 @@ dependencies = [
"rand_chacha 0.2.2", "rand_chacha 0.2.2",
"rand_core 0.5.1", "rand_core 0.5.1",
"rand_hc 0.2.0", "rand_hc 0.2.0",
"rand_pcg 0.2.1",
] ]
[[package]] [[package]]
@ -1768,15 +1646,6 @@ dependencies = [
"rand_core 0.4.2", "rand_core 0.4.2",
] ]
[[package]]
name = "rand_pcg"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
dependencies = [
"rand_core 0.5.1",
]
[[package]] [[package]]
name = "rand_xorshift" name = "rand_xorshift"
version = "0.1.1" version = "0.1.1"
@ -2213,12 +2082,6 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
[[package]]
name = "siphasher"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.2" version = "0.4.2"
@ -2322,31 +2185,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
[[package]]
name = "string_cache"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ddb1139b5353f96e429e1a5e19fbaf663bddedaa06d1dbd49f82e352601209a"
dependencies = [
"lazy_static",
"new_debug_unreachable",
"phf_shared 0.8.0",
"precomputed-hash",
"serde",
]
[[package]]
name = "string_cache_codegen"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97"
dependencies = [
"phf_generator 0.8.0",
"phf_shared 0.8.0",
"proc-macro2 1.0.24",
"quote 1.0.8",
]
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.4.0" version = "2.4.0"
@ -2401,17 +2239,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "tendril"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9ef557cb397a4f0a5a3a628f06515f78563f2209e64d47055d9dc6052bf5e33"
dependencies = [
"futf",
"mac",
"utf-8",
]
[[package]] [[package]]
name = "termcolor" name = "termcolor"
version = "1.1.2" version = "1.1.2"
@ -2450,16 +2277,6 @@ dependencies = [
"once_cell", "once_cell",
] ]
[[package]]
name = "time"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
dependencies = [
"libc",
"winapi",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.2.25" version = "0.2.25"
@ -2668,12 +2485,6 @@ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.1.0" version = "0.1.0"
@ -2714,12 +2525,6 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "utf-8"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "0.8.2" version = "0.8.2"
@ -2882,18 +2687,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "xml5ever"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b1b52e6e8614d4a58b8e70cf51ec0cc21b256ad8206708bcff8139b5bbd6a59"
dependencies = [
"log",
"mac",
"markup5ever",
"time 0.1.43",
]
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.3.0" version = "0.3.0"

View File

@ -29,7 +29,6 @@ byteorder = "1.3"
futures = "0.3" futures = "0.3"
memmem = "0.1" memmem = "0.1"
bincode = "1.3" bincode = "1.3"
html2text = "0.2"
phf = { version = "0.7", features = ["macros"] } phf = { version = "0.7", features = ["macros"] }
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "master" } matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", branch = "master" }

View File

@ -25,8 +25,9 @@ async fn main() -> Result<(), BotError> {
message_body: &input, message_body: &input,
}; };
let message = command.execute(&context).await.message_html("fakeuser"); println!(
let message = html2text::from_read(message.as_bytes(), 80); "{}",
println!("{}", message.trim()); command.execute(&context).await.message_plain("fakeuser")
);
Ok(()) Ok(())
} }

View File

@ -1,13 +1,20 @@
use crate::commands::{execute_command, CommandResult, ExecutionError, ResponseExtractor}; use crate::commands::execute_command;
use crate::config::*; use crate::config::*;
use crate::context::{Context, RoomContext}; use crate::context::{Context, RoomContext};
use crate::db::Database; use crate::db::Database;
use crate::error::BotError; use crate::error::BotError;
use crate::matrix;
use crate::state::DiceBotState; use crate::state::DiceBotState;
use dirs; use dirs;
use log::info; use log::{error, info};
use matrix_sdk::{self, identifiers::RoomId, Client, ClientConfig, JoinedRoom, SyncSettings}; use matrix_sdk::Error as MatrixError;
use matrix_sdk::{
self,
events::{
room::message::{MessageEventContent, NoticeMessageEventContent},
AnyMessageEventContent,
},
Client, ClientConfig, JoinedRoom, SyncSettings,
};
//use matrix_sdk_common_macros::async_trait; //use matrix_sdk_common_macros::async_trait;
use std::clone::Clone; use std::clone::Clone;
use std::path::PathBuf; use std::path::PathBuf;
@ -48,54 +55,13 @@ fn create_client(config: &Config) -> Result<Client, BotError> {
Ok(Client::new_with_config(homeserver_url, client_config)?) Ok(Client::new_with_config(homeserver_url, client_config)?)
} }
/// Handle responding to a single command being executed. Wil print /// Extracts more detailed error messages out of a matrix SDK error.
/// out the full result of that command. fn extract_error_message(error: MatrixError) -> String {
async fn handle_single_result( use matrix_sdk::Error::RumaResponse;
client: &Client, match error {
cmd_result: &CommandResult, RumaResponse(ruma_error) => ruma_error.to_string(),
respond_to: &str, _ => error.to_string(),
room_id: &RoomId, }
) {
let html = cmd_result.message_html(respond_to);
matrix::send_message(client, room_id, &html).await;
}
/// Handle responding to multiple commands being executed. Will print
/// out how many commands succeeded and failed (if any failed).
async fn handle_multiple_results(
client: &Client,
results: &[(&str, CommandResult)],
respond_to: &str,
room_id: &RoomId,
) {
let errors: Vec<(&str, &ExecutionError)> = results
.into_iter()
.filter_map(|(cmd, result)| match result {
Err(e) => Some((*cmd, e)),
_ => None,
})
.collect();
let message = if errors.len() == 0 {
format!("{}: Executed {} commands", respond_to, results.len())
} else {
let failures: String = errors
.iter()
.map(|&(cmd, err)| format!("<strong>{}:</strong> {}", cmd, err))
.collect::<Vec<_>>()
.join("\n");
format!(
"{}: Executed {} commands ({} failed)\n\nFailures:\n{}",
respond_to,
results.len(),
errors.len(),
failures
)
.replace("\n", "<br/>")
};
matrix::send_message(client, room_id, &message).await;
} }
impl DiceBot { impl DiceBot {
@ -156,7 +122,7 @@ impl DiceBot {
let room_name = room.display_name().await.ok().unwrap_or_default(); let room_name = room.display_name().await.ok().unwrap_or_default();
let room_id = room.room_id().clone(); let room_id = room.room_id().clone();
let mut results: Vec<(&str, CommandResult)> = Vec::with_capacity(msg_body.lines().count()); let mut results = Vec::with_capacity(msg_body.lines().count());
let commands = msg_body.trim().lines().filter(|line| line.starts_with("!")); let commands = msg_body.trim().lines().filter(|line| line.starts_with("!"));
@ -170,14 +136,37 @@ impl DiceBot {
}; };
let cmd_result = execute_command(&ctx).await; let cmd_result = execute_command(&ctx).await;
results.push((&command, cmd_result)); results.push(cmd_result);
} }
use crate::commands::ResponseExtractor;
if results.len() >= 1 { if results.len() >= 1 {
if results.len() == 1 { if results.len() == 1 {
handle_single_result(&self.client, &results[0].1, sender_username, &room_id).await; let cmd_result = &results[0];
let response = AnyMessageEventContent::RoomMessage(MessageEventContent::Notice(
NoticeMessageEventContent::html(
cmd_result.message_plain(&sender_username),
cmd_result.message_html(&sender_username),
),
));
let result = self.client.room_send(&room_id, response, None).await;
if let Err(e) = result {
let message = extract_error_message(e);
error!("Error sending message: {}", message);
};
} else if results.len() > 1 { } else if results.len() > 1 {
handle_multiple_results(&self.client, &results, sender_username, &room_id).await; let message = format!("{}: Executed {} commands", sender_username, results.len());
let response = AnyMessageEventContent::RoomMessage(MessageEventContent::Notice(
NoticeMessageEventContent::html(&message, &message),
));
let result = self.client.room_send(&room_id, response, None).await;
if let Err(e) = result {
let message = extract_error_message(e);
error!("Error sending message: {}", message);
};
} }
info!("[{}] {} executed: {}", room_name, sender_username, msg_body); info!("[{}] {} executed: {}", room_name, sender_username, msg_body);

View File

@ -23,16 +23,22 @@ pub enum CommandError {
} }
/// A successfully executed command returns a message to be sent back /// A successfully executed command returns a message to be sent back
/// to the user in HTML (plain text used as a fallback by message /// to the user in both plain text and HTML, one of which will be
/// formatter). /// displayed in the user's client depending on its capabilities.
#[derive(Debug)] #[derive(Debug)]
pub struct Execution { pub struct Execution {
plain: String,
html: String, html: String,
} }
impl Execution { impl Execution {
pub fn new(html: String) -> CommandResult { pub fn new(plain: String, html: String) -> CommandResult {
Ok(Execution { html }) Ok(Execution { plain, html })
}
/// Response message in plain text.
pub fn plain(&self) -> String {
self.plain.clone()
} }
/// Response message in HTML. /// Response message in HTML.
@ -41,9 +47,10 @@ impl Execution {
} }
} }
/// Wraps a command execution failure. Provides HTML formatting for /// Wraps a command execution failure. Provides plain-text and HTML
/// any error message from the BotError type, similar to how Execution /// formatting for any error message from the BotError type, similar
/// provides formatting for successfully executed commands. /// to how Response provides formatting for successfully executed
/// commands.
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[error("{0}")] #[error("{0}")]
pub struct ExecutionError(#[from] BotError); pub struct ExecutionError(#[from] BotError);
@ -55,6 +62,11 @@ impl From<crate::db::errors::DataError> for ExecutionError {
} }
impl ExecutionError { impl ExecutionError {
/// Error message in plain text.
pub fn plain(&self) -> String {
format!("{}", self.0)
}
/// Error message in bolded HTML. /// Error message in bolded HTML.
pub fn html(&self) -> String { pub fn html(&self) -> String {
format!("<p><strong>{}</strong></p>", self.0) format!("<p><strong>{}</strong></p>", self.0)
@ -68,17 +80,29 @@ pub type CommandResult = Result<Execution, ExecutionError>;
/// Extract response messages out of a type, whether it is success or /// Extract response messages out of a type, whether it is success or
/// failure. /// failure.
pub trait ResponseExtractor { pub trait ResponseExtractor {
/// Plain-text representation of the message, directly mentioning
/// the username.
fn message_plain(&self, username: &str) -> String;
/// HTML representation of the message, directly mentioning the /// HTML representation of the message, directly mentioning the
/// username. /// username.
fn message_html(&self, username: &str) -> String; fn message_html(&self, username: &str) -> String;
} }
impl ResponseExtractor for CommandResult { impl ResponseExtractor for CommandResult {
/// Error message in plain text.
fn message_plain(&self, username: &str) -> String {
match self {
Ok(resp) => format!("{}\n{}", username, resp.plain()),
Err(e) => format!("{}\n{}", username, e.plain()),
}
}
/// Error message in bolded HTML. /// Error message in bolded HTML.
fn message_html(&self, username: &str) -> String { fn message_html(&self, username: &str) -> String {
match self { match self {
Ok(resp) => format!("<p>{}</p><p>{}</p>", username, resp.html).replace("\n", "<br/>"), Ok(resp) => format!("<p>{}</p>\n{}", username, resp.html),
Err(e) => format!("<p>{}</p><p>{}</p>", username, e.html()).replace("\n", "<br/>"), Err(e) => format!("<p>{}</p>\n{}", username, e.html()),
} }
} }
} }

View File

@ -14,11 +14,12 @@ impl Command for RollCommand {
async fn execute(&self, _ctx: &Context<'_>) -> CommandResult { async fn execute(&self, _ctx: &Context<'_>) -> CommandResult {
let roll = self.0.roll(); let roll = self.0.roll();
let plain = format!("Dice: {}\nResult: {}", self.0, roll);
let html = format!( let html = format!(
"<p><strong>Dice:</strong> {}</p><p><strong>Result</strong>: {}</p>", "<p><strong>Dice:</strong> {}</p><p><strong>Result</strong>: {}</p>",
self.0, roll self.0, roll
); );
Execution::new(html) Execution::new(plain, html)
} }
} }

View File

@ -15,11 +15,12 @@ impl Command for PoolRollCommand {
let pool_with_ctx = DicePoolWithContext(&self.0, ctx); let pool_with_ctx = DicePoolWithContext(&self.0, ctx);
let rolled_pool = roll_pool(&pool_with_ctx).await?; let rolled_pool = roll_pool(&pool_with_ctx).await?;
let plain = format!("Pool: {}\nResult: {}", rolled_pool, rolled_pool.roll);
let html = format!( let html = format!(
"<p><strong>Pool:</strong> {}</p><p><strong>Result</strong>: {}</p>", "<p><strong>Pool:</strong> {}</p><p><strong>Result</strong>: {}</p>",
rolled_pool, rolled_pool.roll rolled_pool, rolled_pool.roll
); );
Execution::new(html) Execution::new(plain, html)
} }
} }

View File

@ -15,12 +15,13 @@ impl Command for CthRoll {
let roll_with_ctx = DiceRollWithContext(&self.0, ctx); let roll_with_ctx = DiceRollWithContext(&self.0, ctx);
let executed_roll = regular_roll(&roll_with_ctx).await?; let executed_roll = regular_roll(&roll_with_ctx).await?;
let plain = format!("Roll: {}\nResult: {}", executed_roll, executed_roll.roll);
let html = format!( let html = format!(
"<p><strong>Roll:</strong> {}</p><p><strong>Result</strong>: {}</p>", "<p><strong>Roll:</strong> {}</p><p><strong>Result</strong>: {}</p>",
executed_roll, executed_roll.roll executed_roll, executed_roll.roll
); );
Execution::new(html) Execution::new(plain, html)
} }
} }
@ -35,11 +36,12 @@ impl Command for CthAdvanceRoll {
async fn execute(&self, _ctx: &Context<'_>) -> CommandResult { async fn execute(&self, _ctx: &Context<'_>) -> CommandResult {
//TODO this will be converted to a result when supporting variables. //TODO this will be converted to a result when supporting variables.
let roll = self.0.roll(); let roll = self.0.roll();
let plain = format!("Roll: {}\nResult: {}", self.0, roll);
let html = format!( let html = format!(
"<p><strong>Roll:</strong> {}</p><p><strong>Result</strong>: {}</p>", "<p><strong>Roll:</strong> {}</p><p><strong>Result</strong>: {}</p>",
self.0, roll self.0, roll
); );
Execution::new(html) Execution::new(plain, html)
} }
} }

View File

@ -25,7 +25,9 @@ impl Command for ResyncCommand {
) )
.await?; .await?;
let message = "Room information resynced.".to_string(); let plain = "Room information resynced".to_string();
Execution::new(message) let html = "<p>Room information resynced.</p>".to_string();
Execution::new(plain, html)
} }
} }

View File

@ -17,7 +17,8 @@ impl Command for HelpCommand {
_ => "There is no help for this topic", _ => "There is no help for this topic",
}; };
let html = format!("<strong>Help:</strong> {}", help.replace("\n", "<br/>")); let plain = format!("Help: {}", help);
Execution::new(html) let html = format!("<p><strong>Help:</strong> {}", help.replace("\n", "<br/>"));
Execution::new(plain, html)
} }
} }

View File

@ -24,11 +24,12 @@ impl Command for GetAllVariablesCommand {
variable_list.sort(); variable_list.sort();
let value = variable_list.join("\n"); let value = variable_list.join("\n");
let plain = format!("Variables:\n{}", value);
let html = format!( let html = format!(
"<strong>Variables:</strong><br/>{}", "<p><strong>Variables:</strong><br/>{}",
value.replace("\n", "<br/>") value.replace("\n", "<br/>")
); );
Execution::new(html) Execution::new(plain, html)
} }
} }
@ -51,8 +52,9 @@ impl Command for GetVariableCommand {
Err(e) => return Err(e.into()), Err(e) => return Err(e.into()),
}; };
let html = format!("<strong>Variable:</strong> {}", value); let plain = format!("Variable: {}", value);
Execution::new(html) let html = format!("<p><strong>Variable:</strong> {}", value);
Execution::new(plain, html)
} }
} }
@ -72,8 +74,9 @@ impl Command for SetVariableCommand {
ctx.db.variables.set_user_variable(&key, name, value)?; ctx.db.variables.set_user_variable(&key, name, value)?;
let content = format!("{} = {}", name, value); let content = format!("{} = {}", name, value);
let html = format!("<strong>Set Variable:</strong> {}", content); let plain = format!("Set Variable: {}", content);
Execution::new(html) let html = format!("<p><strong>Set Variable:</strong> {}", content);
Execution::new(plain, html)
} }
} }
@ -96,7 +99,8 @@ impl Command for DeleteVariableCommand {
Err(e) => return Err(e.into()), Err(e) => return Err(e.into()),
}; };
let html = format!("<strong>Remove Variable:</strong> {}", value); let plain = format!("Remove Variable: {}", value);
Execution::new(html) let html = format!("<p><strong>Remove Variable:</strong> {}", value);
Execution::new(plain, html)
} }
} }

View File

@ -1,20 +1,5 @@
use log::error;
use matrix_sdk::events::{
room::message::{MessageEventContent::Notice, NoticeMessageEventContent},
AnyMessageEventContent::RoomMessage,
};
use matrix_sdk::Error as MatrixError;
use matrix_sdk::{identifiers::RoomId, Client}; use matrix_sdk::{identifiers::RoomId, Client};
/// Extracts more detailed error messages out of a matrix SDK error.
fn extract_error_message(error: MatrixError) -> String {
use matrix_sdk::Error::RumaResponse;
match error {
RumaResponse(ruma_error) => ruma_error.to_string(),
_ => error.to_string(),
}
}
/// Retrieve a list of users in a given room. /// Retrieve a list of users in a given room.
pub async fn get_users_in_room(client: &Client, room_id: &RoomId) -> Vec<String> { pub async fn get_users_in_room(client: &Client, room_id: &RoomId) -> Vec<String> {
if let Some(joined_room) = client.get_joined_room(room_id) { if let Some(joined_room) = client.get_joined_room(room_id) {
@ -36,17 +21,3 @@ pub async fn get_users_in_room(client: &Client, room_id: &RoomId) -> Vec<String>
vec![] vec![]
} }
} }
pub async fn send_message(client: &Client, room_id: &RoomId, message: &str) {
let plain = html2text::from_read(message.as_bytes(), message.len());
let response = RoomMessage(Notice(NoticeMessageEventContent::html(
plain.trim(),
message,
)));
let result = client.room_send(&room_id, response, None).await;
if let Err(e) = result {
let message = extract_error_message(e);
error!("Error sending message: {}", message);
};
}