bot: watch journald and send events
This commit is contained in:
parent
813ea9848a
commit
dc85ff17e5
119
Cargo.lock
generated
119
Cargo.lock
generated
|
@ -130,9 +130,11 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"futures",
|
||||
"matrix-sdk",
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
"systemd",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing-subscriber",
|
||||
|
@ -166,6 +168,12 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build-env"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6cf89846ef2b2674ef1c153256cec98fba587c72bf4ea2c4b2f6d91a19f55926"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.6.0"
|
||||
|
@ -190,6 +198,12 @@ version = "1.0.66"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -322,7 +336,7 @@ version = "1.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -331,7 +345,7 @@ version = "0.9.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"const_fn",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
|
@ -346,7 +360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
|
@ -360,6 +374,16 @@ dependencies = [
|
|||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cstr-argument"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20bd4e8067c20c7c3a4dea759ef91d4b18418ddb5bd8837ef6e2f2f93ca7ccbb"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.6.0"
|
||||
|
@ -375,7 +399,7 @@ version = "4.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
|
@ -406,7 +430,7 @@ version = "0.8.26"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -421,7 +445,28 @@ version = "0.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
"foreign-types-shared 0.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
|
||||
dependencies = [
|
||||
"foreign-types-macros",
|
||||
"foreign-types-shared 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-macros"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63f713f8b2aa9e24fec85b0e290c56caee12e3b6ae0aeeda238a75b28251afd6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -430,6 +475,12 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7684cf33bb7f28497939e8c7cf17e3e4e3b8d9a0080ffa4f8ae2f515442ee855"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.0.0"
|
||||
|
@ -589,7 +640,7 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi",
|
||||
|
@ -770,7 +821,7 @@ version = "0.1.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"time 0.2.25",
|
||||
"wasm-bindgen",
|
||||
|
@ -819,6 +870,17 @@ version = "0.2.84"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff"
|
||||
|
||||
[[package]]
|
||||
name = "libsystemd-sys"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e03fd580bcecda68dcdcd5297085ade6a3dc552cd8b030d2b94a9b089ef7ab8"
|
||||
dependencies = [
|
||||
"build-env",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.4"
|
||||
|
@ -840,7 +902,7 @@ version = "0.4.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1089,8 +1151,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"cfg-if 1.0.0",
|
||||
"foreign-types 0.3.2",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"openssl-sys",
|
||||
|
@ -1138,7 +1200,7 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall 0.1.57",
|
||||
|
@ -1748,7 +1810,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"cpuid-bool 0.1.2",
|
||||
"digest",
|
||||
"opaque-debug",
|
||||
|
@ -1806,7 +1868,7 @@ version = "0.3.19"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
@ -1904,13 +1966,28 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "systemd"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f722cabda922e471742300045f56dbaa53fafbb4520fca304e51258019bfe91d"
|
||||
dependencies = [
|
||||
"cstr-argument",
|
||||
"foreign-types 0.5.0",
|
||||
"libc",
|
||||
"libsystemd-sys",
|
||||
"log",
|
||||
"memchr",
|
||||
"utf8-cstr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"rand",
|
||||
"redox_syscall 0.2.4",
|
||||
|
@ -2104,7 +2181,7 @@ version = "0.1.22"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
|
@ -2254,6 +2331,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-cstr"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55bcbb425141152b10d5693095950b51c3745d019363fc2929ffd8f61449b628"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "0.8.2"
|
||||
|
@ -2304,7 +2387,7 @@ version = "0.2.70"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wasm-bindgen-macro",
|
||||
|
@ -2331,7 +2414,7 @@ version = "0.4.20"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3de431a2910c86679c34283a33f66f4e4abd7e0aec27b6669060148872aadf94"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
|
|
|
@ -9,11 +9,13 @@ edition = "2018"
|
|||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
clap = "3.0.0-beta.2"
|
||||
futures = "0.3"
|
||||
tokio = { version = "1", features = [ "full" ] }
|
||||
tracing-subscriber = "0.2"
|
||||
url = { version = "2.2", features = [ "serde" ] }
|
||||
serde_yaml = "0.8"
|
||||
serde = "1.0"
|
||||
systemd = "0.8"
|
||||
thiserror = "1.0"
|
||||
|
||||
[dependencies.matrix-sdk]
|
||||
|
|
78
src/bot.rs
78
src/bot.rs
|
@ -3,11 +3,19 @@ use std::{
|
|||
io::{BufReader, BufWriter},
|
||||
};
|
||||
|
||||
use matrix_sdk::{Client, ClientConfig, Session, SyncSettings};
|
||||
use matrix_sdk::{
|
||||
events::{
|
||||
room::message::{MessageEventContent, TextMessageEventContent},
|
||||
AnyMessageEventContent,
|
||||
},
|
||||
Client, ClientConfig, Session, SyncSettings,
|
||||
};
|
||||
use systemd::{journal, JournalRecord};
|
||||
|
||||
use crate::autojoin::AutoJoinHandler;
|
||||
use crate::Config;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BadNewsBot {
|
||||
client: Client,
|
||||
config: Config,
|
||||
|
@ -46,8 +54,76 @@ impl BadNewsBot {
|
|||
/// [`BadNewsBot::init`] **must** be called before this function, otherwise the [`Client`] isn't
|
||||
/// logged in.
|
||||
pub async fn run(&self) {
|
||||
let clone = self.clone();
|
||||
|
||||
tokio::task::spawn_blocking(move || clone.watch_journald());
|
||||
|
||||
self.client.sync(SyncSettings::default()).await
|
||||
}
|
||||
|
||||
fn watch_journald(&self) {
|
||||
let mut reader = journal::OpenOptions::default()
|
||||
.system(true)
|
||||
.open()
|
||||
.expect("Could not open journal");
|
||||
|
||||
// Seek to end of current log to prevent old messages from being printed
|
||||
reader
|
||||
.seek_tail()
|
||||
.expect("Could not seek to end of journal");
|
||||
|
||||
// HACK: for some reason calling `seek_tail` above still leaves old entries when calling
|
||||
// next, so skip all those before we start the real logging
|
||||
loop {
|
||||
if reader.next().unwrap() == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Ugly double loop, but low level `wait` has to be used if we don't want to miss any
|
||||
// new entry. See https://github.com/jmesmon/rust-systemd/issues/66
|
||||
loop {
|
||||
loop {
|
||||
let record = reader.next_entry().unwrap();
|
||||
match record {
|
||||
Some(record) => self.handle_record(record),
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
reader.wait(None).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_record(&self, record: JournalRecord) {
|
||||
const KEY_UNIT: &str = "_SYSTEMD_UNIT";
|
||||
const KEY_MESSAGE: &str = "MESSAGE";
|
||||
|
||||
if let Some(unit) = record.get(KEY_UNIT) {
|
||||
if !self.config.units.contains(unit) {
|
||||
return;
|
||||
}
|
||||
|
||||
let message = record.get(KEY_MESSAGE);
|
||||
let message = format!(
|
||||
"[{}] {}",
|
||||
unit.strip_suffix(".service").unwrap_or(unit),
|
||||
message.map(|m| m.as_ref()).unwrap_or("<EMPTY MESSAGE>")
|
||||
);
|
||||
let content = AnyMessageEventContent::RoomMessage(MessageEventContent::Text(
|
||||
TextMessageEventContent::plain(message),
|
||||
));
|
||||
let room_id = self.config.room_id.clone();
|
||||
let client_clone = self.client.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
client_clone
|
||||
.room_send(&room_id, content, None)
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This loads the session information from an existing file, and tries to login with it. If no such
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::{
|
||||
collections::HashSet,
|
||||
fs::File,
|
||||
io::{self, BufReader},
|
||||
path::PathBuf,
|
||||
|
@ -32,7 +33,7 @@ struct Opts {
|
|||
}
|
||||
|
||||
/// Holds the configuration for the bot.
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct Config {
|
||||
/// The URL for the homeserver we should connect to
|
||||
homeserver: Url,
|
||||
|
@ -45,6 +46,8 @@ pub struct Config {
|
|||
/// ID of the Matrix room where the bot should post messages. The bot will only accept
|
||||
/// invitations to this room.
|
||||
room_id: RoomId,
|
||||
/// Units to watch for logs
|
||||
units: HashSet<String>,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
|
|
Loading…
Reference in a new issue