|
1 | | -use std::fmt::Write as _; |
| 1 | +use std::{borrow::Cow, fmt::Write as _}; |
2 | 2 |
|
3 | 3 | use aformat::{ArrayString, aformat, aformat_into}; |
4 | 4 |
|
@@ -33,9 +33,11 @@ fn get_premium_guilds<'a>( |
33 | 33 | async fn get_premium_guild_count<'a>( |
34 | 34 | conn: impl sqlx::PgExecutor<'a> + 'a, |
35 | 35 | premium_user: serenity::UserId, |
36 | | -) -> Result<i64> { |
37 | | - let guilds = get_premium_guilds(conn, premium_user); |
38 | | - Ok(guilds.count().await as i64) |
| 36 | +) -> Result<i64, sqlx::Error> { |
| 37 | + sqlx::query_scalar("SELECT count(*) FROM guilds WHERE premium_user = $1") |
| 38 | + .bind(premium_user.get() as i64) |
| 39 | + .fetch_one(conn) |
| 40 | + .await |
39 | 41 | } |
40 | 42 |
|
41 | 43 | /// Shows how you can help support TTS Bot's development and hosting! |
@@ -210,34 +212,78 @@ pub async fn list(ctx: Context<'_>) -> CommandResult { |
210 | 212 | category = "Premium", |
211 | 213 | prefix_command, |
212 | 214 | slash_command, |
213 | | - guild_only, |
214 | 215 | required_bot_permissions = "SEND_MESSAGES | EMBED_LINKS" |
215 | 216 | )] |
216 | | -pub async fn deactivate(ctx: Context<'_>) -> CommandResult { |
| 217 | +pub async fn deactivate( |
| 218 | + ctx: Context<'_>, |
| 219 | + #[autocomplete = "premium_guild_autocomplete"] server: serenity::GuildId, |
| 220 | +) -> CommandResult { |
| 221 | + let guild_id = server; |
217 | 222 | let data = ctx.data(); |
| 223 | + let cache = ctx.cache(); |
218 | 224 | let author = ctx.author(); |
219 | | - let guild_id = ctx.guild_id().unwrap(); |
220 | | - let guild_row = data.guilds_db.get(guild_id.get() as i64).await?; |
221 | 225 |
|
| 226 | + let guild_row = data.guilds_db.get(guild_id.get() as i64).await?; |
222 | 227 | let Some(premium_user) = guild_row.premium_user else { |
223 | | - let msg = "This server isn't activated for premium, so I can't deactivate it!"; |
| 228 | + let msg = "The selected server isn't activated for premium, so I can't deactivate it!"; |
224 | 229 | ctx.send_ephemeral(msg).await?; |
225 | 230 | return Ok(()); |
226 | 231 | }; |
227 | 232 |
|
228 | 233 | if premium_user != author.id { |
229 | | - let msg = "You are not setup as the premium user for this server, so cannot deactivate it!"; |
| 234 | + let msg = "You are not setup as the premium user for the selected server, so you cannot deactivate it!"; |
230 | 235 | ctx.send_ephemeral(msg).await?; |
231 | 236 | return Ok(()); |
232 | 237 | } |
233 | 238 |
|
234 | 239 | remove_premium(&data, guild_id).await?; |
235 | 240 |
|
236 | | - let msg = "Deactivated premium from this server."; |
237 | | - ctx.say(msg).await?; |
| 241 | + if Some(guild_id) == ctx.guild_id() { |
| 242 | + let msg = "Deactivated premium from this server."; |
| 243 | + ctx.say(msg).await?; |
| 244 | + } else { |
| 245 | + let msg = if let Some(guild) = cache.guild(guild_id) { |
| 246 | + &*format!("Deactivated premium from: {}", guild.name) |
| 247 | + } else { |
| 248 | + "Deactivated premium from: <unknown>" |
| 249 | + }; |
| 250 | + |
| 251 | + ctx.send_ephemeral(msg).await?; |
| 252 | + } |
| 253 | + |
238 | 254 | Ok(()) |
239 | 255 | } |
240 | 256 |
|
| 257 | +async fn premium_guild_autocomplete<'a>( |
| 258 | + ctx: Context<'a>, |
| 259 | + name: &'a str, |
| 260 | +) -> serenity::CreateAutocompleteResponse<'a> { |
| 261 | + let data = ctx.data(); |
| 262 | + let cache = ctx.cache(); |
| 263 | + |
| 264 | + let mut choices = Vec::new(); |
| 265 | + let mut guilds = get_premium_guilds(&data.pool, ctx.author().id); |
| 266 | + while let Some(Ok(guild_row)) = guilds.next().await { |
| 267 | + let guild_id = serenity::GuildId::new(guild_row.guild_id as u64); |
| 268 | + let Some(guild_name) = cache.guild(guild_id).map(|g| g.name.to_string()) else { |
| 269 | + continue; |
| 270 | + }; |
| 271 | + |
| 272 | + let guild_name_lower = guild_name.to_lowercase(); |
| 273 | + let value = serenity::AutocompleteValue::String(Cow::Owned(guild_id.to_string())); |
| 274 | + let choice = serenity::AutocompleteChoice::new(guild_name, value); |
| 275 | + choices.push((guild_name_lower, choice)); |
| 276 | + } |
| 277 | + |
| 278 | + let name_lower = name.to_lowercase(); |
| 279 | + choices.sort_by_cached_key(|(guild_name_lower, _)| { |
| 280 | + strsim::levenshtein(guild_name_lower, &name_lower) |
| 281 | + }); |
| 282 | + |
| 283 | + let choices: Vec<_> = choices.into_iter().map(|(_, choice)| choice).collect(); |
| 284 | + serenity::CreateAutocompleteResponse::new().set_choices(choices) |
| 285 | +} |
| 286 | + |
241 | 287 | pub fn commands() -> [Command; 1] { |
242 | 288 | [Command { |
243 | 289 | subcommands: vec![ |
|
0 commit comments