Refactors for less nesting, slight performance and memory improvement for count command #46

Open
cordlesscoder wants to merge 1 commit from cordlesscoder/discord-bot:#46_Refactor into main
9 changed files with 161 additions and 287 deletions

View file

@ -10,31 +10,19 @@ use skynet_discord_bot::common::{
use sqlx::{Error, Pool, Sqlite};
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
let sub_options = if let Some(CommandDataOption {
value: CommandDataOptionValue::SubCommand(options),
let Some(CommandDataOption {

I am saying no to this style.

While it is technically possible, readability falls off a cliff.
I had to check out teh file locally to be able to get some understanding, and even then it was only because my IDE was hilighting stuff that it was possible to see the flow.

Cool that it can be done that way, but it means that it has a higher chance to be either abandoned or ripped out in the future.

I am saying no to this style. While it is technically possible, readability falls off a cliff. I had to check out teh file locally to be able to get some understanding, and even then it was only because my IDE was hilighting stuff that it was possible to see the flow. Cool that it can be done that way, but it means that it has a higher chance to be either abandoned or ripped out in the future.
value: CommandDataOptionValue::SubCommand(sub_options),
..
}) = command.data.options.first()
{
options
} else {
else {
return "Please provide sub options".to_string();
};
let wolves_api = if let Some(x) = sub_options.first() {
match &x.value {
CommandDataOptionValue::String(key) => key.to_string(),
_ => return "Please provide a wolves API key".to_string(),
}
} else {
let Some(CommandDataOptionValue::String(wolves_api)) = sub_options.first().map(|opt| &opt.value) else {
return "Please provide a wolves API key".to_string();
};
let role_current = if let Some(x) = sub_options.get(1) {
match &x.value {
CommandDataOptionValue::Role(role) => role.to_owned(),
_ => return "Please provide a valid role for ``Role Current``".to_string(),
}
} else {
let Some(&CommandDataOptionValue::Role(role_current)) = sub_options.get(1).map(|opt| &opt.value) else {
return "Please provide a valid role for ``Role Current``".to_string();
};
@ -47,12 +35,7 @@ pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
None
};
let bot_channel_id = if let Some(x) = sub_options.get(2) {
match &x.value {
CommandDataOptionValue::Channel(channel) => channel.to_owned(),
_ => return "Please provide a valid channel for ``Bot Channel``".to_string(),
}
} else {
let Some(&CommandDataOptionValue::Channel(bot_channel_id)) = sub_options.get(2).map(|opt| &opt.value) else {
return "Please provide a valid channel for ``Bot Channel``".to_string();
};
@ -63,7 +46,7 @@ pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
let server_data = Servers {
server: command.guild_id.unwrap_or_default(),
wolves_api,
wolves_api: wolves_api.to_string(),
wolves_id: 0,
role_past,
role_current,
@ -72,12 +55,9 @@ pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
bot_channel_id,
};
match add_server(&db, ctx, &server_data).await {
Ok(_) => {}

This is more of a personal experience thing but I used to use more if let Err(/if let Ok( but often found myself having to change it to a match to be able to add a capture for the other option to be able to debug why something was succeeding, but not correctly.
It is useful to keep around SQL queries I find.

This is more of a personal experience thing but I used to use more ``if let Err(``/``if let Ok(`` but often found myself having to change it to a match to be able to add a capture for the other option to be able to debug why something was succeeding, but not correctly. It is useful to keep around SQL queries I find.
Err(e) => {
println!("{e:?}");
return format!("Failure to insert into Servers {server_data:?}");
}
if let Err(e) = add_server(&db, ctx, &server_data).await {
println!("{e:?}");
return format!("Failure to insert into Servers {server_data:?}");
}
"Added/Updated server info".to_string()

View file

@ -8,24 +8,21 @@ pub mod committee {
use skynet_discord_bot::common::{database::DataBase, set_roles::committee::db_roles_get};
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
let sub_options = if let Some(CommandDataOption {
value: CommandDataOptionValue::SubCommand(key),
let Some(CommandDataOption {
value: CommandDataOptionValue::SubCommand(sub_options),
..
}) = command.data.options.first()
{
key
} else {
else {
return "Please provide a wolves API key".to_string();
};
let all = if let Some(x) = sub_options.first() {
match x.value {
let all = sub_options
.first()
.map(|x| match x.value {
CommandDataOptionValue::Boolean(y) => y,
_ => false,
}
} else {
false
};
})
.unwrap_or(false);

This is good :3

This is good :3
let db = {
let data_read = ctx.data.read().await;
@ -41,30 +38,24 @@ pub mod committee {
cs.push((committee.count, committee.name_role.to_owned()));
}
cs.sort_by_key(|(count, _)| *count);
cs.reverse();
cs.sort_by_key(|(count, _)| std::cmp::Reverse(*count));

Also good!

Also good!
// msg can be a max 2000 chars long
let mut limit = 2000 - 3;
let limit = 2000 - 3;

This can just be 2000 due to how ye are managing it.

This can just be 2000 due to how ye are managing it.

No it cannot?

No it cannot?
let mut response = vec!["```".to_string()];
let mut response = "```".to_string();
for (count, name) in cs {
let leading = if count < 10 { " " } else { "" };
let line = format!("{leading}{count} {name}");
let length = line.len() + 1;
if length < (limit + 3) {
response.push(line);
limit -= length;
} else {
use std::fmt::Write;
let len_before = response.len();

Whenever ye are doing something "clever" ye need to add a fuckton of comments.
So please add them to explain it.

This is nice though, far better than what I had before.

Whenever ye are doing something "clever" ye need to add a fuckton of comments. So please add them to explain it. This is nice though, far better than what I had before.
_ = writeln!(response, "{count:>2} {name}");
if response.len() >= limit {
// Discard the line that didn't fit
response.truncate(len_before);
break;
}
}
response.push("```".to_string());
response.join("\n")
response.push_str("```");
response
}
pub fn register() -> CreateCommand {
@ -99,12 +90,8 @@ pub mod servers {
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
};
let mut committees = HashMap::new();
if let Some(x) = get_committees(&db).await {
for committee in x {
committees.insert(committee.id, committee.to_owned());
}
}
let committees = get_committees(&db).await.into_iter().flatten().map(|committee| (committee.id, committee));
let committees: HashMap<_, _> = committees.collect();

Dont use the same var name for two different data types.
I know its possible but makes reading just the code hell.

Dont use the same var name for two different data types. I know its possible but makes reading just the code hell.

But this is the entire point of shadowing existing - it is absolutely idiomatic Rust.

But this is the entire point of shadowing existing - it is absolutely idiomatic Rust.
let mut cs = vec![];
// pull it from a DB
@ -127,40 +114,22 @@ pub mod servers {
cs.reverse();
// msg can be a max 2000 chars long
let mut limit = 2000 - 3;
let limit = 2000 - 3;
let mut response = vec!["```".to_string()];
let mut response = "```".to_string();
for (current, past, name) in cs {
let current_leading = if current < 10 {
" "
} else if current < 100 {
" "
} else {
""
};
let past_leading = if past < 10 {
" "
} else if past < 100 {
" "
} else {
""
};
let line = format!("{current_leading}{current} {past_leading}{past} {name}");
let length = line.len() + 1;
// +3 is to account for the closing fence
if length < (limit + 3) {
response.push(line);
limit -= length;
} else {
use std::fmt::Write;

ye may as well import this far higher in the file

ye may as well import this far higher in the file
let len_before = response.len();

Same thing about leaving comments here

Same thing about leaving comments here
_ = writeln!(response, "{current:>3} {past:>} {name}");
if response.len() >= limit {
// Discard the line that didn't fit
response.truncate(len_before);
break;
}
}
response.push("```".to_string());
response.push_str("```");
response.join("\n")
response
}
#[derive(Debug, Clone, Deserialize, Serialize, sqlx::FromRow)]

View file

@ -67,17 +67,11 @@ impl<'r> FromRow<'r, SqliteRow> for ServerMembersWolves {
}
fn get_discord_from_row(row: &SqliteRow) -> Option<UserId> {
match row.try_get("discord") {
Ok(x) => {
let tmp: i64 = x;
if tmp == 0 {
None
} else {
Some(UserId::from(tmp as u64))
}
}
_ => None,
let x: i64 = row.try_get("discord").ok()?;

Pretty nice.
Though if ye are changing it ye may look into some slight changes such as:

  let x: u64 = row.try_get("discord").ok()?;
  if x == 0_u64 {
    // Default value, ID of 0 is not permitted
    return None;
  }
  Some(UserId::from(x))

Added the comment to make it clearer for folks in the future.

Pretty nice. Though if ye are changing it ye may look into some slight changes such as: ```rust let x: u64 = row.try_get("discord").ok()?; if x == 0_u64 { // Default value, ID of 0 is not permitted return None; } Some(UserId::from(x)) ``` Added the comment to make it clearer for folks in the future.
if x == 0 {
return None;
}
Some(UserId::from(x as u64))
}
#[derive(Debug, Clone, Deserialize, Serialize)]

View file

@ -49,7 +49,7 @@ pub async fn post<T: Serialize>(url: &str, bearer: &str, data: &T) {
.body_json(&data)
{
Ok(req) => {
req.await.ok();
_ = req.await;
}
Err(e) => {
dbg!(e);
@ -71,20 +71,14 @@ pub struct ServerDetailsRes {
}
async fn get<T: Serialize + DeserializeOwned>(url: &str, bearer: &str) -> Option<T> {
match surf::get(url)
surf::get(url)
.header("Authorization", bearer)
.header("Content-Type", "application/json")
.header("Accept", "Application/vnd.pterodactyl.v1+json")
.recv_json()
.await
{
Ok(res) => Some(res),

Another artifact left in from debugging, might be useful to leave as some services (this included) send a 200 for even a failure.

Another artifact left in from debugging, might be useful to leave as some services (this included) send a 200 for even a failure.
Err(e) => {
dbg!(e);
None
}
}
.map_err(|e| dbg!(e))
.ok()
}
#[derive(Deserialize, Serialize, Debug)]
@ -157,14 +151,9 @@ pub async fn whitelist_update(add: &Vec<(String, bool)>, server: &str, token: &s
let bearer = format!("Bearer {token}");
for (name, java) in add {
let data = if *java {
BodyCommand {
command: format!("whitelist add {name}"),
}
} else {
BodyCommand {
command: format!("fwhitelist add {name}"),
}
let command = if *java { format!("whitelist add {name}") } else { format!("fwhitelist add {name}") };
let data = BodyCommand {
command,
};
post(&format!("{url_base}/command"), &bearer, &data).await;
}

View file

@ -54,62 +54,47 @@ impl Renderer {
count: 0,
};
let colors = if args.colors.contains(':') {
//? object
let obj = args
.colors
.split(',')
.map(|s| {
let s = s.split(':').collect::<Vec<&str>>();
this.colors = if args.colors.contains(':') {

I strongly recommend doing anything with this file.
If ye want to change this make sure ye do a good job.

I strongly recommend doing anything with this file. If ye want to change this make sure ye do a good job.
let obj = args.colors.split(',').map(|s| {
let mut iter = s.split(':');
let [Some(a), Some(b), None] = std::array::from_fn(|_| iter.next()) else {
dbg!("Invalid color object, try checking help");
return None;
};
if s.len() < 2 {
dbg!("Invalid color object, try checking help");
return None;
}
Some((a.to_string(), b.to_string()))
});
Some((s[0].to_string(), s[1].to_string()))
let colors = obj
.flatten()
.map(|c| {
std::fs::create_dir_all(args.output.join(&c.0))?;
Ok(c)
})
.collect::<Vec<Option<(String, String)>>>();
let mut colors = Vec::new();
for c in obj.into_iter().flatten() {
std::fs::create_dir_all(args.output.join(&c.0))?;
colors.push(c);
}
.collect::<std::io::Result<_>>()?;

Just a personal thing (wont reject over it) but not too much of a fan of <_>, makes it harder to read the code and follow through.
Its great if ye have an IDE which will populate it, not so great if ye dont have teh IDE open.

Just a personal thing (wont reject over it) but not too much of a fan of ``<_>``, makes it harder to read the code and follow through. Its great if ye have an IDE which will populate it, not so great if ye dont have teh IDE open.
ColorType::Object(colors)
} else {
//? list
// let colors = args.colors.split(",").map(|s| {
// s.to_string()
// })
// .collect::<Vec<String>>();
let mut colors = Vec::new();
for color in args.colors.split(',') {
std::fs::create_dir_all(args.output.join(color))?;
colors.push(color.to_string())
}
let colors = args
.colors
.split(',')
.map(|color| -> std::io::Result<String> {
std::fs::create_dir_all(args.output.join(color))?;
Ok(color.to_string())
})
.collect::<std::io::Result<_>>()?;
ColorType::Array(colors)
};
this.colors = colors;
Ok(this)
}
pub fn render(&mut self, fi: &Path, args: &Args) -> Result<()> {
match fi.extension() {
Some(e) if e.to_str() == Some("svg") => {}
Some(_) | None => {
dbg!("Filer {:?} is not of type SVG", fi);
// util::logger::warning(format!("File '{}' is not of SVG type", fi.clone().to_str().unwrap()));
bail!("Failed to render");
}
};
if fi.extension().is_none_or(|ext| ext != "svg") {
dbg!("Filer {:?} is not of type SVG", fi);
// util::logger::warning(format!("File '{}' is not of SVG type", fi.clone().to_str().unwrap()));
bail!("Failed to render");
}
match self.colors.clone() {
ColorType::Array(c) => {

View file

@ -60,17 +60,11 @@ pub mod get_config_icons {
let config_source = minimal();
let file_path = format!("{}/open-governance/{}/{}", &config.home, &config_source.source.directory, &config_source.source.file);
let contents = fs::read_to_string(file_path).unwrap_or_else(|e| {
dbg!(e);
"".to_string()
});
let festivals = match toml::from_str::<ConfigTomlRemote>(&contents) {
Ok(config_festivals) => config_festivals.festivals,
Err(e) => {
dbg!(e);
vec![]
}
};
let contents = fs::read_to_string(file_path).map_err(|e| dbg!(e)).unwrap_or_default();
let festivals = toml::from_str::<ConfigTomlRemote>(&contents)
.map(|config| config.festivals)
.map_err(|e| dbg!(e))
.unwrap_or_default();
ConfigToml {
source: config_source.source,
@ -248,12 +242,9 @@ pub mod update_icon {
for tmp in paths.flatten() {
let path_local = tmp.path().to_owned();
let path_local2 = tmp.path().to_owned();
let name = match path_local2.file_name() {
None => {
dbg!(path_local2);
continue;
}
Some(x) => x.to_owned(),
let Some(name) = path_local2.file_name().map(ToOwned::to_owned) else {

This is grand for using let Some().
The ones up in add_servers were far more complex and so not suited to using this format.

This is grand for using ``let Some()``. The ones up in ``add_servers`` were far more complex and so not suited to using this format.
dbg!(path_local2);
continue;
};
let mut path = tmp.path();
@ -308,16 +299,15 @@ pub mod update_icon {
fn logos_filter(festival_data: &FestivalData, existing: Vec<LogoData>) -> Vec<LogoData> {
let mut filtered: Vec<LogoData> = vec![];
let allowed_files = vec![".png", ".jpeg", ".gif", ".svg"];
let allowed_extensions = ["png", "jpeg", "gif", "svg"];
'outer: for logo in existing {
let name_lowercase0 = logo.name.to_ascii_lowercase();
let name_lowercase = name_lowercase0.to_str().unwrap_or_default();
let mut allowed = false;
for allowed_type in &allowed_files {
if name_lowercase.ends_with(allowed_type) {
allowed = true;
}
}
let name_lowercase = logo.name.to_ascii_lowercase();
let name_lowercase = name_lowercase.to_str().unwrap_or_default();

Dont shadow var name.

Dont shadow var name.
let allowed = {
let extension = name_lowercase.split('.').next_back().unwrap_or_default();
allowed_extensions.contains(&extension)
};
if !allowed {
continue;
}
@ -332,13 +322,7 @@ pub mod update_icon {
}
} else {
// else filter using the excluded ones
let mut excluded = false;
for festival in &festival_data.exclusions {
if name_lowercase.contains(festival) {
excluded = true;
}
}
let excluded = festival_data.exclusions.iter().any(|festival| name_lowercase.contains(festival));
if !excluded {
filtered.push(logo);
}
@ -349,39 +333,34 @@ pub mod update_icon {
}
async fn logo_set(ctx: &Context, db: &Pool<Sqlite>, server: &GuildId, logo_selected: &LogoData) {
// add to teh database
if !logo_set_db(db, logo_selected).await {
// add to the database
if logo_set_db(db, logo_selected).await.is_err() {
// something went wrong
return;
}
if let Some(logo_path) = logo_selected.path.to_str() {
match CreateAttachment::path(logo_path).await {
Ok(icon) => {
// assuming a `guild` has already been bound
let builder = EditGuild::new().icon(Some(&icon));
if let Err(e) = server.edit(ctx, builder).await {
dbg!(e);
}
}
Err(e) => {
let Some(logo_path) = logo_selected.path.to_str() else {
return;
};
match CreateAttachment::path(logo_path).await {
Ok(icon) => {
// assuming a `guild` has already been bound
let builder = EditGuild::new().icon(Some(&icon));
if let Err(e) = server.edit(ctx, builder).await {
dbg!(e);
}
}
Err(e) => {
dbg!(e);
}
}
}
async fn logo_set_db(db: &Pool<Sqlite>, logo_selected: &LogoData) -> bool {
let name = match logo_selected.name.to_str() {
None => return false,
Some(x) => x,
};
let path = match logo_selected.path.to_str() {
None => return false,
Some(x) => x,
};
async fn logo_set_db(db: &Pool<Sqlite>, logo_selected: &LogoData) -> Result<(), ()> {
let name = logo_selected.name.to_str().ok_or(())?;
let path = logo_selected.path.to_str().ok_or(())?;
match sqlx::query_as::<_, ServerIcons>(
sqlx::query_as::<_, ServerIcons>(
"
INSERT OR REPLACE INTO server_icons (name, date, path)
VALUES (?1, ?2, ?3)
@ -392,13 +371,9 @@ pub mod update_icon {
.bind(path)
.fetch_optional(db)
.await
{
Ok(_) => {}

As I have outlined before, dont get rid of the match.
Consider it a hard learnt lesson in debugging.

As I have outlined before, dont get rid of the match. Consider it a hard learnt lesson in debugging.
Err(e) => {
dbg!(e);
return false;
}
}
true
.map_err(|e| {
dbg!(e);
})?;
Ok(())
}
}

View file

@ -24,7 +24,7 @@ struct WolvesResultUserMin {
}
async fn add_users_wolves(db: &Pool<Sqlite>, user: &WolvesResultUserMin) {
// expiry
match sqlx::query_as::<_, Wolves>(

Again with the match, there is a reason they are all on teh SQL sections.

Again with the match, there is a reason they are all on teh SQL sections.
if let Err(e) = sqlx::query_as::<_, Wolves>(
"
INSERT INTO wolves (id_wolves, email)
VALUES ($1, $2)
@ -36,11 +36,8 @@ async fn add_users_wolves(db: &Pool<Sqlite>, user: &WolvesResultUserMin) {
.fetch_optional(db)
.await
{
Ok(_) => {}
Err(e) => {
println!("Failure to insert into Wolves {user:?}");
println!("{e:?}");
}
println!("Failure to insert into Wolves {user:?}");
println!("{e:?}");
}
}
@ -91,7 +88,6 @@ pub mod cns {
wolves_id,
..
} = &server_config;
// dbg!(&server_config);
let existing_tmp = get_server_member(&db, server).await;
let existing = existing_tmp.iter().map(|data| (data.id_wolves, data)).collect::<BTreeMap<_, _>>();
@ -99,7 +95,6 @@ pub mod cns {
// list of users that need to be updated for this server
let mut server_name_tmp = None;
for user in wolves.get_members(wolves_api).await {
// dbg!(&user.committee);
if server_name_tmp.is_none() {
server_name_tmp = Some(user.committee_id);
}

View file

@ -106,21 +106,19 @@ pub fn get_config() -> Config {
}
}
if let Ok(x) = env::var("COMMITTEE_ROLE") {
if let Ok(x) = x.trim().parse::<u64>() {
if let Ok(x) = x.trim().parse() {
config.committee_role = RoleId::new(x);
}
}
if let Ok(x) = env::var("COMMITTEE_CATEGORY") {
for part in x.split(',') {
if let Ok(x) = part.trim().parse::<u64>() {
config.committee_category.push(ChannelId::new(x));
}
for id in x.split(',').flat_map(|part| part.trim().parse()) {
config.committee_category.push(ChannelId::new(id));
}
}
if let Ok(x) = env::var("COMPSOC_DISCORD") {
if let Ok(x) = x.trim().parse::<u64>() {
config.compsoc_server = GuildId::new(x);
if let Ok(x) = x.trim().parse() {
config.compsoc_server = GuildId::new(x)

What happened the ;?

What happened the ``;``?
}
}

View file

@ -54,15 +54,14 @@ impl EventHandler for Handler {
// committee server takes priority
let committee_server = config_global.committee_server;
if new_member.guild_id.get() == committee_server.get() {
if new_member.guild_id == committee_server {

In case ye were wondering the .get() was part of the migration from v0.11 to v0.12

https://github.com/serenity-rs/serenity/blob/current/CHANGELOG.md#ids

In case ye were wondering the ``.get()`` was part of the migration from v0.11 to v0.12 https://github.com/serenity-rs/serenity/blob/current/CHANGELOG.md#ids
let mut member = vec![new_member.clone()];
update_committees(&db, &ctx, &config_global, &mut member).await;
return;
}
let config_server = match get_server_config(&db, &new_member.guild_id).await {
None => return,
Some(x) => x,
let Some(config_server) = get_server_config(&db, &new_member.guild_id).await else {
return;
};
if get_server_member(&db, &new_member.guild_id, &new_member).await.is_ok() {
@ -81,26 +80,26 @@ impl EventHandler for Handler {
if let Err(e) = new_member.add_roles(&ctx, &roles).await {
println!("{e:?}");
}
} else {
let tmp = get_committee(&db, config_server.wolves_id).await;
if !tmp.is_empty() {
let committee = &tmp[0];
let msg = format!(
r#"
return;
}
let tmp = get_committee(&db, config_server.wolves_id).await;
let Some(committee) = tmp.first() else {
return;
};
let msg = format!(
r#"
Welcome {} to the {} server!
Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use ``/wolves link email_here`` with the email associated with your wolves account, to get full access.
"#,
new_member.display_name(),
committee.name_full,
committee.link,
&config_server.server,
&config_server.bot_channel_id
);
new_member.display_name(),
committee.name_full,
committee.link,
&config_server.server,
&config_server.bot_channel_id
);
if let Err(err) = new_member.user.direct_message(&ctx, CreateMessage::new().content(&msg)).await {
dbg!(err);
}
}
if let Err(err) = new_member.user.direct_message(&ctx, CreateMessage::new().content(&msg)).await {
dbg!(err);
}
}
@ -113,9 +112,8 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
};
// check if the role changed is part of the ones for this server
if let Some(x) = new_data {
on_role_change(&db, &ctx, x).await;
}
let Some(x) = new_data else { return };

I get where ye are coming from, but this makes it less clear that its tied directly to teh role change.

I get where ye are coming from, but this makes it less clear that its tied directly to teh role change.
on_role_change(&db, &ctx, x).await;
}
async fn ready(&self, ctx: Context, ready: Ready) {
@ -128,7 +126,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
};
let config = config_lock.read().await;
match Command::set_global_commands(
if let Err(e) = Command::set_global_commands(

ye really dont like matching.

In this case would be good to keep it since sometimes the error is in the Ok branch, when stuff goes wrong, but not badly.

ye really dont like matching. In this case would be good to keep it since sometimes the error is in the Ok branch, when stuff goes wrong, but not badly.
&ctx.http,
vec![
commands::wolves::register(),
@ -140,22 +138,16 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
)
.await
{
Ok(_) => {}
Err(e) => {
println!("{e:?}")
}
println!("{e:?}")
}
// Inter-Committee server
match config.committee_server.set_commands(&ctx.http, vec![commands::count::committee::register()]).await {
Ok(_) => {}
Err(e) => {
println!("{e:?}")
}
if let Err(e) = config.committee_server.set_commands(&ctx.http, vec![commands::count::committee::register()]).await {
println!("{e:?}")
}
// CompSoc Server
match config
if let Err(e) = config
.compsoc_server
.set_commands(
&ctx.http,
@ -167,16 +159,13 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
)
.await
{
Ok(_) => {}
Err(e) => {
println!("{e:?}")
}
println!("{e:?}")
}
}
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
if let Interaction::Command(command) = interaction {
let _ = command.defer_ephemeral(&ctx.http).await;
_ = command.defer_ephemeral(&ctx.http).await;
// println!("Received command interaction: {:#?}", command);
let content = match command.data.name.as_str() {
@ -190,7 +179,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
"link_minecraft" => commands::minecraft::user::add::run(&command, &ctx).await,
"docs" => commands::wolves::link_docs::users::run(&command, &ctx).await,
// "link" => commands::count::servers::run(&command, &ctx).await,
&_ => format!("not implemented :( wolves {}", x.name.as_str()),
_ => format!("not implemented :( wolves {}", x.name.as_str()),
},
},
@ -205,7 +194,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
None => "error".to_string(),
Some(z) => match z.name.as_str() {
"change" => commands::server_icon::admin::change::run(&command, &ctx).await,
&_ => format!("not implemented :( count {}", x.name.as_str()),
_ => format!("not implemented :( count {}", x.name.as_str()),
},
},
_ => {
@ -214,7 +203,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
},
// TODO: move teh minecraft commands in here as a subgroup
// "link" => commands::count::servers::run(&command, &ctx).await,
&_ => format!("not implemented :( committee {}", x.name.as_str()),
_ => format!("not implemented :( committee {}", x.name.as_str()),
},
},
"minecraft_add" => commands::minecraft::server::add::run(&command, &ctx).await,
@ -226,7 +215,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
Some(x) => match x.name.as_str() {
"committee" => commands::count::committee::run(&command, &ctx).await,
"servers" => commands::count::servers::run(&command, &ctx).await,
&_ => format!("not implemented :( count {}", x.name.as_str()),
_ => format!("not implemented :( count {}", x.name.as_str()),
},
},
@ -240,16 +229,16 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
Some(z) => match z.name.as_str() {
"icon" => commands::server_icon::user::current::icon::run(&command, &ctx).await,
"festival" => commands::server_icon::user::current::festival::run(&command, &ctx).await,
&_ => format!("not implemented :( count {}", x.name.as_str()),
_ => format!("not implemented :( count {}", x.name.as_str()),
},
},
&_ => format!("not implemented :( {}", command.data.name.as_str()),
_ => format!("not implemented :( {}", command.data.name.as_str()),
};
result
}
"stats" => commands::server_icon::user::stats::run(&command, &ctx).await,
&_ => format!("not implemented :( count {}", x.name.as_str()),
_ => format!("not implemented :( count {}", x.name.as_str()),
},
},
_ => format!("not implemented :( {}", command.data.name.as_str()),