166 lines
7.2 KiB
Rust
166 lines
7.2 KiB
Rust
use futures::TryStreamExt;
|
|
use std::sync::LazyLock;
|
|
use twilight_model::{
|
|
application::{
|
|
command::{Command, CommandType},
|
|
interaction::Interaction,
|
|
},
|
|
channel::message::MessageFlags,
|
|
http::interaction::{InteractionResponse, InteractionResponseType},
|
|
};
|
|
use twilight_util::builder::{
|
|
InteractionResponseDataBuilder,
|
|
command::CommandBuilder,
|
|
embed::{EmbedAuthorBuilder, EmbedBuilder, EmbedFieldBuilder, EmbedFooterBuilder},
|
|
};
|
|
|
|
use crate::{build_info, command::State};
|
|
|
|
const NAME: &str = "info";
|
|
const DESCRIPTION: &str = "Show various information";
|
|
|
|
pub static COMMAND: LazyLock<Command> = LazyLock::new(|| {
|
|
CommandBuilder::new(NAME, DESCRIPTION, CommandType::ChatInput)
|
|
.validate()
|
|
.expect("command wasn't correct")
|
|
.build()
|
|
});
|
|
|
|
#[tracing::instrument]
|
|
pub async fn handle(state: State, interaction: Interaction) {
|
|
let revision = build_info::COMMIT_HASH;
|
|
|
|
let bot_owner_user_id = state.discord_bot_owner_user_id;
|
|
|
|
let is_bot_owner = interaction
|
|
.member
|
|
.as_ref()
|
|
.and_then(|member| member.user.as_ref().map(|user| user.id))
|
|
.map(|user_id| user_id == bot_owner_user_id)
|
|
.unwrap_or(false);
|
|
|
|
let bot_owner_mention = format!("<@{}>", bot_owner_user_id);
|
|
|
|
let opt_in_mention = format!(
|
|
"</{}:{}>",
|
|
state.discord_opt_in_command_name, state.discord_opt_in_command_id
|
|
);
|
|
let opt_out_mention = format!(
|
|
"</{}:{}>",
|
|
state.discord_opt_out_command_name, state.discord_opt_out_command_id
|
|
);
|
|
|
|
state
|
|
.discord_client
|
|
.interaction(state.discord_application_id)
|
|
.create_response(
|
|
interaction.id,
|
|
&interaction.token,
|
|
&InteractionResponse {
|
|
kind: InteractionResponseType::ChannelMessageWithSource,
|
|
data: Some(
|
|
InteractionResponseDataBuilder::new().embeds([
|
|
EmbedBuilder::new()
|
|
.title("About This Bot")
|
|
.description(format!("This bot intends to record VCs it's in. You can opt out with {opt_out_mention} or explicitly opt in with {opt_in_mention} (I'd appreciate this one). Here are some pledges backed by faith (because there is no way to verify them yourself) in {bot_owner_mention}:"))
|
|
.field(
|
|
EmbedFieldBuilder::new("Recordings are never shared", "Audio recordings are only stored on my home server and desktop computer and will never be uploaded to services or hardware that is owned by another person: not even curated clips, and not even to people who were in the recording. When transcription to text is implemented, this will only be run on my personally owned devices and not on any internet or cloud offering.").build()
|
|
)
|
|
.field(
|
|
EmbedFieldBuilder::new("You won't be \"audited\"", "I will not reference things said in past recordings with the goal of \"making a point\", nor pull them up on the spot (even by the request of the person who said it). Ideally, these are just peace of mind for me that I'm not missing out by not being in a Discord call all the time and can take my life back, so using them in an unhealthy way isn't in my interest.").build()
|
|
)
|
|
.field(
|
|
EmbedFieldBuilder::new("Code is publicly available", format!("The latest source code is at https://gitea.katniss.top/jacob/fomo-reducer so that I don't have to write guarantees about the technology here (e.g. what data is acquired, how it's used or stored) and you can just check it yourself. To that end: this bot is running revision `{revision}` at the time of this message.")).build()
|
|
)
|
|
.footer(
|
|
EmbedFooterBuilder::new("Thanks for your patience and understanding as I have bad and unusual mental health and it's crazy that I need this. This - especially if I learn if I can record streams or webcams so I don't miss out on those experiences either - should be the end of abrasion and force about how we spend our time. Again, thank you, I appreciate it.")
|
|
)
|
|
.validate()
|
|
.unwrap()
|
|
.build()
|
|
])
|
|
.flags(MessageFlags::EPHEMERAL)
|
|
.build()
|
|
)
|
|
})
|
|
.await
|
|
.expect("TODO");
|
|
|
|
if is_bot_owner {
|
|
let heat_script_description = state
|
|
.bot_manager
|
|
.with(|bot_data| {
|
|
let heat_script_option = bot_data.has_heat_script().then(|| {
|
|
bot_data
|
|
.get_heat_script()
|
|
.expect("TODO")
|
|
.to_str()
|
|
.expect("TODO")
|
|
});
|
|
heat_script_option.map_or("none set yet".into(), |heat_script| {
|
|
format!("```\n{heat_script}\n```")
|
|
})
|
|
})
|
|
.await
|
|
.expect("TODO");
|
|
|
|
state
|
|
.discord_client
|
|
.interaction(state.discord_application_id)
|
|
.create_followup(&interaction.token)
|
|
.embeds(&[EmbedBuilder::new()
|
|
.title("Bot Data")
|
|
.field(EmbedFieldBuilder::new("Heat Script", heat_script_description).build())
|
|
.validate()
|
|
.unwrap()
|
|
.build()])
|
|
.flags(MessageFlags::EPHEMERAL)
|
|
.await
|
|
.expect("TODO");
|
|
|
|
let mut user_id_stream = state.user_manager.list().await.expect("TODO");
|
|
|
|
while let Some(user_id) = user_id_stream.try_next().await.expect("TODO") {
|
|
let (consent, notification_script) = state
|
|
.user_manager
|
|
.with(user_id, |user_data| {
|
|
let consent = user_data.get_voice_recording_consent().unwrap();
|
|
let notification_script = user_data.has_notification_script().then_some(
|
|
user_data
|
|
.get_notification_script()
|
|
.expect("TODO")
|
|
.to_string()
|
|
.expect("TODO"),
|
|
);
|
|
|
|
(consent, notification_script)
|
|
})
|
|
.await
|
|
.expect("TODO");
|
|
|
|
let user_mention = format!("<@{user_id}>");
|
|
|
|
state
|
|
.discord_client
|
|
.interaction(state.discord_application_id)
|
|
.create_followup(&interaction.token)
|
|
.embeds(&[EmbedBuilder::new()
|
|
.author(EmbedAuthorBuilder::new(user_mention))
|
|
.field(EmbedFieldBuilder::new("Consent", format!("{consent:?}")).build())
|
|
.field(
|
|
EmbedFieldBuilder::new(
|
|
"Notification Script",
|
|
format!("{notification_script:?}"),
|
|
)
|
|
.build(),
|
|
)
|
|
.validate()
|
|
.unwrap()
|
|
.build()])
|
|
.flags(MessageFlags::EPHEMERAL)
|
|
.await
|
|
.expect("TODO");
|
|
}
|
|
}
|
|
}
|