feat: send events from gateway to bot over http

This commit is contained in:
alyssa 2025-04-04 11:06:16 +00:00
parent a72afb35a0
commit 2578eb0e3c
8 changed files with 134 additions and 15 deletions

View file

@ -13,6 +13,7 @@ futures = { workspace = true }
lazy_static = { workspace = true }
libpk = { path = "../libpk" }
metrics = { workspace = true }
reqwest = { workspace = true }
serde_json = { workspace = true }
signal-hook = { workspace = true }
tokio = { workspace = true }

View file

@ -1,7 +1,8 @@
use futures::StreamExt;
use libpk::_config::ClusterSettings;
use libpk::{_config::ClusterSettings, runtime_config::RuntimeConfig};
use metrics::counter;
use std::sync::{mpsc::Sender, Arc};
use std::sync::Arc;
use tokio::sync::mpsc::Sender;
use tracing::{error, info, warn};
use twilight_gateway::{
create_iterator, ConfigBuilder, Event, EventTypeFlags, Message, Shard, ShardId,
@ -12,7 +13,10 @@ use twilight_model::gateway::{
Intents,
};
use crate::discord::identify_queue::{self, RedisQueue};
use crate::{
discord::identify_queue::{self, RedisQueue},
RUNTIME_CONFIG_KEY_EVENT_TARGET,
};
use super::{cache::DiscordCache, shard_state::ShardStateManager};
@ -78,13 +82,20 @@ pub fn create_shards(redis: fred::clients::RedisPool) -> anyhow::Result<Vec<Shar
pub async fn runner(
mut shard: Shard<RedisQueue>,
_tx: Sender<(ShardId, String)>,
tx: Sender<(ShardId, String)>,
shard_state: ShardStateManager,
cache: Arc<DiscordCache>,
runtime_config: Arc<RuntimeConfig>,
) {
// let _span = info_span!("shard_runner", shard_id = shard.id().number()).entered();
let shard_id = shard.id().number();
let our_user_id = libpk::config
.discord
.as_ref()
.expect("missing discord config")
.client_id;
info!("waiting for events");
while let Some(item) = shard.next().await {
let raw_event = match item {
@ -165,7 +176,28 @@ pub async fn runner(
cache.0.update(&event);
// okay, we've handled the event internally, let's send it to consumers
// tx.send((shard.id(), raw_event)).unwrap();
// some basic filtering here is useful
// we can't use if matching using the | operator, so anything matched does nothing
// and the default match skips the next block (continues to the next event)
match event {
Event::InteractionCreate(_) => {}
Event::MessageCreate(m) if m.author.id != our_user_id => {}
Event::MessageUpdate(m)
if let Some(author) = m.author.clone()
&& author.id != our_user_id
&& !author.bot => {}
Event::MessageDelete(_) => {}
Event::MessageDeleteBulk(_) => {}
Event::ReactionAdd(r) if r.user_id != our_user_id => {}
_ => {
continue;
}
}
if runtime_config.exists(RUNTIME_CONFIG_KEY_EVENT_TARGET).await {
tx.send((shard.id(), raw_event)).await.unwrap();
}
}
}

View file

@ -5,6 +5,7 @@ use chrono::Timelike;
use discord::gateway::cluster_config;
use fred::{clients::RedisPool, interfaces::*};
use libpk::runtime_config::RuntimeConfig;
use reqwest::ClientBuilder;
use signal_hook::{
consts::{SIGINT, SIGTERM},
iterator::Signals,
@ -15,7 +16,7 @@ use std::{
vec::Vec,
};
use tokio::task::JoinSet;
use tracing::{info, warn};
use tracing::{error, info, warn};
use twilight_gateway::{MessageSender, ShardId};
use twilight_model::gateway::payload::outgoing::UpdatePresence;
@ -23,6 +24,8 @@ mod cache_api;
mod discord;
mod logger;
const RUNTIME_CONFIG_KEY_EVENT_TARGET: &'static str = "event_target";
libpk::main!("gateway");
async fn real_main() -> anyhow::Result<()> {
let (shutdown_tx, shutdown_rx) = channel::<()>();
@ -57,9 +60,40 @@ async fn real_main() -> anyhow::Result<()> {
event_tx.clone(),
shard_state.clone(),
cache.clone(),
runtime_config.clone(),
)));
}
set.spawn(tokio::spawn({
let runtime_config = runtime_config.clone();
async move {
let client = Arc::new(ClientBuilder::new()
.connect_timeout(Duration::from_secs(1))
.timeout(Duration::from_secs(1))
.build()
.expect("error making client"));
while let Some((shard_id, event)) = event_rx.recv().await {
let target = runtime_config.get(RUNTIME_CONFIG_KEY_EVENT_TARGET).await;
if let Some(target) = target {
tokio::spawn({
let client = client.clone();
async move {
if let Err(error) = client
.post(format!("{target}/{}", shard_id.number()))
.body(event)
.send()
.await
{
error!(error = ?error, "failed to request event target")
}
}
});
}
}
}
}));
set.spawn(tokio::spawn(
async move { scheduled_task(redis, senders).await },
));

View file

@ -43,6 +43,7 @@ pub fn init_logging(component: &str) {
tracing_subscriber::registry()
.with(sentry_layer)
.with(tracing_subscriber::fmt::layer())
.with(EnvFilter::from_default_env())
.init();
}
}

View file

@ -33,7 +33,7 @@ impl RuntimeConfig {
settings.insert(key, value);
}
info!("starting with runtime config: {:?}", self.settings);
info!("starting with runtime config: {:?}", settings);
Ok(())
}
@ -58,8 +58,8 @@ impl RuntimeConfig {
Ok(())
}
pub async fn get(&self, key: String) -> Option<String> {
self.settings.read().await.get(&key).cloned()
pub async fn get(&self, key: &str) -> Option<String> {
self.settings.read().await.get(key).cloned()
}
pub async fn exists(&self, key: &str) -> bool {