Skip to content

Commit

Permalink
/update: Automatic main world backup and support for exact version
Browse files Browse the repository at this point in the history
  • Loading branch information
fenhl committed Jan 18, 2025
1 parent 333f0d5 commit 9868c32
Show file tree
Hide file tree
Showing 9 changed files with 1,364 additions and 948 deletions.
2,070 changes: 1,269 additions & 801 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ authors = ["Fenhl <[email protected]>"]
edition = "2021"

[profile.release]
codegen-units = 1
lto = true
strip = true
6 changes: 6 additions & 0 deletions assets/pre-commit.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ if (-not $?)
throw 'Native Failure'
}

cargo +beta check --package=wurstminebot-cli --package=wurstminebot-python
if (-not $?)
{
throw 'Native Failure'
}

# copy the tree to the WSL file system to improve compile times
wsl rsync --delete -av /mnt/c/Users/fenhl/git/github.com/wurstmineberg/wurstminebot-discord/stage/ /home/fenhl/wslgit/github.com/wurstmineberg/wurstminebot-discord/ --exclude target
if (-not $?)
Expand Down
38 changes: 9 additions & 29 deletions crate/wurstminebot-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,16 @@ name = "wurstminebot"
path = "src/main.rs"

[dependencies]
itertools = "0.12"
discord-message-parser = { git = "https://github.com/fenhl/discord-message-parser", branch = "main" }
itertools = "0.14"
minecraft = { git = "https://github.com/wurstmineberg/rust-minecraft-types", branch = "main" }
rand = "0.8"
rcon = "0.6"
serde_json = "1"
serenity = "0.12"

[dependencies.discord-message-parser]
git = "https://github.com/fenhl/discord-message-parser"
branch = "main"

[dependencies.minecraft]
git = "https://github.com/wurstmineberg/rust-minecraft-types"
branch = "main"

[dependencies.serenity-utils]
git = "https://github.com/fenhl/serenity-utils" #TODO publish to crates.io?
branch = "main"

[dependencies.sqlx]
version = "0.7"
features = ["postgres", "runtime-tokio-rustls"]

[dependencies.systemd_minecraft]
git = "https://github.com/wurstmineberg/systemd-minecraft"
branch = "riir"
package = "minecraft"

[dependencies.tokio]
version = "1.3"
features = ["fs", "macros", "parking_lot", "process", "rt-multi-thread", "time"]

