add discord membercount service & endpoint
a background worker is added that sends an approximate member count request every 60 seconds, caches it into memory, and serves the cache on a public endpoint
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::discordbot::MAIN_GUILD_ID;
|
||||||
use chrono::{Datelike, Utc};
|
use chrono::{Datelike, Utc};
|
||||||
use chrono_tz::Europe::Warsaw;
|
use chrono_tz::Europe::Warsaw;
|
||||||
use rand::{SeedableRng, seq::IndexedRandom};
|
use rand::{SeedableRng, seq::IndexedRandom};
|
||||||
@@ -21,8 +22,6 @@ pub fn init_service(ctx: &Context, guild_id: &GuildId) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAIN_GUILD_ID: GuildId = GuildId::new(447075692664979466);
|
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Normal,
|
Normal,
|
||||||
PolskaGórą,
|
PolskaGórą,
|
||||||
|
|||||||
22
src/discordbot/member_count/mod.rs
Normal file
22
src/discordbot/member_count/mod.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
use crate::discordbot::MAIN_GUILD_ID;
|
||||||
|
use serenity::all::{Context, GuildId};
|
||||||
|
use service::run_membercount_service;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
mod service;
|
||||||
|
|
||||||
|
pub use service::get_member_count;
|
||||||
|
|
||||||
|
pub fn init_service(ctx: &Context, guild_id: &GuildId) {
|
||||||
|
let (ctx, guild_id) = (ctx.clone(), guild_id.clone());
|
||||||
|
info!("Initialising discord member count service...");
|
||||||
|
|
||||||
|
if guild_id != MAIN_GUILD_ID {
|
||||||
|
info!("Guild member count service not initialised; Bot not running on main guild.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
run_membercount_service(ctx, guild_id).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
33
src/discordbot/member_count/service.rs
Normal file
33
src/discordbot/member_count/service.rs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
use serenity::all::{Context, GuildId};
|
||||||
|
use std::{
|
||||||
|
sync::{Arc, LazyLock},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
use tokio::{sync::RwLock, time::sleep};
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
static MEMBER_COUNT: LazyLock<Arc<RwLock<Option<u64>>>> =
|
||||||
|
LazyLock::new(|| Arc::new(RwLock::new(None)));
|
||||||
|
|
||||||
|
pub async fn run_membercount_service(ctx: Context, guild_id: GuildId) {
|
||||||
|
loop {
|
||||||
|
update_member_count(&ctx, guild_id).await;
|
||||||
|
sleep(Duration::from_secs(60)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_member_count() -> Option<u64> {
|
||||||
|
*MEMBER_COUNT.read().await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_member_count(ctx: &Context, guild_id: GuildId) {
|
||||||
|
let count = match ctx.http.get_guild_with_counts(guild_id).await {
|
||||||
|
Ok(guild) => guild.approximate_member_count,
|
||||||
|
Err(e) => {
|
||||||
|
error!("Could not fetch guild member count: {e}");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut member_count = MEMBER_COUNT.write().await;
|
||||||
|
*member_count = count;
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
use serenity::{
|
use serenity::{
|
||||||
all::{CreateInteractionResponse, CreateInteractionResponseMessage, Interaction, Ready},
|
all::{
|
||||||
|
CreateInteractionResponse, CreateInteractionResponseMessage, GuildId, Interaction, Ready,
|
||||||
|
},
|
||||||
async_trait,
|
async_trait,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
@@ -12,8 +14,12 @@ struct Handler;
|
|||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
mod events;
|
mod events;
|
||||||
|
mod member_count;
|
||||||
mod status;
|
mod status;
|
||||||
|
|
||||||
|
const MAIN_GUILD_ID: GuildId = GuildId::new(447075692664979466);
|
||||||
|
pub use member_count::get_member_count;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EventHandler for Handler {
|
impl EventHandler for Handler {
|
||||||
async fn ready(&self, ctx: Context, ready: Ready) {
|
async fn ready(&self, ctx: Context, ready: Ready) {
|
||||||
@@ -37,6 +43,7 @@ impl EventHandler for Handler {
|
|||||||
|
|
||||||
status::init_service(&ctx);
|
status::init_service(&ctx);
|
||||||
events::init_service(&ctx, &guild_id);
|
events::init_service(&ctx, &guild_id);
|
||||||
|
member_count::init_service(&ctx, &guild_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
|
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
use axum::{Router, routing::get};
|
use axum::{Router, http::StatusCode, routing::get};
|
||||||
|
|
||||||
pub fn init() -> Router {
|
pub fn init() -> Router {
|
||||||
Router::new().route("/", get(async || "root"))
|
Router::new()
|
||||||
|
.route("/", get(async || "root"))
|
||||||
|
.route("/discord/member-count", get(get_member_count))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_member_count() -> (StatusCode, String) {
|
||||||
|
match crate::discordbot::get_member_count().await {
|
||||||
|
Some(count) => (StatusCode::OK, format!("{count}")),
|
||||||
|
None => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!("An error occured - could not fetch discord member count."),
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user