M Cargo.lock => Cargo.lock +25 -0
@@ 155,6 155,7 @@ dependencies = [
"async-trait",
"axum",
"clap",
+ "pulldown-cmark",
"reqwest",
"serde",
"serde_json",
@@ 793,6 794,24 @@ dependencies = [
]
[[package]]
+name = "pulldown-cmark"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0"
+dependencies = [
+ "bitflags",
+ "memchr",
+ "pulldown-cmark-escape",
+ "unicase",
+]
+
+[[package]]
+name = "pulldown-cmark-escape"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
+
+[[package]]
name = "quinn"
version = "0.11.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1487,6 1506,12 @@ dependencies = [
]
[[package]]
+name = "unicase"
+version = "2.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
+
+[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
M Cargo.toml => Cargo.toml +3 -0
@@ 25,6 25,9 @@ clap = { version = "4", default-features = false, features = [
"help",
"std",
] }
+pulldown-cmark = { version = "0.13", default-features = false, features = [
+ "html",
+] }
reqwest = { version = "0.12", default-features = false, features = [
"http2",
"rustls-tls",
M src/main.rs => src/main.rs +3 -1
@@ 90,6 90,8 @@ async fn main() {
struct MessageForm {
title: String,
message: String,
+ #[serde(default)]
+ format_commonmark: bool,
}
async fn message(
@@ 121,7 123,7 @@ async fn message(
.iter()
.filter(|(k, _v)| notifier.1.services.contains(k))
{
- match v.send(&message.title, &message.message).await {
+ match v.send(&message).await {
Ok(_) => {}
Err(err) => {
error!(msg = "message sending failed", ?err);
M src/service/gotify.rs => src/service/gotify.rs +6 -3
@@ 8,7 8,10 @@
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
-use crate::config::{ServiceConfig, deserialize_token};
+use crate::{
+ MessageForm,
+ config::{ServiceConfig, deserialize_token},
+};
use super::Service;
@@ 39,12 42,12 @@ impl GotifyService {
#[async_trait]
impl Service for GotifyService {
- async fn send(&self, title: &str, message: &str) -> Result<(), Box<dyn std::error::Error>> {
+ async fn send(&self, form: &MessageForm) -> Result<(), Box<dyn std::error::Error>> {
let _ = self
.client
.post(format!("{}/message", self.config.instance))
.query(&[("token", &self.config.token)])
- .form(&[("title", title), ("message", message)])
+ .form(&[("title", &form.title), ("message", &form.message)])
.send()
.await?;
Ok(())
M src/service/matrix.rs => src/service/matrix.rs +31 -8
@@ 9,10 9,16 @@ use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use serde_json::json;
-use crate::config::{ServiceConfig, deserialize_token};
+use crate::{
+ MessageForm,
+ config::{ServiceConfig, deserialize_token},
+};
use super::Service;
+const COMMONMARK_OPTIONS: pulldown_cmark::Options =
+ pulldown_cmark::Options::ENABLE_TABLES.union(pulldown_cmark::Options::ENABLE_STRIKETHROUGH);
+
#[derive(Clone, Deserialize, Serialize)]
pub struct MatrixConfig {
pub instance: String,
@@ 52,13 58,30 @@ impl MatrixService {
#[async_trait]
impl Service for MatrixService {
- async fn send(&self, title: &str, message: &str) -> Result<(), Box<dyn std::error::Error>> {
- let body = json!({
- "msgtype": "m.notice",
- "body": format!("**{}**\n\n{}", title, message),
- "format": "org.matrix.custom.html",
- "formatted_body": format!("<p><strong>{}</strong></p>\n<p>{}</p>\n", title, message),
- });
+ async fn send(&self, form: &MessageForm) -> Result<(), Box<dyn std::error::Error>> {
+ let body = if form.format_commonmark {
+ let bold_title = format!("**{}**", form.title.trim());
+ let title_parser = pulldown_cmark::Parser::new_ext(&bold_title, COMMONMARK_OPTIONS);
+ let mut html_title = String::new();
+ pulldown_cmark::html::push_html(&mut html_title, title_parser);
+ let body_parser =
+ pulldown_cmark::Parser::new_ext(form.message.trim(), COMMONMARK_OPTIONS);
+ let mut html_body = String::new();
+ pulldown_cmark::html::push_html(&mut html_body, body_parser);
+ json!({
+ "msgtype": "m.notice",
+ "body": format!("{}\n\n{}", form.title, form.message),
+ "format": "org.matrix.custom.html",
+ "formatted_body": format!("{}\n{}", html_title, html_body),
+ })
+ } else {
+ json!({
+ "msgtype": "m.notice",
+ "body": format!("**{}**\n\n{}", form.title, form.message),
+ "format": "org.matrix.custom.html",
+ "formatted_body": format!("<p><strong>{}</strong></p>\n<p>{}</p>", form.title, form.message),
+ })
+ };
let _ = self
.client
.put(format!(
M src/service/mod.rs => src/service/mod.rs +2 -2
@@ 7,14 7,14 @@
use async_trait::async_trait;
-use crate::config::ServiceConfig;
+use crate::{MessageForm, config::ServiceConfig};
pub mod gotify;
pub mod matrix;
#[async_trait]
pub trait Service {
- async fn send(&self, title: &str, message: &str) -> Result<(), Box<dyn std::error::Error>>;
+ async fn send(&self, form: &MessageForm) -> Result<(), Box<dyn std::error::Error>>;
}
pub fn build(
M static/license.html => static/license.html +33 -2
@@ 44,8 44,8 @@
<h2>Overview of licenses:</h2>
<ul class="licenses-overview">
- <li><a href="#Apache-2.0">Apache License 2.0</a> (82)</li>
- <li><a href="#MIT">MIT License</a> (32)</li>
+ <li><a href="#Apache-2.0">Apache License 2.0</a> (83)</li>
+ <li><a href="#MIT">MIT License</a> (34)</li>
<li><a href="#Unicode-3.0">Unicode License v3</a> (20)</li>
<li><a href="#ISC">ISC License</a> (3)</li>
<li><a href="#BSD-3-Clause">BSD 3-Clause "New" or "Revised" License</a> (2)</li>
@@ 2826,6 2826,7 @@ limitations under the License.
<li><a href=" https://github.com/rust-lang/socket2 ">socket2 0.5.8</a></li>
<li><a href=" https://github.com/storyyeller/stable_deref_trait ">stable_deref_trait 1.2.0</a></li>
<li><a href=" https://github.com/Amanieu/thread_local-rs ">thread_local 1.1.8</a></li>
+ <li><a href=" https://github.com/seanmonstar/unicase ">unicase 2.8.1</a></li>
<li><a href=" https://github.com/servo/rust-url ">url 2.5.4</a></li>
</ul>
<pre class="license-text"> Apache License
@@ 4344,6 4345,36 @@ SOFTWARE.</pre>
<h3 id="MIT">MIT License</h3>
<h4>Used by:</h4>
<ul class="license-used-by">
+ <li><a href=" https://github.com/raphlinus/pulldown-cmark ">pulldown-cmark-escape 0.11.0</a></li>
+ <li><a href=" https://github.com/raphlinus/pulldown-cmark ">pulldown-cmark 0.13.0</a></li>
+ </ul>
+ <pre class="license-text">The MIT License
+
+Copyright 2015 Google Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+</pre>
+ </li>
+ <li class="license">
+ <h3 id="MIT">MIT License</h3>
+ <h4>Used by:</h4>
+ <ul class="license-used-by">
<li><a href=" https://github.com/nushell/nu-ansi-term ">nu-ansi-term 0.46.0</a></li>
</ul>
<pre class="license-text">The MIT License (MIT)