Skip to content

Commit

Permalink
Add option to send transcriptions to a non-discord webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
wilt00 committed Dec 19, 2023
1 parent a2c57eb commit b4ea58b
Show file tree
Hide file tree
Showing 17 changed files with 146 additions and 22 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions scripty_audio_handler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ tracing = "0.1"
backtrace = "0.3"
async-trait = "0.1"
parking_lot = "0.12"
reqwest = { version = "0.11", default-features = false, features = ["json", "rustls"] }
scripty_db = { path = "../scripty_db" }
scripty_stt = { path = "../scripty_stt" }
#scripty_tts = { path = "../scripty_tts" }
Expand Down Expand Up @@ -41,3 +42,4 @@ serenity = { git = "https://github.com/serenity-rs/serenity", branch = "next", f
"utils",
] }
sqlx = { version = "0.7", features = ["postgres", "macros", "migrate", "runtime-tokio-rustls"] }
url = "2"
68 changes: 65 additions & 3 deletions scripty_audio_handler/src/audio_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ use ahash::RandomState;
use dashmap::{DashMap, DashSet};
use parking_lot::RwLock;
use scripty_automod::types::AutomodServerConfig;
use scripty_utils::get_thirdparty_http;
use serenity::{
all::RoleId,
builder::ExecuteWebhook,
client::Context,
http::CacheHttp,
model::{
id::{ChannelId, GuildId},
webhook::Webhook,
webhook::Webhook as SerenityWebhook,
},
};
use songbird::{Event, EventContext, EventHandler};
use url::Url;

use crate::{
events::*,
Expand Down Expand Up @@ -55,7 +59,7 @@ pub struct AudioHandler {
channel_id: ChannelId,
voice_channel_id: ChannelId,
thread_id: Option<ChannelId>,
webhook: Arc<Webhook>,
webhook: Arc<WebhookWrapper>,
context: Context,
premium_level: Arc<AtomicU8>,
verbose: Arc<AtomicBool>,
Expand All @@ -68,10 +72,68 @@ pub struct AudioHandler {
translate: Arc<AtomicBool>,
}

#[derive(Clone)]
pub struct WebhookWrapper {
discord_webhook: SerenityWebhook,
url_override: Option<Url>,
}

impl WebhookWrapper {
pub fn new(discord_webhook: SerenityWebhook, url_override: Option<Url>) -> WebhookWrapper {
WebhookWrapper {
discord_webhook,
url_override,
}
}

pub async fn execute(
&self,
cache_http: impl CacheHttp,
wait: bool,
builder: ExecuteWebhook,
) -> Result<(), serenity::Error> {
match &self.url_override {
Some(url) => {
match get_thirdparty_http()
.post(url.clone())
.json(&builder)
.send()
.await
{
Err(e) => Err(serenity::Error::Http(
serenity::prelude::HttpError::Request(e),
)),
Ok(_) => {
// TODO: debug logging
Ok(())
}
}
}
None => {
match self
.discord_webhook
.execute(cache_http, wait, builder)
.await
{
Err(e) => Err(e),
Ok(_) => {
// TODO: debug logging
Ok(())
}
}
}
}
}

pub fn get_url_override(&self) -> Option<Url> {
self.url_override.clone()
}
}

impl AudioHandler {
pub async fn new(
guild_id: GuildId,
webhook: Webhook,
webhook: WebhookWrapper,
context: Context,
channel_id: ChannelId,
voice_channel_id: ChannelId,
Expand Down
6 changes: 4 additions & 2 deletions scripty_audio_handler/src/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use serenity::{
};
use songbird::{error::JoinError, events::Event, CoreEvent};

use crate::Error;
use crate::{audio_handler::WebhookWrapper, Error};

// TODO: implement `force`
#[allow(clippy::let_unit_value)]
Expand All @@ -20,12 +20,13 @@ pub async fn connect_to_vc(
thread_id: Option<ChannelId>,
_force: bool,
record_transcriptions: bool,
webhook_override_url: Option<url::Url>,
) -> Result<(), Error> {
debug!(%guild_id, "fetching webhook");
// thanks to Discord undocumented breaking changes, we have to do this
// <3 shitcord
let hooks = channel_id.webhooks(&ctx).await?;
let webhook = if hooks.is_empty() {
let discord_webhook = if hooks.is_empty() {
channel_id
.create_webhook(&ctx, CreateWebhook::new("Scripty Transcriptions"))
.await?
Expand All @@ -48,6 +49,7 @@ pub async fn connect_to_vc(
}
}
};
let webhook = WebhookWrapper::new(discord_webhook, webhook_override_url);

// automatically leave after the specified time period
let premium_tier = scripty_premium::get_guild(guild_id.get()).await;
Expand Down
9 changes: 6 additions & 3 deletions scripty_audio_handler/src/events/client_disconnect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@ use std::sync::{
};

use serenity::{
all::{ChannelId, Context, Webhook},
all::{ChannelId, Context},
builder::ExecuteWebhook,
};
use songbird::model::payload::ClientDisconnect;

use crate::{audio_handler::ArcSsrcMaps, types::TranscriptResults};
use crate::{
audio_handler::{ArcSsrcMaps, WebhookWrapper},
types::TranscriptResults,
};

pub async fn client_disconnect(
client_disconnect_data: ClientDisconnect,
ssrc_state: ArcSsrcMaps,
premium_level: Arc<AtomicU8>,
ctx: Context,
webhook: Arc<Webhook>,
webhook: Arc<WebhookWrapper>,
thread_id: Option<ChannelId>,
transcript_results: TranscriptResults,
) {
Expand Down
7 changes: 5 additions & 2 deletions scripty_audio_handler/src/events/driver_disconnect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ use serenity::{
all::UserId,
builder::{CreateAttachment, CreateMessage, ExecuteWebhook},
client::Context,
model::{id::ChannelId, webhook::Webhook},
model::id::ChannelId,
};
use songbird::{events::context_data::DisconnectReason, id::GuildId, model::CloseCode};

use crate::{
audio_handler::WebhookWrapper,
connect_to_vc,
error::ErrorKind,
types::{SeenUsers, TranscriptResults},
Expand All @@ -18,7 +19,7 @@ pub async fn driver_disconnect(
guild_id: GuildId,
reason: Option<DisconnectReason>,
ctx: Context,
webhook: Arc<Webhook>,
webhook: Arc<WebhookWrapper>,
channel_id: ChannelId,
voice_channel_id: ChannelId,
thread_id: Option<ChannelId>,
Expand Down Expand Up @@ -76,6 +77,7 @@ pub async fn driver_disconnect(
// retry connection in 30 seconds
let record_transcriptions = transcript_results.is_some();
let webhook2 = webhook.clone();
let webhook_override_url = webhook.get_url_override();
let ctx2 = ctx.clone();
let ctx3 = ctx.clone();
tokio::spawn(async move {
Expand All @@ -91,6 +93,7 @@ pub async fn driver_disconnect(
thread_id,
false,
record_transcriptions,
webhook_override_url,
)
.await
.map_err(|x| x.kind)
Expand Down
8 changes: 4 additions & 4 deletions scripty_audio_handler/src/events/voice_tick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ use scripty_automod::types::{AutomodRuleAction, AutomodServerConfig};
use scripty_metrics::Metrics;
use scripty_stt::{ModelError, Stream};
use serenity::{
all::{ChannelId as SerenityChannelId, ChannelId, GuildId, Webhook},
all::{ChannelId as SerenityChannelId, ChannelId, GuildId},
builder::{CreateEmbed, CreateMessage, EditMember, ExecuteWebhook},
client::Context,
};
use songbird::events::context_data::VoiceTick;

use crate::{
audio_handler::SsrcMaps,
audio_handler::{SsrcMaps, WebhookWrapper},
consts::SIZE_OF_I16,
types::{SsrcUserDataMap, TranscriptResults},
};
Expand All @@ -32,7 +32,7 @@ pub async fn voice_tick(
language: Arc<RwLock<String>>,
verbose: Arc<AtomicBool>,
ctx: Context,
webhook: Arc<Webhook>,
webhook: Arc<WebhookWrapper>,
thread_id: Option<ChannelId>,
transcript_results: Option<Arc<RwLock<Vec<String>>>>,
automod_server_cfg: Arc<AutomodServerConfig>,
Expand Down Expand Up @@ -108,7 +108,7 @@ async fn handle_silent_speakers(
automod_server_cfg,
transcript_results,
ctx,
auto_detect_lang,
auto_detect_lang: _,
translate,
}: SilentSpeakersContext<'_>,
) -> Vec<(ExecuteWebhook, u32)> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,26 @@ use scripty_botlists::*;
use scripty_config::BotListsConfig;
use serenity::client::Context;

use scripty_utils::get_thirdparty_http;

use crate::{background_tasks::core::BackgroundTask, Error};

pub struct BotListUpdater {
ctx: Context,
bot_lists: Arc<Vec<BotLists>>,
client: reqwest::Client,
}

#[async_trait]
impl BackgroundTask for BotListUpdater {
async fn init(ctx: Context) -> Result<Self, Error> {
let mut bot_lists = vec![];
let bot_id = ctx.cache.current_user().id.get();
let client = reqwest::Client::new();

add_bot_lists(&mut bot_lists, bot_id);

Ok(Self {
ctx,
bot_lists: Arc::new(bot_lists),
client,
})
}

Expand All @@ -38,9 +37,10 @@ impl BackgroundTask for BotListUpdater {
server_count: self.ctx.cache.guild_count(),
shard_count: self.ctx.cache.shard_count().get(),
};
let client = get_thirdparty_http();

for list in self.bot_lists.iter() {
if let Err(e) = list.post_stats(&self.client, stats).await {
if let Err(e) = list.post_stats(&client, stats).await {
error!("Failed to post stats to bot list: {}", e);
}
}
Expand Down
1 change: 1 addition & 0 deletions scripty_bot_utils/src/handler/normal/voice_state_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ pub async fn voice_state_update(ctx: Context, _: Option<VoiceState>, new: VoiceS
None,
false,
false,
None,
)
.await
{
Expand Down
1 change: 1 addition & 0 deletions scripty_commands/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ serenity = { git = "https://github.com/serenity-rs/serenity", branch = "next", f
sqlx = { version = "0.7", features = ["postgres", "macros", "migrate", "runtime-tokio-rustls", "time"] }
poise = { git = "https://github.com/serenity-rs/poise", branch = "serenity-next", features = ["cache", "collector"] }
rand = "0.8.5"
url = "2"
28 changes: 24 additions & 4 deletions scripty_commands/src/cmds/join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use serenity::{
model::channel::{ChannelType, GuildChannel},
prelude::Mentionable,
};
use url::Url;

use crate::{Context, Error};

Expand Down Expand Up @@ -40,6 +41,9 @@ pub async fn join(

#[description = "Create a new thread for this transcription? Defaults to false."]
create_thread: Option<bool>,

#[description = "Send transcribed messages to this webhook instead of Discord."]
message_webhook: Option<String>,
) -> Result<(), Error> {
let resolved_language =
scripty_i18n::get_resolved_language(ctx.author().id.get(), ctx.guild_id().map(|g| g.get()))
Expand Down Expand Up @@ -248,10 +252,25 @@ pub async fn join(
(None, target_channel.id)
};

let output_channel_mention = if let Some(ref target_thread) = target_thread {
target_thread.mention().to_string()
} else {
target_channel.mention().to_string()
let mut url_override: Option<Url> = None;
match message_webhook {
Some(url_str) => match Url::parse(&url_str) {
Ok(parsed_url) => url_override = Some(parsed_url),
Err(e) => {
ctx.say(
format_message!(resolved_language, "join-invalid-url", error: e.to_string()),
)
.await?;
return Ok(());
}
},
None => (),
}

let output_channel_mention = match (&target_thread, &url_override) {
(_, Some(url)) => url.to_string(),
(Some(thread), _) => thread.mention().to_string(),
(_, _) => target_channel.mention().to_string(),
};
let res = scripty_audio_handler::connect_to_vc(
ctx.serenity_context().clone(),
Expand All @@ -261,6 +280,7 @@ pub async fn join(
target_thread.map(|x| x.id),
false,
record_transcriptions,
url_override,
)
.await;
match res {
Expand Down
Loading

0 comments on commit b4ea58b

Please sign in to comment.