Report bot stats to top.gg

This commit is contained in:
2026-02-15 17:56:35 -03:00
parent a0c0c17747
commit 5dd8fdcc58
8 changed files with 192 additions and 51 deletions
+64 -1
View File
@@ -1,7 +1,8 @@
use std::{fmt::Debug, sync::Arc};
use std::{fmt::Debug, sync::Arc, time::Duration};
use async_trait::async_trait;
use thiserror::Error;
use topgg::Stats;
use twilight_cache_inmemory::{DefaultInMemoryCache, ResourceType};
use twilight_gateway::{ConfigBuilder, Event, EventTypeFlags, Intents, Shard, ShardId, StreamExt};
use twilight_http::Client;
@@ -113,6 +114,7 @@ pub struct Bot<S: Send + Sync, E: Send + Sync = ()> {
on_server_create_handlers: Vec<Arc<dyn OnServerCreateHandler<S, E>>>,
on_server_update_handlers: Vec<Arc<dyn OnServerUpdateHandler<S, E>>>,
on_server_delete_handlers: Vec<Arc<dyn OnServerDeleteHandler<S, E>>>,
topgg_token: Option<String>,
}
impl<T, E> Bot<T, E>
@@ -145,6 +147,7 @@ where
on_server_create_handlers: Vec::new(),
on_server_update_handlers: Vec::new(),
on_server_delete_handlers: Vec::new(),
topgg_token: None,
}
}
@@ -173,6 +176,7 @@ where
self
}
#[allow(dead_code)]
pub fn task(mut self, task: impl Task<T, E> + 'static) -> Self {
self.tasks.push(Arc::new(task));
self
@@ -237,6 +241,11 @@ where
self
}
pub fn topgg_token(mut self, token: impl ToString) -> Self {
self.topgg_token = Some(token.to_string());
self
}
pub async fn run(self, token: &str) -> Result<(), RuntimeError> {
let http = Client::new(token.to_string());
let app = http
@@ -248,6 +257,60 @@ where
.await
.inspect_err(|e| log::error!("Could not parse application data! {e:?}"))
.map_err(|_| RuntimeError::ApplicationFetchingFailed)?;
if let Some(topgg_token) = &self.topgg_token
&& self.shard.number() == 0
{
let topgg_token = topgg_token.clone();
let http = Client::new(token.to_string());
tokio::spawn(async move {
let topgg_client = topgg::Client::new(topgg_token);
loop {
let app = match http
.current_user_application()
.await
.map_err(|_| RuntimeError::ApplicationFetchingFailed)
{
Ok(v) => {
match v
.model()
.await
.map_err(|_| RuntimeError::ApplicationFetchingFailed)
{
Ok(app) => app,
Err(err) => {
log::warn!(
"Could not parse application data, skipping stats post to Top.gg! {err:?}"
);
continue;
}
}
}
Err(err) => {
log::warn!(
"Could not fetch application data, skipping stats post to Top.gg! {err:?}"
);
continue;
}
};
topgg_client
.post_stats(Stats::from_count(
app.approximate_guild_count.unwrap() as usize,
Some(self.shard.total() as usize),
))
.await
.inspect_err(|err| {
log::warn!("Could not report bot stats to Top.gg: {err}")
})
.ok();
tokio::time::sleep(Duration::from_secs(120)).await;
}
});
}
let registry = ComponentRegistry::new();
for component in &self.components {