feat: use embeds for the message and add startup and shutdown messages!
This commit is contained in:
parent
baef052a4a
commit
aa434ed39b
5 changed files with 99 additions and 17 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
noisebell.service
|
||||||
|
|
|
||||||
12
Cargo.lock
generated
12
Cargo.lock
generated
|
|
@ -1449,9 +1449,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.15.0"
|
version = "1.15.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
|
|
@ -1742,9 +1742,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-attributes"
|
name = "tracing-attributes"
|
||||||
version = "0.1.28"
|
version = "0.1.29"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
|
checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -1753,9 +1753,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-core"
|
name = "tracing-core"
|
||||||
version = "0.1.33"
|
version = "0.1.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
|
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"valuable",
|
"valuable",
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,10 @@ WantedBy=multi-user.target
|
||||||
EOL
|
EOL
|
||||||
|
|
||||||
echo "Copying to Raspberry Pi..."
|
echo "Copying to Raspberry Pi..."
|
||||||
ssh noisebridge@noisebell.local "mkdir -p ~/noisebell"
|
# Stop the service if it's running
|
||||||
|
ssh noisebridge@noisebell.local "sudo systemctl stop noisebell || true"
|
||||||
|
sleep 1
|
||||||
|
# Copy files
|
||||||
scp target/aarch64-unknown-linux-gnu/release/noisebell noisebridge@noisebell.local:~/noisebell/
|
scp target/aarch64-unknown-linux-gnu/release/noisebell noisebridge@noisebell.local:~/noisebell/
|
||||||
scp noisebell.service noisebridge@noisebell.local:~/noisebell/
|
scp noisebell.service noisebridge@noisebell.local:~/noisebell/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::env;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use serenity::prelude::*;
|
use serenity::all::{prelude::*, Color, CreateEmbed, CreateMessage};
|
||||||
use serenity::model::id::ChannelId;
|
use serenity::model::id::ChannelId;
|
||||||
use tracing::{info, error};
|
use tracing::{info, error};
|
||||||
|
|
||||||
|
|
@ -40,9 +40,21 @@ impl DiscordClient {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
info!("Sending Discord message for circuit event: {:?}", event);
|
info!("Sending Discord message for circuit event: {:?}", event);
|
||||||
|
|
||||||
let message = format!("Circuit state changed: {:?}", event);
|
let embed = CreateEmbed::new()
|
||||||
|
.title(format!("Noisebridge is {}!", event))
|
||||||
if let Err(why) = self.channel_id.say(&self.client.http, message).await {
|
.description(match event {
|
||||||
|
crate::gpio::CircuitEvent::Open => "It's time to start hacking.",
|
||||||
|
crate::gpio::CircuitEvent::Closed => "We'll see you again soon.",
|
||||||
|
})
|
||||||
|
.color(match event {
|
||||||
|
crate::gpio::CircuitEvent::Open => Color::new(0x00FF00), // Red for open
|
||||||
|
crate::gpio::CircuitEvent::Closed => Color::new(0xFF0000), // Green for closed
|
||||||
|
}).thumbnail(match event {
|
||||||
|
crate::gpio::CircuitEvent::Open => "https://www.noisebridge.net/images/7/7f/Open.png", // Image that says "Open"
|
||||||
|
crate::gpio::CircuitEvent::Closed => "https://www.noisebridge.net/images/c/c9/Closed.png", // Image that says "Closed"
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Err(why) = self.channel_id.send_message(&self.client.http, CreateMessage::default().add_embed(embed)).await {
|
||||||
error!("Error sending Discord message: {:?}", why);
|
error!("Error sending Discord message: {:?}", why);
|
||||||
return Err(anyhow::anyhow!("Failed to send Discord message: {}", why));
|
return Err(anyhow::anyhow!("Failed to send Discord message: {}", why));
|
||||||
}
|
}
|
||||||
|
|
@ -51,4 +63,44 @@ impl DiscordClient {
|
||||||
info!("Discord message sent successfully in {:?}", duration);
|
info!("Discord message sent successfully in {:?}", duration);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn send_startup_message(&self) -> Result<()> {
|
||||||
|
let start = Instant::now();
|
||||||
|
info!("Sending Discord startup message");
|
||||||
|
|
||||||
|
let embed = CreateEmbed::new()
|
||||||
|
.title("Noisebell is starting up!")
|
||||||
|
.description("The Noisebell service is initializing and will begin monitoring the space status.")
|
||||||
|
.color(Color::new(0xFFA500)) // Orange for startup
|
||||||
|
.thumbnail("https://cats.com/wp-content/uploads/2024/07/Beautiful-red-cat-stretches-and-shows-tongue.jpg");
|
||||||
|
|
||||||
|
if let Err(why) = self.channel_id.send_message(&self.client.http, CreateMessage::default().add_embed(embed)).await {
|
||||||
|
error!("Error sending Discord startup message: {:?}", why);
|
||||||
|
return Err(anyhow::anyhow!("Failed to send Discord startup message: {}", why));
|
||||||
|
}
|
||||||
|
|
||||||
|
let duration = start.elapsed();
|
||||||
|
info!("Discord startup message sent successfully in {:?}", duration);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_shutdown_message(&self) -> Result<()> {
|
||||||
|
let start = Instant::now();
|
||||||
|
info!("Sending Discord shutdown message");
|
||||||
|
|
||||||
|
let embed = CreateEmbed::new()
|
||||||
|
.title("Noisebell is shutting down")
|
||||||
|
.description("The Noisebell service is stopping. Status updates won't go through")
|
||||||
|
.color(Color::new(0x800080)) // Purple for shutdown
|
||||||
|
.thumbnail("https://static.vecteezy.com/system/resources/thumbnails/050/619/685/large/a-laptop-computer-on-fire-on-a-desk-in-a-dark-room-video.jpg");
|
||||||
|
|
||||||
|
if let Err(why) = self.channel_id.send_message(&self.client.http, CreateMessage::default().add_embed(embed)).await {
|
||||||
|
error!("Error sending Discord shutdown message: {:?}", why);
|
||||||
|
return Err(anyhow::anyhow!("Failed to send Discord shutdown message: {}", why));
|
||||||
|
}
|
||||||
|
|
||||||
|
let duration = start.elapsed();
|
||||||
|
info!("Discord shutdown message sent successfully in {:?}", duration);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
38
src/main.rs
38
src/main.rs
|
|
@ -3,6 +3,7 @@ mod discord;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
|
|
@ -10,6 +11,22 @@ use tracing_appender::rolling::{RollingFileAppender, Rotation};
|
||||||
use tracing_subscriber::filter::LevelFilter;
|
use tracing_subscriber::filter::LevelFilter;
|
||||||
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
|
struct ShutdownGuard {
|
||||||
|
discord_client: Arc<discord::DiscordClient>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for ShutdownGuard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
info!("Shutdown guard triggered");
|
||||||
|
let runtime = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
runtime.block_on(async {
|
||||||
|
if let Err(e) = self.discord_client.send_shutdown_message().await {
|
||||||
|
error!("Failed to send shutdown message: {}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
info!("creating logs directory");
|
info!("creating logs directory");
|
||||||
|
|
@ -39,18 +56,27 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
info!("initializing Discord client");
|
info!("initializing Discord client");
|
||||||
let discord_client = discord::DiscordClient::new().await?;
|
let discord_client = discord::DiscordClient::new().await?;
|
||||||
|
let discord_client = Arc::new(discord_client);
|
||||||
|
|
||||||
|
// Create shutdown guard that will send message on any exit
|
||||||
|
let _guard = ShutdownGuard {
|
||||||
|
discord_client: Arc::clone(&discord_client),
|
||||||
|
};
|
||||||
|
|
||||||
|
discord_client.send_startup_message().await?;
|
||||||
|
|
||||||
const DEFAULT_GPIO_PIN: u8 = 17;
|
const DEFAULT_GPIO_PIN: u8 = 17;
|
||||||
|
|
||||||
info!("initializing gpio monitor");
|
info!("initializing gpio monitor");
|
||||||
let mut gpio_monitor = gpio::GpioMonitor::new(DEFAULT_GPIO_PIN, Duration::from_millis(100))?;
|
let mut gpio_monitor = gpio::GpioMonitor::new(DEFAULT_GPIO_PIN, Duration::from_millis(100))?;
|
||||||
|
|
||||||
let discord_client = std::sync::Arc::new(discord_client);
|
// Send initial state
|
||||||
let discord_client_clone = discord_client.clone();
|
discord_client.clone().send_circuit_event(&gpio_monitor.get_current_state()).await?;
|
||||||
|
|
||||||
|
// Set up the callback for state changes
|
||||||
let callback = move |event: gpio::CircuitEvent| {
|
let callback = move |event: gpio::CircuitEvent| {
|
||||||
info!("Circuit state changed: {:?}", event);
|
info!("Circuit state changed to: {:?}", event);
|
||||||
let discord_client = discord_client_clone.clone();
|
let discord_client = discord_client.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(e) = discord_client.send_circuit_event(&event).await {
|
if let Err(e) = discord_client.send_circuit_event(&event).await {
|
||||||
error!("Failed to send Discord message: {}", e);
|
error!("Failed to send Discord message: {}", e);
|
||||||
|
|
@ -58,10 +84,10 @@ async fn main() -> Result<()> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("starting GPIO monitor");
|
// Start monitoring - this will block until an error occurs
|
||||||
|
|
||||||
if let Err(e) = gpio_monitor.monitor(callback).await {
|
if let Err(e) = gpio_monitor.monitor(callback).await {
|
||||||
error!("GPIO monitoring error: {}", e);
|
error!("GPIO monitoring error: {}", e);
|
||||||
|
return Err(anyhow::anyhow!("GPIO monitoring failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue