Use tracing, split brain by guild, commit to disk
parent
5a76bf4bc1
commit
34fe58d89b
|
@ -3,10 +3,4 @@
|
||||||
/target
|
/target
|
||||||
/.pre-commit-config.yaml
|
/.pre-commit-config.yaml
|
||||||
.env
|
.env
|
||||||
|
buscemi.ron
|
||||||
|
|
||||||
# Added by cargo
|
|
||||||
#
|
|
||||||
# already existing elements were commented out
|
|
||||||
|
|
||||||
#/target
|
|
||||||
|
|
|
@ -3,10 +3,4 @@
|
||||||
/target
|
/target
|
||||||
/.pre-commit-config.yaml
|
/.pre-commit-config.yaml
|
||||||
.env
|
.env
|
||||||
|
buscemi.ron
|
||||||
|
|
||||||
# Added by cargo
|
|
||||||
#
|
|
||||||
# already existing elements were commented out
|
|
||||||
|
|
||||||
#/target
|
|
||||||
|
|
|
@ -17,6 +17,21 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.64"
|
version = "0.1.64"
|
||||||
|
@ -87,9 +102,15 @@ checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||||
name = "buscemi"
|
name = "buscemi"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"poise",
|
"poise",
|
||||||
"rand",
|
"rand",
|
||||||
|
"ron",
|
||||||
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"tracing-forest",
|
||||||
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -123,9 +144,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
|
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
"serde",
|
||||||
|
"time 0.1.45",
|
||||||
|
"wasm-bindgen",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -416,7 +440,7 @@ checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -595,6 +619,12 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.139"
|
version = "0.2.139"
|
||||||
|
@ -629,6 +659,15 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchers"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||||
|
dependencies = [
|
||||||
|
"regex-automata",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
@ -668,10 +707,20 @@ checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"wasi",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nu-ansi-term"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||||
|
dependencies = [
|
||||||
|
"overload",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.45"
|
version = "0.1.45"
|
||||||
|
@ -716,6 +765,12 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "overload"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
@ -860,6 +915,15 @@ dependencies = [
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
dependencies = [
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.28"
|
version = "0.6.28"
|
||||||
|
@ -923,6 +987,17 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ron"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "300a51053b1cb55c80b7a9fde4120726ddf25ca241a1cbb926626f62fb136bff"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.13.1",
|
||||||
|
"bitflags",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.20.8"
|
version = "0.20.8"
|
||||||
|
@ -1056,7 +1131,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde-value",
|
"serde-value",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"time",
|
"time 0.3.20",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"typemap_rev",
|
"typemap_rev",
|
||||||
|
@ -1074,6 +1149,15 @@ dependencies = [
|
||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sharded-slab"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
|
@ -1160,6 +1244,27 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.20"
|
version = "0.3.20"
|
||||||
|
@ -1295,6 +1400,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-forest"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "119324027fc01804d9f83aefb7d80fda2e8fbe7c28e0acc59187cbd751a12915"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"chrono",
|
||||||
|
"serde",
|
||||||
|
"smallvec",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-log"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
|
||||||
|
dependencies = [
|
||||||
|
"matchers",
|
||||||
|
"nu-ansi-term",
|
||||||
|
"once_cell",
|
||||||
|
"regex",
|
||||||
|
"sharded-slab",
|
||||||
|
"smallvec",
|
||||||
|
"thread_local",
|
||||||
|
"tracing",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1396,6 +1548,22 @@ version = "0.7.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "valuable"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
@ -1412,6 +1580,12 @@ dependencies = [
|
||||||
"try-lock",
|
"try-lock",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.10.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
|
|
@ -6,6 +6,12 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.69"
|
||||||
poise = "0.5.2"
|
poise = "0.5.2"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
ron = "0.8.0"
|
||||||
|
serde = { version = "1.0.152", features = ["derive"] }
|
||||||
tokio = { version = "1.25.0", features = ["full"] }
|
tokio = { version = "1.25.0", features = ["full"] }
|
||||||
|
tracing = "0.1.37"
|
||||||
|
tracing-forest = { version = "0.1.5", features = ["full"] }
|
||||||
|
tracing-subscriber = "0.3.16"
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
rust-analyzer
|
rust-analyzer
|
||||||
rustfmt
|
rustfmt
|
||||||
clippy
|
clippy
|
||||||
|
docker-client
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
# this is a hack to force nixpacks on fly.io to build without musl
|
||||||
|
[toolchain]
|
||||||
|
channel = "stable"
|
117
src/commands.rs
117
src/commands.rs
|
@ -1,15 +1,86 @@
|
||||||
use std::{collections::HashMap, sync::Mutex};
|
use std::collections::HashMap;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use anyhow::{Error, Result};
|
||||||
|
use poise::serenity_prelude as serenity;
|
||||||
use rand::seq::SliceRandom;
|
use rand::seq::SliceRandom;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tokio::fs::{File, OpenOptions};
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
/// this is where we keep data for the bot
|
/// a brain stores data for a single guild
|
||||||
// can we eventually serialize this to disk for cheap persistence?
|
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||||
#[derive(Default)]
|
pub struct Brain {
|
||||||
pub struct Data {
|
facts: HashMap<String, String>,
|
||||||
facts: Mutex<HashMap<String, String>>,
|
|
||||||
}
|
}
|
||||||
type Error = Box<dyn std::error::Error + Send + Sync>;
|
|
||||||
type Context<'a> = poise::Context<'a, Data, Error>;
|
/// top level data
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Data {
|
||||||
|
file: Mutex<File>,
|
||||||
|
brain: Mutex<HashMap<serenity::GuildId, Brain>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Data {
|
||||||
|
#[tracing::instrument(fields(path = %path.as_ref().display()))]
|
||||||
|
pub async fn from_path(path: impl AsRef<Path>) -> Result<Data> {
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(&path)
|
||||||
|
.await?;
|
||||||
|
let mut content = String::new();
|
||||||
|
file.read_to_string(&mut content).await?;
|
||||||
|
let brain = if content.is_empty() {
|
||||||
|
tracing::info!("initializing brain at {}", path.as_ref().display());
|
||||||
|
Default::default()
|
||||||
|
} else {
|
||||||
|
let brain = ron::from_str(content.as_str())?;
|
||||||
|
tracing::info!("loaded brain from {}", path.as_ref().display());
|
||||||
|
Mutex::new(brain)
|
||||||
|
};
|
||||||
|
let file = Mutex::new(file);
|
||||||
|
Ok(Data { file, brain })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub async fn commit(&self) -> Result<()> {
|
||||||
|
let mut contents = vec![];
|
||||||
|
self.brain
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.serialize(&mut ron::Serializer::new(
|
||||||
|
&mut contents,
|
||||||
|
Some(Default::default()),
|
||||||
|
)?)?;
|
||||||
|
let mut file = self.file.lock().await;
|
||||||
|
file.set_len(0).await?;
|
||||||
|
file.write_all(&contents).await?;
|
||||||
|
tracing::info!("committed brain to disk");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(f))]
|
||||||
|
async fn with_guild<T>(
|
||||||
|
&self,
|
||||||
|
guild_id: serenity::GuildId,
|
||||||
|
mut f: impl FnMut(&mut Brain) -> T,
|
||||||
|
) -> T {
|
||||||
|
let mut brain = self.brain.lock().await;
|
||||||
|
if let Some(guild) = brain.get_mut(&guild_id) {
|
||||||
|
f(guild)
|
||||||
|
} else {
|
||||||
|
let mut guild = Default::default();
|
||||||
|
let result = f(&mut guild);
|
||||||
|
brain.insert(guild_id, guild);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Context<'a> = poise::Context<'a, Data, Error>;
|
||||||
|
|
||||||
/// all of the commands supported by `buscemi`
|
/// all of the commands supported by `buscemi`
|
||||||
pub fn commands() -> Vec<poise::Command<Data, Error>> {
|
pub fn commands() -> Vec<poise::Command<Data, Error>> {
|
||||||
|
@ -23,14 +94,14 @@ async fn help(
|
||||||
#[description = "optional command to show help about"]
|
#[description = "optional command to show help about"]
|
||||||
#[autocomplete = "poise::builtins::autocomplete_command"]
|
#[autocomplete = "poise::builtins::autocomplete_command"]
|
||||||
command: Option<String>,
|
command: Option<String>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<()> {
|
||||||
poise::builtins::help(ctx, command.as_deref(), Default::default()).await?;
|
poise::builtins::help(ctx, command.as_deref(), Default::default()).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// check that the bot is working
|
/// check that the bot is working
|
||||||
#[poise::command(prefix_command, slash_command)]
|
#[poise::command(prefix_command, slash_command)]
|
||||||
async fn ping(ctx: Context<'_>) -> Result<(), Error> {
|
async fn ping(ctx: Context<'_>) -> Result<()> {
|
||||||
let vowel = {
|
let vowel = {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let vowels = ['a', 'e', 'o', 'u', 'y'];
|
let vowels = ['a', 'e', 'o', 'u', 'y'];
|
||||||
|
@ -48,7 +119,7 @@ async fn eight_ball(
|
||||||
#[rename = "question"]
|
#[rename = "question"]
|
||||||
#[description = "a yes or no question"]
|
#[description = "a yes or no question"]
|
||||||
_question: String,
|
_question: String,
|
||||||
) -> Result<(), Error> {
|
) -> Result<()> {
|
||||||
let answer = {
|
let answer = {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let answers = [
|
let answers = [
|
||||||
|
@ -101,17 +172,19 @@ async fn know(
|
||||||
#[rest]
|
#[rest]
|
||||||
#[description = "the definition of the thing"]
|
#[description = "the definition of the thing"]
|
||||||
is: String,
|
is: String,
|
||||||
) -> Result<(), Error> {
|
) -> Result<()> {
|
||||||
let (that, is) = if that.as_str() == "that" {
|
let (that, is) = if that.as_str() == "that" {
|
||||||
is.split_once(' ').unwrap()
|
is.split_once(' ').unwrap()
|
||||||
} else {
|
} else {
|
||||||
(that.as_str(), is.as_str())
|
(that.as_str(), is.as_str())
|
||||||
};
|
};
|
||||||
let is = is.strip_prefix("is ").unwrap_or(is);
|
let is = is.strip_prefix("is ").unwrap_or(is);
|
||||||
let old = {
|
let old = ctx
|
||||||
let mut facts = ctx.data().facts.lock().unwrap();
|
.data()
|
||||||
facts.insert(that.to_string(), is.to_string())
|
.with_guild(ctx.guild_id().unwrap(), |brain| {
|
||||||
};
|
brain.facts.insert(that.to_string(), is.to_string())
|
||||||
|
})
|
||||||
|
.await;
|
||||||
let message = if let Some(old) = old {
|
let message = if let Some(old) = old {
|
||||||
format!("ok, {that} is {is} (changed from {old})")
|
format!("ok, {that} is {is} (changed from {old})")
|
||||||
} else {
|
} else {
|
||||||
|
@ -128,15 +201,17 @@ async fn what(
|
||||||
#[rest]
|
#[rest]
|
||||||
#[description = "the thing you want to look up"]
|
#[description = "the thing you want to look up"]
|
||||||
is: String,
|
is: String,
|
||||||
) -> Result<(), Error> {
|
) -> Result<()> {
|
||||||
let message = {
|
let message = ctx
|
||||||
let facts = ctx.data().facts.lock().unwrap();
|
.data()
|
||||||
|
.with_guild(ctx.guild_id().unwrap(), |brain| {
|
||||||
let is = is.strip_prefix("is ").unwrap_or(is.as_str());
|
let is = is.strip_prefix("is ").unwrap_or(is.as_str());
|
||||||
facts.get(is).map_or_else(
|
brain.facts.get(is).map_or_else(
|
||||||
|| format!("i don't know what {is} is"),
|
|| format!("i don't know what {is} is"),
|
||||||
|definition| format!("{is} is {definition}"),
|
|definition| format!("{is} is {definition}"),
|
||||||
)
|
)
|
||||||
};
|
})
|
||||||
|
.await;
|
||||||
ctx.say(message).await?;
|
ctx.say(message).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
70
src/main.rs
70
src/main.rs
|
@ -1,23 +1,73 @@
|
||||||
mod commands;
|
mod commands;
|
||||||
|
|
||||||
|
use anyhow::{Error, Result};
|
||||||
use poise::serenity_prelude as serenity;
|
use poise::serenity_prelude as serenity;
|
||||||
|
use tracing_forest::{util::EnvFilter, ForestLayer};
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Registry};
|
||||||
|
|
||||||
|
const DISCORD_TOKEN: &str = "DISCORD_TOKEN";
|
||||||
|
const BUSCEMI_DATA: &str = "BUSCEMI_DATA";
|
||||||
|
const BUSCEMI_DATA_PATH: &str = "./buscemi.ron";
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() -> Result<()> {
|
||||||
|
init_tracing();
|
||||||
|
let framework = init_discord();
|
||||||
|
tracing::info!("it's beneath me. i'm mr. pink. let's move on.");
|
||||||
|
framework.run().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_tracing() {
|
||||||
|
Registry::default()
|
||||||
|
.with(EnvFilter::from_default_env())
|
||||||
|
.with(ForestLayer::default())
|
||||||
|
.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[tracing::instrument(level = "debug")]
|
||||||
|
// async fn pre_command(ctx: commands::Context<'_>) {
|
||||||
|
// // TODO: set up tracing span?
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug")]
|
||||||
|
async fn post_command(ctx: commands::Context<'_>) {
|
||||||
|
ctx.data()
|
||||||
|
.commit()
|
||||||
|
.await
|
||||||
|
.unwrap_or_else(|e| tracing::error!("failed to commit brain to disk: {e}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug")]
|
||||||
|
async fn on_error(error: poise::FrameworkError<'_, commands::Data, Error>) {
|
||||||
|
if let Err(e) = poise::builtins::on_error(error).await {
|
||||||
|
tracing::error!("unhandled error: {e}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_discord() -> poise::FrameworkBuilder<commands::Data, Error> {
|
||||||
let options = poise::FrameworkOptions {
|
let options = poise::FrameworkOptions {
|
||||||
commands: commands::commands(),
|
commands: commands::commands(),
|
||||||
|
// pre_command: |ctx| Box::pin(pre_command(ctx)),
|
||||||
|
post_command: |ctx| Box::pin(post_command(ctx)),
|
||||||
|
on_error: |error| Box::pin(on_error(error)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let framework = poise::Framework::builder()
|
poise::Framework::builder()
|
||||||
.options(options)
|
.options(options)
|
||||||
.token(std::env::var("DISCORD_TOKEN").expect("failed to find DISCORD_TOKEN in env"))
|
.token(std::env::var(DISCORD_TOKEN).expect("failed to find DISCORD_TOKEN in env"))
|
||||||
.intents(serenity::GatewayIntents::non_privileged())
|
.intents(serenity::GatewayIntents::non_privileged())
|
||||||
.setup(|ctx, _ready, framework| {
|
.setup(|ctx, ready, framework| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
|
for guild in &ready.guilds {
|
||||||
Ok(Default::default())
|
poise::builtins::register_in_guild(ctx, &framework.options().commands, guild.id)
|
||||||
})
|
.await
|
||||||
});
|
.unwrap_or_else(|e| tracing::error!("failed to register commands: {e}"))
|
||||||
println!("it's beneath me. i'm mr. pink. let's move on.");
|
}
|
||||||
framework.run().await.unwrap();
|
tracing::debug!("registered commands");
|
||||||
|
let data_path =
|
||||||
|
std::env::var(BUSCEMI_DATA).unwrap_or_else(|_| String::from(BUSCEMI_DATA_PATH));
|
||||||
|
commands::Data::from_path(data_path).await
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue