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
Generated
+65 -30
View File
@@ -438,6 +438,7 @@ dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
"serde",
"windows-link",
]
@@ -1161,7 +1162,7 @@ dependencies = [
"hyper-util",
"rustls",
"rustls-pki-types",
"rustls-platform-verifier 0.6.1",
"rustls-platform-verifier 0.6.2",
"tokio",
"tokio-rustls",
"tower-service",
@@ -1755,7 +1756,7 @@ dependencies = [
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-probe 0.1.6",
"openssl-sys",
"schannel",
"security-framework 2.11.1",
@@ -1948,6 +1949,12 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-probe"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
[[package]]
name = "openssl-src"
version = "300.5.5+3.5.5"
@@ -2006,7 +2013,7 @@ checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]]
name = "payphone"
version = "4.4.18"
version = "4.4.19"
dependencies = [
"anyhow",
"async-trait",
@@ -2037,11 +2044,12 @@ dependencies = [
"thiserror 2.0.12",
"time",
"tokio",
"topgg",
"tower-http",
"twilight-cache-inmemory",
"twilight-gateway",
"twilight-http",
"twilight-model",
"twilight-model 0.16.0",
"twilight-util",
"twilight-validate",
"unicode-segmentation",
@@ -2341,18 +2349,18 @@ dependencies = [
[[package]]
name = "ref-cast"
version = "1.0.24"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf"
checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
dependencies = [
"ref-cast-impl",
]
[[package]]
name = "ref-cast-impl"
version = "1.0.24"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [
"proc-macro2",
"quote",
@@ -2489,14 +2497,14 @@ dependencies = [
[[package]]
name = "rustls-native-certs"
version = "0.8.1"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3"
checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63"
dependencies = [
"openssl-probe",
"openssl-probe 0.2.1",
"rustls-pki-types",
"schannel",
"security-framework 3.2.0",
"security-framework 3.6.0",
]
[[package]]
@@ -2523,7 +2531,7 @@ dependencies = [
"rustls-native-certs",
"rustls-platform-verifier-android",
"rustls-webpki",
"security-framework 3.2.0",
"security-framework 3.6.0",
"security-framework-sys",
"webpki-root-certs 0.26.11",
"windows-sys 0.59.0",
@@ -2531,9 +2539,9 @@ dependencies = [
[[package]]
name = "rustls-platform-verifier"
version = "0.6.1"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be59af91596cac372a6942530653ad0c3a246cdd491aaa9dcaee47f88d67d5a0"
checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784"
dependencies = [
"core-foundation 0.10.1",
"core-foundation-sys",
@@ -2544,10 +2552,10 @@ dependencies = [
"rustls-native-certs",
"rustls-platform-verifier-android",
"rustls-webpki",
"security-framework 3.2.0",
"security-framework 3.6.0",
"security-framework-sys",
"webpki-root-certs 1.0.2",
"windows-sys 0.59.0",
"webpki-root-certs 1.0.6",
"windows-sys 0.60.2",
]
[[package]]
@@ -2691,9 +2699,9 @@ dependencies = [
[[package]]
name = "security-framework"
version = "3.2.0"
version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38"
dependencies = [
"bitflags 2.9.1",
"core-foundation 0.10.1",
@@ -2704,9 +2712,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.14.0"
version = "2.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a"
dependencies = [
"core-foundation-sys",
"libc",
@@ -3197,6 +3205,20 @@ dependencies = [
"winnow",
]
[[package]]
name = "topgg"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ed67b6c13c05e039e1239c421b8e658b1fff440376311bb81473bf86efbca10"
dependencies = [
"cfg-if",
"chrono",
"reqwest",
"serde",
"serde_json",
"twilight-model 0.15.4",
]
[[package]]
name = "tower"
version = "0.5.2"
@@ -3300,7 +3322,7 @@ dependencies = [
"bitflags 2.9.1",
"dashmap",
"serde",
"twilight-model",
"twilight-model 0.16.0",
"twilight-util",
]
@@ -3322,7 +3344,7 @@ dependencies = [
"tracing",
"twilight-gateway-queue",
"twilight-http",
"twilight-model",
"twilight-model 0.16.0",
]
[[package]]
@@ -3356,7 +3378,7 @@ dependencies = [
"tokio",
"tracing",
"twilight-http-ratelimiting",
"twilight-model",
"twilight-model 0.16.0",
"twilight-validate",
]
@@ -3370,6 +3392,19 @@ dependencies = [
"tracing",
]
[[package]]
name = "twilight-model"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "276bd50f4817b3b421395afac89f5d7b61fdfd0f00a28b2a7db983e4878b4a1a"
dependencies = [
"bitflags 1.3.2",
"serde",
"serde-value",
"serde_repr",
"time",
]
[[package]]
name = "twilight-model"
version = "0.16.0"
@@ -3389,7 +3424,7 @@ version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5777d71286611c1639021f5f6e6b40300eb8da278449ac1cf6da01c94053425"
dependencies = [
"twilight-model",
"twilight-model 0.16.0",
"twilight-validate",
]
@@ -3399,7 +3434,7 @@ version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f8d106028ede53708526364b03318bbf846babe146e3ff9e39821a0ca25ff4"
dependencies = [
"twilight-model",
"twilight-model 0.16.0",
]
[[package]]
@@ -3634,14 +3669,14 @@ version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e"
dependencies = [
"webpki-root-certs 1.0.2",
"webpki-root-certs 1.0.6",
]
[[package]]
name = "webpki-root-certs"
version = "1.0.2"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4ffd8df1c57e87c325000a3d6ef93db75279dc3a231125aac571650f22b12a"
checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca"
dependencies = [
"rustls-pki-types",
]
+21 -5
View File
@@ -1,6 +1,6 @@
[package]
name = "payphone"
version = "4.4.18"
version = "4.4.19"
edition = "2024"
default-run = "payphone"
@@ -26,20 +26,36 @@ open = "5.3.2"
rand = "0.9.2"
rand_chacha = { version = "0.9.0", features = ["os_rng"] }
regex = "1.11.1"
reqwest = { version = "0.12.23", features = ["gzip", "brotli", "zstd", "native-tls-vendored"] }
reqwest = { version = "0.12.23", features = [
"gzip",
"brotli",
"zstd",
"native-tls-vendored",
] }
rgb = "0.8.52"
scc = "2.3.4"
scylla = { version = "1.3.1", features = ["time-03"] }
serde_json = "1.0.143"
thiserror = "2.0.12"
time = { version = "0.3.41", features = ["formatting", "local-offset", "macros"] }
time = { version = "0.3.41", features = [
"formatting",
"local-offset",
"macros",
] }
tokio = { version = "1.47.1", features = ["macros", "rt-multi-thread"] }
topgg = { version = "1.4.2", features = ["twilight"] }
tower-http = { version = "0.6.6", features = ["fs"] }
twilight-cache-inmemory = { version = "0.16.0", features = ["permission-calculator"] }
twilight-cache-inmemory = { version = "0.16.0", features = [
"permission-calculator",
] }
twilight-gateway = "0.16.0"
twilight-http = { version = "0.16.0", features = ["simd-json"] }
twilight-model = "0.16.0"
twilight-util = { version = "0.16.0", features = ["builder", "permission-calculator", "snowflake"] }
twilight-util = { version = "0.16.0", features = [
"builder",
"permission-calculator",
"snowflake",
] }
twilight-validate = "0.16.0"
unicode-segmentation = "1.12.0"
unidecode = "0.3.0"
+23 -13
View File
@@ -1,14 +1,24 @@
$ANSIBLE_VAULT;1.1;AES256
31353838363564633532353539313763643561396661313030346466653839663931323961663362
6333376338336336346562643136316439393962356236640a653836643066346564663363633364
30616634363430646335663339613333616334393037333065336664396338346135353239346261
3366303231616166300a613566643231303066373266646665343637353364303939346464323633
37623565643063353435376238326564353563653735393164616136373531356135666337353765
39326463633965383463353335306432326433313132373461633666343934616638346666306339
36313561363965663662313163663362333466663135363731643737386466643134396564353439
32313936316432313433336235643337386430633434363764666439386234323933313465306638
65396532396533303662326338376661343962613432393735356130613165626465656464343434
63646265333064623735646161656236623366623265626664313564316665396331616631613536
38646264656563353934383237626534663563666335666430326562303862616461343935393737
62343637336563383864383732303861633634303061376666353231323331643538333633643762
35623539303562643763336232353633666661626539356465383631336261363532
38323862623762363734393366316436666137373937653630656665666232333435326166306633
6438393065663630383537316230336633363932646663300a666666393930376638663537663837
64366231366561623365363634323466626333626534326631323964613361373339333639623137
3335376535313338390a373262393230353238373332316464653165363762323634646335613564
31356633643837643437366130623638643133333336343264623536346339313365663533346566
61333564323066386639353032306639656465383263616263386563343539313530396662613831
61393030363264346564626239663531343433616231643732343835333338326538393838396132
36316331666131616264613461323432663430616562303865636461306264336330646263313439
66633261333063313162393765653263356263333934366333363037363765646264386632393733
39663339313939366162656336353563643836376366363032363430306162666331373165643462
32363930373231646135306466613935646636386639643137313830346531393735373938373531
63356665613434353162366638396339396130643066336135616433633830313736343265646165
61373461616363623239616534396431646561333630666230633766363832613365636664633865
32626636393262303235626132666661623134373766663135643131626363383238363836326232
62363962613965356165653134366235376364333965303361643634636231323639373132623336
33383532383237636436303164396531343134633838373936646132353132386465636330363161
65653937313032346138373435656663653639653133373564366137363261326438336436303330
32386434663236643132326536306437653231383366366363666461323931613839383762343361
38343138613466346335396136313334343731313265633365646666366131653837343664663666
62616336386339393465626138613465316334303239643335633239666165373630333135373062
35353530643164643732633732336364326161366666333233313833313939663535653763636237
62633064363561323065653162336134643338623065356536613961303034323235363631343530
663832616435656433306266643463373930
+1
View File
@@ -49,6 +49,7 @@
type: Opaque
stringData:
PAYPHONE_TOKEN: "{{ bot_token }}"
PAYPHONE_TOPGG_TOKEN: "{{ topgg_token }}"
kubeconfig: /etc/rancher/k3s/k3s.yaml
- name: Set Git credentials
+8
View File
@@ -230,6 +230,14 @@ pub enum Commands {
default_value_t = 0
)]
bot_owner_id: u64,
#[arg(
long,
env = "PAYPHONE_TOPGG_TOKEN",
value_name = "TOKEN",
help = "The token to use for the Top.gg API, used for posting server counts and other stats. If not provided, Top.gg integration will be disabled."
)]
topgg_token: Option<String>,
},
/// Starts a documentation server for the project which serves `cargo doc` and refreshes on
+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 {
+1 -1
View File
@@ -15,7 +15,7 @@
"Help us sharing Payphone to make it more active!",
"Emojis will only show if they're from a server Payphone's in.",
"You cannot send links.",
"[Vote for Payphone on top.gg](<https://top.gg/bot/1212940413795827763/vote>) to help us reach more users!",
"[Vote for Payphone on top.gg](<https://top.gg/bot/1212940413795827763/vote>) to see more people around!",
"[Write a review](<https://top.gg/bot/1212940413795827763#reviews>) to tell everyone your opinion about Payphone!",
"Calls will be automatically hung up after 15 minutes if nobody talks.",
"You can change Payphone's prefix with `{prefix}prefix`.",
+9 -1
View File
@@ -192,6 +192,7 @@ pub async fn main() {
shard,
redis_urls,
bot_owner_id,
topgg_token
} => {
start(
token,
@@ -201,6 +202,7 @@ pub async fn main() {
shard.into(),
redis_urls,
bot_owner_id,
topgg_token
)
.await;
}
@@ -256,6 +258,7 @@ impl ExtrasGetter<State> for PayphoneExtrasGetter {
}
/// Starts a Payphone shard.
#[allow(clippy::too_many_arguments)]
async fn start(
token: String,
database_addr: String,
@@ -264,6 +267,7 @@ async fn start(
shard: ShardId,
redis_urls: Vec<String>,
bot_owner_id: u64,
topgg_token: Option<String>,
) {
log::info!("Welcome to Payphone, Nyeki!");
log::info!("Payphone is running on version v{VERSION}");
@@ -289,7 +293,7 @@ async fn start(
init_color_fetching_queue_listener(color_queue_receiver, state.clone());
let bot = Bot::new(state, ServerPrefixOrPayphoneMention, PayphoneExtrasGetter)
let mut bot = Bot::new(state, ServerPrefixOrPayphoneMention, PayphoneExtrasGetter)
.shard(shard)
.intent(Intents::GUILDS)
.intent(Intents::GUILD_MESSAGES)
@@ -348,6 +352,10 @@ async fn start(
.expect("Could not set bot presence since the parameters passed were invalid"),
);
if let Some(topgg_token) = topgg_token {
bot = bot.topgg_token(topgg_token);
}
bot.run(&token).await.expect("Could not run bot!");
}