209 lines
5.8 KiB
Rust
209 lines
5.8 KiB
Rust
|
use serenity::all::{CommandInteraction, Context};
|
||
|
use skynet_discord_bot::{
|
||
|
common::{
|
||
|
database::DataBase,
|
||
|
server_icon::{get_config_icons, update_icon::update_icon_main, ServerIcons},
|
||
|
},
|
||
|
Config,
|
||
|
};
|
||
|
|
||
|
use serenity::all::{CommandOptionType, CreateCommand, CreateCommandOption};
|
||
|
|
||
|
// commands that server mods are able to use
|
||
|
pub(crate) mod admin {
|
||
|
use super::*;
|
||
|
|
||
|
// Moderators can force a icon change
|
||
|
pub(crate) mod change {
|
||
|
use super::*;
|
||
|
|
||
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||
|
let db_lock = {
|
||
|
let data_read = ctx.data.read().await;
|
||
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||
|
};
|
||
|
let db = db_lock.read().await;
|
||
|
|
||
|
let config_lock = {
|
||
|
let data_read = ctx.data.read().await;
|
||
|
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
||
|
};
|
||
|
let config_global = config_lock.read().await;
|
||
|
|
||
|
let config_toml = get_config_icons::minimal();
|
||
|
update_icon_main(ctx, &db, &config_global, &config_toml).await;
|
||
|
|
||
|
"Changed server Icon".to_string()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// commands for general users
|
||
|
pub(crate) mod user {
|
||
|
use super::*;
|
||
|
use skynet_discord_bot::common::server_icon::get_config_icons::ConfigTomlLocal;
|
||
|
|
||
|
pub fn register() -> CreateCommand {
|
||
|
CreateCommand::new("icon")
|
||
|
.description("Commands related to the Server Icon")
|
||
|
.add_option(
|
||
|
CreateCommandOption::new(CommandOptionType::SubCommandGroup, "current", "Information on current items.")
|
||
|
.add_sub_option(CreateCommandOption::new(CommandOptionType::SubCommand, "icon", "Information on current icon."))
|
||
|
.add_sub_option(CreateCommandOption::new(CommandOptionType::SubCommand, "festival", "Information on current festival.")),
|
||
|
)
|
||
|
.add_option(CreateCommandOption::new(CommandOptionType::SubCommand, "stats", "Some Stats."))
|
||
|
}
|
||
|
|
||
|
fn get_logo_url(config_toml: &ConfigTomlLocal, logo_name: &str) -> String {
|
||
|
format!("{}/src/branch/main/{}/{}", &config_toml.source.repo, &config_toml.source.directory, logo_name)
|
||
|
}
|
||
|
|
||
|
/// Regular users can get teh link to teh current icon
|
||
|
pub(crate) mod current {
|
||
|
use super::*;
|
||
|
|
||
|
pub(crate) mod icon {
|
||
|
use super::*;
|
||
|
|
||
|
use sqlx::{Pool, Sqlite};
|
||
|
|
||
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||
|
let db_lock = {
|
||
|
let data_read = ctx.data.read().await;
|
||
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||
|
};
|
||
|
let db = db_lock.read().await;
|
||
|
|
||
|
let config_toml = get_config_icons::minimal();
|
||
|
|
||
|
if let Some(logo) = get_current_icon(&db).await {
|
||
|
get_logo_url(&config_toml, &logo.name)
|
||
|
} else {
|
||
|
"Could not find current icon".to_string()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async fn get_current_icon(db: &Pool<Sqlite>) -> Option<ServerIcons> {
|
||
|
match sqlx::query_as::<_, ServerIcons>(
|
||
|
"
|
||
|
SELECT * from server_icons ORDER BY id DESC LIMIT 1
|
||
|
",
|
||
|
)
|
||
|
.fetch_one(db)
|
||
|
.await
|
||
|
{
|
||
|
Ok(res) => Some(res),
|
||
|
Err(e) => {
|
||
|
dbg!(e);
|
||
|
None
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub(crate) mod festival {
|
||
|
use serenity::all::{CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption};
|
||
|
use skynet_discord_bot::common::server_icon::get_config_icons;
|
||
|
use skynet_discord_bot::Config;
|
||
|
|
||
|
// use this to return what current festivals are active?
|
||
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||
|
let config_lock = {
|
||
|
let data_read = ctx.data.read().await;
|
||
|
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
|
||
|
};
|
||
|
let config = config_lock.read().await;
|
||
|
|
||
|
let config_toml = get_config_icons::full(&config);
|
||
|
|
||
|
let mut response = vec![];
|
||
|
|
||
|
for festival in &config_toml.festivals {
|
||
|
response.push(festival.name.to_owned());
|
||
|
}
|
||
|
|
||
|
format!("Festivals active: {}", response.join(", "))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Get the statistics of the icons
|
||
|
pub(crate) mod stats {
|
||
|
use super::*;
|
||
|
use sqlx::{Pool, Sqlite};
|
||
|
|
||
|
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
|
||
|
let db_lock = {
|
||
|
let data_read = ctx.data.read().await;
|
||
|
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
|
||
|
};
|
||
|
let db = db_lock.read().await;
|
||
|
|
||
|
let config_toml = get_config_icons::minimal();
|
||
|
|
||
|
let totals = get_totals(&db).await;
|
||
|
|
||
|
fmt_msg(&config_toml, &totals)
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Clone, sqlx::FromRow)]
|
||
|
pub struct CountResult {
|
||
|
pub name: String,
|
||
|
pub times: i64,
|
||
|
}
|
||
|
|
||
|
async fn get_totals(db: &Pool<Sqlite>) -> Vec<CountResult> {
|
||
|
sqlx::query_as::<_, CountResult>(
|
||
|
"
|
||
|
SELECT
|
||
|
DISTINCT name,
|
||
|
COUNT(*) OVER(PARTITION BY name) AS times
|
||
|
FROM server_icons
|
||
|
",
|
||
|
)
|
||
|
.fetch_all(db)
|
||
|
.await
|
||
|
.unwrap_or_else(|e| {
|
||
|
dbg!(e);
|
||
|
vec![]
|
||
|
})
|
||
|
}
|
||
|
|
||
|
fn fmt_msg(config_toml: &ConfigTomlLocal, totals: &Vec<CountResult>) -> String {
|
||
|
// msg can be a max 2000 chars long
|
||
|
let mut limit = 2000 - 3;
|
||
|
|
||
|
let mut response = vec![];
|
||
|
for CountResult {
|
||
|
name,
|
||
|
times,
|
||
|
} in totals
|
||
|
{
|
||
|
let current_leading = if times < &10 {
|
||
|
"00"
|
||
|
} else if times < &100 {
|
||
|
"0"
|
||
|
} else {
|
||
|
""
|
||
|
};
|
||
|
|
||
|
let url = get_logo_url(config_toml, name);
|
||
|
|
||
|
let line = format!("{}{} <{}>", current_leading, times, url);
|
||
|
|
||
|
let length = line.len() + 1;
|
||
|
|
||
|
// +3 is to account for the closing fense
|
||
|
if length < (limit + 3) {
|
||
|
response.push(line);
|
||
|
limit -= length;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
response.join("\n")
|
||
|
}
|
||
|
}
|
||
|
}
|