Discord: customizable announcements and live embeds (status, guilds, leaderboard, baltop) backend
This commit is contained in:
7 files changed
+924
-15
No files matched your search
@@ -11,6 +11,7 @@ use crate::routes::connections::ConnectionsSettings;
|
||||
use crate::state::AppState;
|
||||
use crate::store;
|
||||
use axum::extract::{Path, State};
|
||||
use crate::embeds;
|
||||
use axum::Json;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
@@ -336,36 +337,46 @@ pub async fn announce(state: &AppState) -> AppResult<u32> {
|
||||
}
|
||||
let mut sent = 0;
|
||||
if s.notify_achievements {
|
||||
let rows: Vec<(String, String, String)> = sqlx::query_as(
|
||||
"SELECT COALESCE(u.username, ua.user_uuid), a.title, ua.unlocked_at FROM user_achievements ua
|
||||
let rows: Vec<(String, String, String, String, i64, String, String)> = sqlx::query_as(
|
||||
"SELECT ua.user_uuid, COALESCE(u.username, ua.user_uuid), a.title, a.description, a.xp_reward, a.category, ua.unlocked_at FROM user_achievements ua
|
||||
JOIN achievements a ON a.id = ua.achievement_id LEFT JOIN users u ON u.uuid = ua.user_uuid
|
||||
WHERE ua.unlocked_at > ? ORDER BY ua.unlocked_at LIMIT 10",
|
||||
)
|
||||
.bind(&cursor.achievements)
|
||||
.fetch_all(&state.db)
|
||||
.await?;
|
||||
for (who, title, at) in rows {
|
||||
post_webhook(state, &s.webhook_url, "Achievement unlocked", &format!("**{}** earned **{}**", clip(&who), clip(&title)), 0xfcd34d).await;
|
||||
for (uuid, who, title, desc, xp, category, at) in rows {
|
||||
let mut vars = embeds::player_vars(state, &uuid, &who).await;
|
||||
for (k, v) in [("achievement", embeds::plain(&title)), ("achievement_description", embeds::plain(&desc)), ("xp", xp.to_string()), ("category", embeds::plain(&category))] {
|
||||
vars.insert(k.into(), v);
|
||||
}
|
||||
if embeds::announce_event(state, "achievement", &vars).await.unwrap_or(false) {
|
||||
sent += 1;
|
||||
}
|
||||
cursor.achievements = at;
|
||||
sent += 1;
|
||||
}
|
||||
}
|
||||
if s.notify_guilds {
|
||||
let rows: Vec<(String, String, String)> =
|
||||
sqlx::query_as("SELECT name, tag, created_at FROM guilds WHERE created_at > ? ORDER BY created_at LIMIT 10").bind(&cursor.guilds).fetch_all(&state.db).await?;
|
||||
for (name, tag, at) in rows {
|
||||
post_webhook(state, &s.webhook_url, "New guild", &format!("**{}** [{}] was founded", clip(&name), clip(&tag)), 0x22d3ee).await;
|
||||
let rows: Vec<(String, String)> = sqlx::query_as("SELECT id, created_at FROM guilds WHERE created_at > ? ORDER BY created_at LIMIT 10").bind(&cursor.guilds).fetch_all(&state.db).await?;
|
||||
for (id, at) in rows {
|
||||
let vars = embeds::guild_vars(state, &id).await;
|
||||
if embeds::announce_event(state, "guild", &vars).await.unwrap_or(false) {
|
||||
sent += 1;
|
||||
}
|
||||
cursor.guilds = at;
|
||||
sent += 1;
|
||||
}
|
||||
}
|
||||
if s.notify_members {
|
||||
let rows: Vec<(String, String)> =
|
||||
sqlx::query_as("SELECT username, created_at FROM users WHERE status = 'active' AND created_at > ? ORDER BY created_at LIMIT 10").bind(&cursor.members).fetch_all(&state.db).await?;
|
||||
for (name, at) in rows {
|
||||
post_webhook(state, &s.webhook_url, "New player", &format!("Welcome **{}**!", clip(&name)), 0x6ee7b7).await;
|
||||
let rows: Vec<(String, String, String)> =
|
||||
sqlx::query_as("SELECT uuid, username, created_at FROM users WHERE status = 'active' AND created_at > ? ORDER BY created_at LIMIT 10").bind(&cursor.members).fetch_all(&state.db).await?;
|
||||
for (uuid, name, at) in rows {
|
||||
let mut vars = embeds::player_vars(state, &uuid, &name).await;
|
||||
let total: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM users WHERE status = 'active'").fetch_one(&state.db).await.unwrap_or(0);
|
||||
vars.insert("members_total".into(), total.to_string());
|
||||
if embeds::announce_event(state, "member", &vars).await.unwrap_or(false) {
|
||||
sent += 1;
|
||||
}
|
||||
cursor.members = at;
|
||||
sent += 1;
|
||||
}
|
||||
}
|
||||
store::kv_set(state, "discord_cursor", &cursor).await?;
|
||||
@@ -385,11 +396,13 @@ pub async fn test_webhook(_: AdminUser, State(state): State<AppState>) -> AppRes
|
||||
pub fn spawn_worker(state: AppState) {
|
||||
tokio::spawn(async move {
|
||||
let mut tick = 0u64;
|
||||
let mut live_last = std::collections::BTreeMap::new();
|
||||
loop {
|
||||
tokio::time::sleep(Duration::from_secs(30)).await;
|
||||
if let Err(e) = announce(&state).await {
|
||||
tracing::debug!("discord announce: {e:?}");
|
||||
}
|
||||
embeds::tick_live(&state, &mut live_last).await;
|
||||
tick += 1;
|
||||
if tick % 30 == 0 {
|
||||
if let Err(e) = sync_all(&state).await {
|
||||
|
||||
Reference in new issue
Block a user