diff --git a/Cargo.lock b/Cargo.lock index 7920ea2..88f3a0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -972,7 +972,7 @@ dependencies = [ [[package]] name = "kon" -version = "0.3.0" +version = "0.3.1" dependencies = [ "bb8", "bb8-postgres", @@ -980,6 +980,7 @@ dependencies = [ "once_cell", "os_info", "poise", + "regex", "reqwest 0.12.5", "serde", "serde_json", @@ -1350,11 +1351,11 @@ dependencies = [ [[package]] name = "postgres-protocol" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" +checksum = "acda0ebdebc28befa84bee35e651e4c5f09073d668c7aed4cf7e23c3cda84b23" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "byteorder", "bytes", "fallible-iterator", @@ -1368,9 +1369,9 @@ dependencies = [ [[package]] name = "postgres-types" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2234cdee9408b523530a9b6d2d6b373d1db34f6a8e51dc03ded1828d7fb67c" +checksum = "02048d9e032fb3cc3413bbf7b83a15d84a5d419778e2628751896d856498eee9" dependencies = [ "bytes", "fallible-iterator", @@ -1494,9 +1495,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -2218,9 +2219,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d340244b32d920260ae7448cb72b6e238bddc3d4f7603394e7dd46ed8e48f5b8" +checksum = "03adcf0147e203b6032c0b2d30be1415ba03bc348901f3ff1cc0df6a733e60c3" dependencies = [ "async-trait", "byteorder", diff --git a/Cargo.toml b/Cargo.toml index 3f3d959..8d6b107 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kon" -version = "0.3.0" +version = "0.3.1" edition = "2021" [dependencies] @@ -10,13 +10,14 @@ cargo_toml = "0.20.4" once_cell = "1.19.0" os_info = "3.8.2" poise = "0.6.1" +regex = "1.10.5" reqwest = { version = "0.12.5", features = ["json"] } serde = "1.0.204" serde_json = "1.0.120" sysinfo = "0.30.13" tokenservice-client = { version = "0.3.2", registry = "gitea" } tokio = { version = "1.38.1", features = ["macros", "signal", "rt-multi-thread"] } -tokio-postgres = "0.7.10" +tokio-postgres = "0.7.11" uptime_lib = "0.3.1" [features] diff --git a/Dockerfile b/Dockerfile index 3c188df..e1a5932 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ COPY . . RUN cargo build -rF production FROM alpine:3.20 -RUN apk add --no-cache libgcc +RUN apk add --no-cache libgcc fluidsynth WORKDIR /kon COPY --from=builder /usr/src/kon/target/release/kon . CMD [ "./kon" ] diff --git a/src/commands.rs b/src/commands.rs index 2cd38c3..8f6a068 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,3 +1,4 @@ pub mod ping; pub mod status; +pub mod midi; pub mod uptime; diff --git a/src/commands/midi.rs b/src/commands/midi.rs new file mode 100644 index 0000000..6dd12b5 --- /dev/null +++ b/src/commands/midi.rs @@ -0,0 +1,78 @@ +use crate::{ + Error, + internals::http::HttpClient +}; + +use regex::Regex; +use std::fs::{ + write, + read_to_string, + remove_file +}; +use poise::{ + CreateReply, + serenity_prelude::CreateAttachment +}; + +/// Convert MIDI file to WAV +#[poise::command(context_menu_command = "MIDI -> WAV")] +pub async fn midi_to_wav( + ctx: poise::Context<'_, (), Error>, + #[description = "MIDI file to be converted"] message: poise::serenity_prelude::Message +) -> Result<(), Error> { + ctx.defer().await?; + + let http = HttpClient::new(); + let resp = http.get(&message.attachments[0].url, "MIDI Conversion").await?; + let bytes = resp.bytes().await?; + + let midi_path = &message.attachments[0].filename; + write(midi_path, bytes)?; + + let re = Regex::new(r"(?i)\.mid$").unwrap(); + + let wav_path = re.replace(&midi_path, ".wav"); + + let alpine_sf2 = include_bytes!("../internals/assets/FluidR3_GM.sf2"); + let sf2_path = if let Ok(os_release) = read_to_string("/etc/os-release") { + if os_release.contains("Alpine") { + let sf2_path = "/tmp/FluidR3_GM.sf2"; + write(sf2_path, alpine_sf2)?; + sf2_path + } else { + "/usr/share/sounds/sf2/FluidR3_GM.sf2" + } + } else { + return Err(Error::from("Couldn't read \"/etc/os-release\" file!")) + }; + + let output = std::process::Command::new("fluidsynth") + .args(&[ + "-ni", sf2_path, midi_path, "-F", &wav_path + ]) + .output(); + + match output { + Ok(_) => { + ctx.send(CreateReply::default() + .attachment(CreateAttachment::path(&*wav_path).await.unwrap()) + ).await.expect("Reply failed"); + + remove_file(midi_path)?; + remove_file(&*wav_path)?; + }, + Err(y) => { + ctx.send(CreateReply::default() + .content("Command didn't execute successfully, check console for more information!") + ) + .await.unwrap(); + + return Err(Error::from(format!( + "Midi conversion failed: {}", + y + ))) + } + } + + Ok(()) +} diff --git a/src/internals/assets/FluidR3_GM.sf2 b/src/internals/assets/FluidR3_GM.sf2 new file mode 100644 index 0000000..443d42b Binary files /dev/null and b/src/internals/assets/FluidR3_GM.sf2 differ diff --git a/src/main.rs b/src/main.rs index 975ec36..cbd954a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -98,6 +98,7 @@ async fn main() { commands: vec![ commands::ping::ping(), commands::status::status(), + commands::midi::midi_to_wav(), commands::uptime::uptime() ], pre_command: |ctx| Box::pin(async move {