[dependencies.wurstminebot]
path = "../wurstminebot"
serenity-utils = { git = "https://github.com/fenhl/serenity-utils", branch = "main" } #TODO publish to crates.io?
sqlx = { version = "0.8", default-features = false, features = ["postgres", "runtime-tokio", "tls-rustls-ring-webpki"] }
systemd_minecraft = { git = "https://github.com/wurstmineberg/systemd-minecraft", branch = "riir", package = "minecraft" }
tokio = { version = "1.3", features = ["fs", "macros", "parking_lot", "process", "rt-multi-thread", "time"] }
wheel = { git = "https://github.com/fenhl/wheel", branch = "main", package = "wheel" }
wurstminebot = { path = "../wurstminebot" }
53 changes: 37 additions & 16 deletions crate/wurstminebot-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use {
process::Command,
time::sleep,
},
wheel::traits::AsyncCommandOutputExt as _,
wurstminebot::{
DEV,
Database,
Expand Down Expand Up @@ -285,7 +286,7 @@ async fn main() -> Result<serenity_utils::Builder, Error> {
let idx = commands.len();
commands.push(CreateCommand::new("iam")
.kind(CommandType::ChatInput)
.dm_permission(false)
.add_context(InteractionContext::Guild)
.description("Give yourself a self-assignable role")
.add_option(CreateCommandOption::new(
CommandOptionType::Role,
Expand All @@ -299,7 +300,7 @@ async fn main() -> Result<serenity_utils::Builder, Error> {
let idx = commands.len();
commands.push(CreateCommand::new("iamn")
.kind(CommandType::ChatInput)
.dm_permission(false)
.add_context(InteractionContext::Guild)
.description("Remove a self-assignable role from yourself")
.add_option(CreateCommandOption::new(
CommandOptionType::Role,
Expand All @@ -313,7 +314,7 @@ async fn main() -> Result<serenity_utils::Builder, Error> {
let idx = commands.len();
commands.push(CreateCommand::new("ping")
.kind(CommandType::ChatInput)
.dm_permission(false)
.add_context(InteractionContext::Guild)
.description("Test if wurstminebot is online")
);
idx
Expand All @@ -322,16 +323,21 @@ async fn main() -> Result<serenity_utils::Builder, Error> {
let idx = commands.len();
commands.push(CreateCommand::new("update")
.kind(CommandType::ChatInput)
.dm_permission(false)
.description("Update Minecraft to the latest release")
.add_context(InteractionContext::Guild)
.description("Update this Minecraft world")
.add_option(CreateCommandOption::new(
CommandOptionType::String,
"version",
"the version to update to, defaults to latest release",
).required(false))
);
idx
};
let veto = {
let idx = commands.len();
commands.push(CreateCommand::new("veto")
.kind(CommandType::ChatInput)
.dm_permission(false)
.add_context(InteractionContext::Guild)
.description("Anonymously veto a Wurstmineberg invite")
.add_option(CreateCommandOption::new(
CommandOptionType::User,
Expand Down Expand Up @@ -405,12 +411,28 @@ async fn main() -> Result<serenity_utils::Builder, Error> {
)).await?;
} else if interaction.data.id == command_ids.update {
if let Some((world_name, _)) = ctx.data.read().await.get::<Config>().expect("missing config").wurstminebot.world_channels.iter().find(|(_, &chan_id)| chan_id == interaction.channel_id) {
//TODO automatic pre-update backup for wurstmineberg world
interaction.create_response(ctx, CreateInteractionResponse::Message(CreateInteractionResponseMessage::new()
.ephemeral(false)
.content(MessageBuilder::default().push("Updating ").push_safe(world_name).push(" world…").build())
)).await?;
let reply = match World::new(world_name).update(VersionSpec::LatestRelease).await { //TODO allow optional args for different version specs?
let version_spec = if let Some(option) = interaction.data.options.get(0) {
match &option.value {
CommandDataOptionValue::String(version) => VersionSpec::Exact(version.clone()),
_ => panic!("unexpected slash command option type"),
}
} else {
VersionSpec::LatestRelease
};
if *world_name == World::default().to_string() {
interaction.create_response(ctx, CreateInteractionResponse::Message(CreateInteractionResponseMessage::new()
.ephemeral(false)
.content(MessageBuilder::default().push("Backing up ").push_safe(world_name).push(" world…").build())
)).await?;
Command::new("/opt/wurstmineberg/bin/wurstminebackup").check("wurstminebackup").await?;
interaction.channel_id.say(ctx, MessageBuilder::default().push("Updating ").push_safe(world_name).push(" world…").build()).await?;
} else {
interaction.create_response(ctx, CreateInteractionResponse::Message(CreateInteractionResponseMessage::new()
.ephemeral(false)
.content(MessageBuilder::default().push("Updating ").push_safe(world_name).push(" world…").build())
)).await?;
}
let reply = match World::new(world_name).update(version_spec).await {
Ok(()) => format!("Done!"),
Err(e) => MessageBuilder::default().push("World update error: ").push_safe(e.to_string()).push(" (").push_mono_safe(format!("{:?}", e)).push(")").build(),
};
Expand Down Expand Up @@ -466,10 +488,9 @@ async fn main() -> Result<serenity_utils::Builder, Error> {
})
.task(|ctx_fut, notify_thread_crash| async move {
// follow the Minecraft log
if let Err(e) = log::handle(ctx_fut).await {
eprintln!("{}", e);
notify_thread_crash(format!("log"), Box::new(e), None).await;
}
let Err(e) = log::handle(ctx_fut).await;
eprintln!("{}", e);
notify_thread_crash(format!("log"), Box::new(e), None).await;
})
.task(|ctx_fut, notify_thread_crash| async move {
// listen for Twitch chat messages
Expand Down
25 changes: 14 additions & 11 deletions crate/wurstminebot-python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@ version.workspace = true
authors.workspace = true
edition.workspace = true

[lints.rust]
rust_2018_idioms = "deny"
unsafe_code = "forbid"
unused = "deny"
unused_crate_dependencies = "deny"
unused_import_braces = "deny"
unused_lifetimes = "deny"
unused_qualifications = "deny"
warnings = "deny"

[lib]
name = "wurstminebot"
crate-type = ["cdylib"]

[dependencies.wurstminebot-ipc]
path = "../wurstminebot-ipc"

[dependencies.pyo3]
version = "0.20"
features = ["extension-module"]

[dependencies.serenity]
version = "0.12"
default-features = false
features = ["model", "rustls_backend", "utils"]
[dependencies]
pyo3 = { version = "0.23", features = ["extension-module"] }
serenity = { version = "0.12", default-features = false, features = ["model", "rustls_backend", "utils"] }
wurstminebot-ipc = { path = "../wurstminebot-ipc" }
17 changes: 7 additions & 10 deletions crate/wurstminebot-python/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#![deny(rust_2018_idioms, unused, unused_crate_dependencies, unused_import_braces, unused_lifetimes, unused_qualifications, warnings)]
#![forbid(unsafe_code)]

use {
pyo3::{
create_exception,
Expand All @@ -15,7 +12,7 @@ use {

create_exception!(wurstminebot, CommandError, pyo3::exceptions::PyRuntimeError);

fn user_to_id(user: &PyAny) -> PyResult<UserId> {
fn user_to_id(user: &Bound<'_, PyAny>) -> PyResult<UserId> {
if let Ok(snowflake) = user.getattr("snowflake") {
// support wurstmineberg_web.models.Person arguments
Ok(UserId::new(snowflake.extract()?))
Expand Down Expand Up @@ -43,16 +40,16 @@ fn user_to_id(user: &PyAny) -> PyResult<UserId> {
.map_err(|e| CommandError::new_err(e.to_string()))
}

#[pyfunction] fn set_display_name(user_id: &PyAny, new_display_name: String) -> PyResult<()> {
#[pyfunction] fn set_display_name(user_id: &Bound<'_, PyAny>, new_display_name: String) -> PyResult<()> {
wurstminebot_ipc::set_display_name(user_to_id(user_id)?, new_display_name)
.map_err(|e| CommandError::new_err(e.to_string()))
}

#[pymodule] fn wurstminebot(_: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(escape))?;
#[pymodule] fn wurstminebot(_: Python<'_>, m: Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(escape, m.clone())?)?;
//TODO make sure that all IPC commands are listed below
m.add_wrapped(wrap_pyfunction!(channel_msg))?;
m.add_wrapped(wrap_pyfunction!(quit))?;
m.add_wrapped(wrap_pyfunction!(set_display_name))?;
m.add_function(wrap_pyfunction!(channel_msg, m.clone())?)?;
m.add_function(wrap_pyfunction!(quit, m.clone())?)?;
m.add_function(wrap_pyfunction!(set_display_name, m.clone())?)?;
Ok(())
}
100 changes: 20 additions & 80 deletions crate/wurstminebot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,91 +15,31 @@ unused_qualifications = "deny"
warnings = "deny"

[dependencies]
async-compression = { version = "0.4", features = ["gzip", "tokio"] }
async_zip = { version = "0.0.17", features = ["full"] }
chase = { git = "https://github.com/fenhl/chase-rs", branch = "wmb" }
chrono = "0.4"
futures = { version = "0.3", features = ["compat"] }
ics = "0.5"
itertools = "0.12"
itertools = "0.14"
lazy-regex = "3"
minecraft = { git = "https://github.com/wurstmineberg/rust-minecraft-types", branch = "main" }
rcon = "0.6"
regex = "1"
reqwest = { version = "0.12", default-features = false, features = ["charset", "hickory-dns", "http2", "macos-system-configuration", "rustls-tls", "stream"] }
rocket = "0.5"
rocket-util = { git = "https://github.com/fenhl/rocket-util", branch = "main", features = ["ics"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1" #TODO make sure enabling the arbitrary_precision feature doesn't break anything
serenity = "0.12"
thiserror = "1"

[dependencies.async-compression]
version = "0.4"
features = ["gzip", "tokio"]

[dependencies.async_zip]
version = "0.0.17"
features = ["full"]

[dependencies.chase]
git = "https://github.com/fenhl/chase-rs"
branch = "wmb"

[dependencies.futures]
version = "0.3"
features = ["compat"]

[dependencies.minecraft]
git = "https://github.com/wurstmineberg/rust-minecraft-types"
branch = "main"

[dependencies.reqwest]
version = "0.12"
default-features = false
features = ["charset", "hickory-dns", "http2", "macos-system-configuration", "rustls-tls", "stream"]

[dependencies.rocket-util]
git = "https://github.com/fenhl/rocket-util"
branch = "main"
features = ["ics"]

[dependencies.serde]
version = "1"
features = ["derive"]

[dependencies.serenity-utils]
git = "https://github.com/fenhl/serenity-utils" #TODO publish to crates.io?
branch = "main"

[dependencies.sqlx]
version = "0.7"
default-features = false
features = ["chrono", "json", "macros", "postgres", "runtime-tokio-rustls"]

[dependencies.systemd_minecraft]
git = "https://github.com/wurstmineberg/systemd-minecraft"
branch = "riir"
package = "minecraft"

[dependencies.tokio]
version = "1.3"
features = ["fs", "macros", "parking_lot", "sync", "rt-multi-thread"]

[dependencies.tokio-stream]
version = "0.1"
features = ["io-util"]

[dependencies.tokio-util]
version = "0.7"
features = ["io"]

[dependencies.twitch-irc]
version = "5"
default-features = false
features = ["transport-tcp-rustls-webpki-roots"]

[dependencies.twitch_helix]
git = "https://github.com/fenhl/rust-twitch-helix" #TODO publish to crates.io
branch = "main"

[dependencies.url]
version = "2"
features = ["serde"]

[dependencies.wheel]
git = "https://github.com/fenhl/wheel"
branch = "main"
features = ["reqwest", "serde", "serde_json"]
serenity-utils = { git = "https://github.com/fenhl/serenity-utils", branch = "main" } #TODO publish to crates.io?
sqlx = { version = "0.8", default-features = false, features = ["chrono", "json", "macros", "postgres", "runtime-tokio", "tls-rustls-ring-webpki"] }
systemd_minecraft = { git = "https://github.com/wurstmineberg/systemd-minecraft", branch = "riir", package = "minecraft" }
thiserror = "2"
tokio = { version = "1.3", features = ["fs", "macros", "parking_lot", "sync", "rt-multi-thread"] }
tokio-stream = { version = "0.1", features = ["io-util"] }
tokio-util = { version = "0.7", features = ["io"] }
twitch-irc = { version = "5", default-features = false, features = ["transport-tcp-rustls-webpki-roots"] }
twitch_helix = { git = "https://github.com/fenhl/rust-twitch-helix", branch = "main" } #TODO publish to crates.io
url = { version = "2", features = ["serde"] }
wheel = { git = "https://github.com/fenhl/wheel", branch = "main", features = ["reqwest", "serde", "serde_json"] }
2 changes: 1 addition & 1 deletion crate/wurstminebot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub fn base_path() -> &'static Path { //TODO make this a constant when stable
pub enum Error {
#[error(transparent)] Envar(#[from] env::VarError),
#[error(transparent)] Io(#[from] io::Error),
#[error(transparent)] Ipc(#[from] crate::ipc::Error),
#[error(transparent)] Ipc(#[from] ipc::Error),
#[error(transparent)] Join(#[from] tokio::task::JoinError),
#[error(transparent)] Json(#[from] serde_json::Error),
#[error(transparent)] Log(#[from] log::Error),
Expand Down

0 comments on commit 9868c32

Please sign in to comment.