feat: reorganize with remote
This commit is contained in:
parent
a74e5753fa
commit
dc7b8cbadd
28 changed files with 622 additions and 3024 deletions
|
|
@ -1,34 +1,22 @@
|
|||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use axum::extract::State;
|
||||
use axum::http::{HeaderMap, StatusCode};
|
||||
use axum::routing::post;
|
||||
use axum::routing::{get, post};
|
||||
use axum::{Json, Router};
|
||||
use serde::Deserialize;
|
||||
use serenity::all::{ChannelId, Colour, CreateEmbed, CreateMessage, GatewayIntents, Http};
|
||||
use tracing::{error, info};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct WebhookPayload {
|
||||
status: String,
|
||||
timestamp: u64,
|
||||
}
|
||||
use noisebell_common::{validate_bearer, WebhookPayload};
|
||||
use serenity::all::{ChannelId, Colour, CreateEmbed, CreateMessage, GatewayIntents};
|
||||
use tower_http::trace::TraceLayer;
|
||||
use tracing::{error, info, Level};
|
||||
|
||||
struct AppState {
|
||||
http: Arc<Http>,
|
||||
http: Arc<serenity::all::Http>,
|
||||
channel_id: ChannelId,
|
||||
webhook_secret: String,
|
||||
}
|
||||
|
||||
fn validate_bearer(headers: &HeaderMap, expected: &str) -> bool {
|
||||
headers
|
||||
.get("authorization")
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.map(|v| v.strip_prefix("Bearer ").unwrap_or("") == expected)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn build_embed(status: &str, timestamp: u64) -> CreateEmbed {
|
||||
let (colour, title, description) = match status {
|
||||
"open" => (Colour::from_rgb(87, 242, 135), "Door is open", "The door at Noisebridge is open."),
|
||||
|
|
@ -98,12 +86,12 @@ async fn main() -> Result<()> {
|
|||
info!(port, channel_id, "starting noisebell-discord");
|
||||
|
||||
let intents = GatewayIntents::empty();
|
||||
let mut client = serenity::Client::builder(&discord_token, intents)
|
||||
let mut initial_client = serenity::Client::builder(&discord_token, intents)
|
||||
.event_handler(Handler)
|
||||
.await
|
||||
.context("failed to create Discord client")?;
|
||||
|
||||
let http = client.http.clone();
|
||||
let http = initial_client.http.clone();
|
||||
|
||||
let app_state = Arc::new(AppState {
|
||||
http,
|
||||
|
|
@ -112,7 +100,13 @@ async fn main() -> Result<()> {
|
|||
});
|
||||
|
||||
let app = Router::new()
|
||||
.route("/health", get(|| async { StatusCode::OK }))
|
||||
.route("/webhook", post(post_webhook))
|
||||
.layer(
|
||||
TraceLayer::new_for_http()
|
||||
.make_span_with(tower_http::trace::DefaultMakeSpan::new().level(Level::INFO))
|
||||
.on_response(tower_http::trace::DefaultOnResponse::new().level(Level::INFO)),
|
||||
)
|
||||
.with_state(app_state);
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(("0.0.0.0", port))
|
||||
|
|
@ -121,21 +115,39 @@ async fn main() -> Result<()> {
|
|||
|
||||
info!(port, "webhook listener ready");
|
||||
|
||||
// Gateway reconnect loop — the Http client for sending messages is independent
|
||||
let token_for_gateway = discord_token.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = initial_client.start().await {
|
||||
error!(error = %e, "Discord gateway disconnected");
|
||||
}
|
||||
loop {
|
||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||
info!("reconnecting to Discord gateway");
|
||||
match serenity::Client::builder(&token_for_gateway, GatewayIntents::empty())
|
||||
.event_handler(Handler)
|
||||
.await
|
||||
{
|
||||
Ok(mut client) => {
|
||||
if let Err(e) = client.start().await {
|
||||
error!(error = %e, "Discord gateway disconnected");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!(error = %e, "failed to create Discord client");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mut sigterm = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
|
||||
.context("failed to register SIGTERM handler")?;
|
||||
|
||||
tokio::select! {
|
||||
result = client.start() => {
|
||||
if let Err(e) = result {
|
||||
error!(error = %e, "Discord client error");
|
||||
}
|
||||
}
|
||||
result = axum::serve(listener, app).with_graceful_shutdown(async move { sigterm.recv().await; }) => {
|
||||
if let Err(e) = result {
|
||||
error!(error = %e, "HTTP server error");
|
||||
}
|
||||
}
|
||||
}
|
||||
axum::serve(listener, app)
|
||||
.with_graceful_shutdown(async move {
|
||||
sigterm.recv().await;
|
||||
})
|
||||
.await
|
||||
.context("server error")?;
|
||||
|
||||
info!("shutdown complete");
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue