From dfa96910bb50bacd506684571952a4e811f060a0 Mon Sep 17 00:00:00 2001 From: Niko Date: Sat, 16 Nov 2024 14:42:33 -0700 Subject: [PATCH] Actually implement Kiai API stuffs --- Cargo.lock | 2 + scripty_bot_utils/Cargo.toml | 1 + scripty_bot_utils/src/error/error_type.rs | 12 +++++ scripty_commands/Cargo.toml | 1 + .../src/cmds/config/kiai_enabled.rs | 49 +++++++++++++++++++ scripty_commands/src/cmds/config/mod.rs | 2 + scripty_commands/src/lib.rs | 1 + scripty_i18n/locales/en.ftl | 12 +++++ scripty_integrations/src/kiai/error.rs | 12 ++++- scripty_integrations/src/kiai/http_client.rs | 17 ++++++- 10 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 scripty_commands/src/cmds/config/kiai_enabled.rs diff --git a/Cargo.lock b/Cargo.lock index df23c484..1ed18e49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3285,6 +3285,7 @@ dependencies = [ "scripty_data_type", "scripty_db", "scripty_i18n", + "scripty_integrations", "scripty_metrics", "scripty_premium", "scripty_redis", @@ -3334,6 +3335,7 @@ dependencies = [ "scripty_data_storage", "scripty_db", "scripty_i18n", + "scripty_integrations", "scripty_premium", "scripty_redis", "scripty_utils", diff --git a/scripty_bot_utils/Cargo.toml b/scripty_bot_utils/Cargo.toml index fad934cd..f5002ff7 100644 --- a/scripty_bot_utils/Cargo.toml +++ b/scripty_bot_utils/Cargo.toml @@ -29,6 +29,7 @@ scripty_premium = { path = "../scripty_premium" } scripty_botlists = { path = "../scripty_botlists" } scripty_data_type = { path = "../scripty_data_type" } scripty_data_storage = { path = "../scripty_data_storage" } +scripty_integrations = { path = "../scripty_integrations" } scripty_audio_handler = { path = "../scripty_audio_handler" } tokio = { version = "1", features = ["parking_lot", "signal"] } reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } diff --git a/scripty_bot_utils/src/error/error_type.rs b/scripty_bot_utils/src/error/error_type.rs index 7ea2234a..9af6e2c2 100644 --- a/scripty_bot_utils/src/error/error_type.rs +++ b/scripty_bot_utils/src/error/error_type.rs @@ -40,6 +40,7 @@ pub enum ErrorEnum { ExpectedPremiumValue, AudioTranscription(GenericMessageError), CallAlreadyExists, + KiaiError(scripty_integrations::kiai::KiaiApiError), Custom(String), } @@ -230,6 +231,7 @@ impl Display for Error { } Custom(e) => format!("Custom error: {}", e).into(), AudioTranscription(e) => format!("Failed to transcribe audio message: {}", e).into(), + KiaiError(e) => format!("Kiai API error: {}", e).into(), CallAlreadyExists => "a call for this channel already exists - not trying to rejoin \ the same channel" .into(), @@ -254,6 +256,7 @@ impl StdError for Error { Transcription(e) => Some(e), ExpectedPremiumValue => None, AudioTranscription(e) => Some(e), + KiaiError(e) => Some(e), CallAlreadyExists => None, Custom(_) => None, } @@ -382,3 +385,12 @@ impl From for Error { } } } + +impl From for Error { + fn from(e: scripty_integrations::kiai::KiaiApiError) -> Self { + Self { + err: ErrorEnum::KiaiError(e), + bt: Backtrace::new(), + } + } +} diff --git a/scripty_commands/Cargo.toml b/scripty_commands/Cargo.toml index f778b45b..5a0e48c7 100644 --- a/scripty_commands/Cargo.toml +++ b/scripty_commands/Cargo.toml @@ -22,6 +22,7 @@ scripty_automod = { path = "../scripty_automod" } scripty_premium = { path = "../scripty_premium" } scripty_bot_utils = { path = "../scripty_bot_utils" } scripty_data_storage = { path = "../scripty_data_storage" } +scripty_integrations = { path = "../scripty_integrations" } scripty_audio_handler = { path = "../scripty_audio_handler" } tokio = { version = "1", features = ["parking_lot", "signal"] } serenity = { git = "https://github.com/serenity-rs/serenity", branch = "next", features = [ diff --git a/scripty_commands/src/cmds/config/kiai_enabled.rs b/scripty_commands/src/cmds/config/kiai_enabled.rs new file mode 100644 index 00000000..faf6962e --- /dev/null +++ b/scripty_commands/src/cmds/config/kiai_enabled.rs @@ -0,0 +1,49 @@ +use scripty_bot_utils::{checks::is_guild, Context, Error}; +use scripty_integrations::kiai::{get_kiai_api_client, Permissions as KiaiPermissions}; + +/// Enable Scripty's Kiai integration. You should disable Kiai's voice XP levelling if you use this. +#[poise::command( + prefix_command, + slash_command, + check = "is_guild", + required_permissions = "MANAGE_GUILD", + rename = "enable_kiai" +)] +pub async fn config_enable_kiai(ctx: Context<'_>, enable_kiai: Option) -> Result<(), Error> { + let guild_id = ctx + .guild_id() + .map(|g| g.get()) + .ok_or_else(Error::expected_guild)?; + let resolved_language = + scripty_i18n::get_resolved_language(ctx.author().id.get(), Some(guild_id)).await; + + let i18n_string = if let Some(enable_kiai) = enable_kiai { + let kc = get_kiai_api_client(); + let perms = kc.get_permissions(guild_id).await?; + if perms.contains(KiaiPermissions::LEVELS) { + sqlx::query!( + "INSERT INTO guilds (guild_id, kiai_enabled) VALUES ($1, $2) ON CONFLICT \ + (guild_id) DO UPDATE SET kiai_enabled = $2", + guild_id as i64, + enable_kiai + ) + .execute(scripty_db::get_db()) + .await?; + + if enable_kiai { + "config-kiai-enabled" + } else { + "config-kiai-disabled" + } + } else { + "config-kiai-missing-perms" + } + } else { + "config-kiai-info" + }; + + ctx.say(format_message!(resolved_language, i18n_string)) + .await?; + + Ok(()) +} diff --git a/scripty_commands/src/cmds/config/mod.rs b/scripty_commands/src/cmds/config/mod.rs index 3ea22f16..61752cc5 100644 --- a/scripty_commands/src/cmds/config/mod.rs +++ b/scripty_commands/src/cmds/config/mod.rs @@ -1,4 +1,5 @@ mod auto_detect_lang; +mod kiai_enabled; mod language; mod transcribe_audio; mod transcribe_only_role; @@ -8,6 +9,7 @@ mod translate; mod verbose; pub use auto_detect_lang::config_auto_detect_lang; +pub use kiai_enabled::config_enable_kiai; pub use language::config_server_language; use poise::CreateReply; use scripty_bot_utils::{checks::is_guild, Context, Error}; diff --git a/scripty_commands/src/lib.rs b/scripty_commands/src/lib.rs index 547f5920..a8f2d4bb 100644 --- a/scripty_commands/src/lib.rs +++ b/scripty_commands/src/lib.rs @@ -64,6 +64,7 @@ pub fn build_commands() -> Vec> { cmds::config::config_auto_detect_lang(), cmds::config::config_transcribe_only_role(), cmds::config::config_translate(), + cmds::config::config_enable_kiai(), ], subcommand_required: true, ..cmds::config::config_root() diff --git a/scripty_i18n/locales/en.ftl b/scripty_i18n/locales/en.ftl index 94a2f467..d383b9de 100644 --- a/scripty_i18n/locales/en.ftl +++ b/scripty_i18n/locales/en.ftl @@ -163,6 +163,18 @@ config-translate-enabled = Scripty will now translate transcriptions to English. config-translate-disabled = Scripty will now attempt to match the phrases being spoken to English words, but will not translate. config-translate-not-english = You must set your language to English to enable translation. Do so with `{ $contextPrefix }config language en`. +## config - enable_kiai command +config_enable_kiai = enable_kiai + .description = Enable Scripty's Kiai integration. Run this command with no arguments to get info on Kiai. + .enable_kiai = enable_kiai + .enable_kiai-description = Defaults to false +config-kiai-enabled = Scripty will now send any voice XP gained to Kiai. Disable Kiai's voice XP leveling to prevent users getting double XP. +config-kiai-disabled = Scripty will no longer send any voice XP gained to Kiai's API. +config-kiai-info = You can find more info about Kiai at [https://www.kiai.app/](https://www.kiai.app/?utm_source=scripty_info). + {""} + If you use this integration, be sure to disable Kiai's voice XP module as they will conflict. +config-kiai-missing-perms = Scripty is missing permissions to work in this server. Authorize it with the `/application authorize` command, using an application ID of `811652199100317726`, and giving Scripty the "view and edit all levels and XP" permission. + ## Help menu translation strings command-not-found = No command with name `{ $commandName }` found. diff --git a/scripty_integrations/src/kiai/error.rs b/scripty_integrations/src/kiai/error.rs index af1d2ac5..12918319 100644 --- a/scripty_integrations/src/kiai/error.rs +++ b/scripty_integrations/src/kiai/error.rs @@ -1,4 +1,4 @@ -use std::fmt; +use std::{fmt, num::ParseIntError}; use serde::{Deserialize, Serialize}; @@ -15,8 +15,11 @@ pub enum KiaiApiError { status: reqwest::StatusCode, body: String, }, + BadInteger(ParseIntError), } +impl std::error::Error for KiaiApiError {} + #[derive(Debug, Serialize, Deserialize)] pub struct BadRequestPayload { pub error: String, @@ -56,7 +59,14 @@ impl fmt::Display for KiaiApiError { Self::Unauthorized(msg) => write!(f, "Unauthorized: {}", msg), Self::TooManyRequests(payload) => write!(f, "TooManyRequests: {}", payload.message), Self::Unknown { status, body } => write!(f, "Unknown: {} {}", status, body), + Self::BadInteger(e) => write!(f, "Invalid integer received: {}", e), }?; f.write_str(" }") } } + +impl From for KiaiApiError { + fn from(value: ParseIntError) -> Self { + Self::BadInteger(value) + } +} diff --git a/scripty_integrations/src/kiai/http_client.rs b/scripty_integrations/src/kiai/http_client.rs index 14fb3f47..3d3acb2e 100644 --- a/scripty_integrations/src/kiai/http_client.rs +++ b/scripty_integrations/src/kiai/http_client.rs @@ -1,6 +1,6 @@ use reqwest::{Client as ReqwestClient, StatusCode}; -use crate::kiai::{KiaiApiError, KiaiApiResult, KiaiPostVirtualMessage}; +use crate::kiai::{KiaiApiError, KiaiApiResult, KiaiPostVirtualMessage, Permissions}; #[derive(Debug)] pub struct KiaiHttpClient { @@ -33,6 +33,21 @@ impl KiaiHttpClient { self.decode_response(res).await } + pub async fn get_permissions(&self, guild_id: u64) -> KiaiApiResult { + let url = format!("https://api.kiaibot.com/v1/guild/{}/permissions", guild_id); + + let res = self + .client + .get(&url) + .header(reqwest::header::AUTHORIZATION, &self.token) + .send() + .await?; + + Ok(Permissions::from_bits_retain( + res.text().await?.trim().parse()?, + )) + } + async fn decode_response(&self, res: reqwest::Response) -> KiaiApiResult where for<'de> T: serde::Deserialize<'de>,