mirror of
https://github.com/System-End/plura.git
synced 2026-04-19 16:28:21 +00:00
refactor: refactor interactions
This commit is contained in:
parent
561d07efe2
commit
9c0b51db2b
1 changed files with 119 additions and 61 deletions
|
|
@ -4,12 +4,13 @@ use std::error::Error;
|
|||
use std::sync::Arc;
|
||||
|
||||
use axum::Extension;
|
||||
use error_stack::Report;
|
||||
use member::{create_member, edit_member};
|
||||
use slack_morphism::prelude::*;
|
||||
use tracing::{debug, error};
|
||||
use trigger::{create_trigger, edit_trigger};
|
||||
|
||||
use crate::fields;
|
||||
use crate::BOT_TOKEN;
|
||||
use crate::models::system::System;
|
||||
use crate::models::{self, Trusted, user};
|
||||
|
||||
|
|
@ -34,69 +35,72 @@ async fn interaction_event(
|
|||
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
match event {
|
||||
SlackInteractionEvent::ViewSubmission(slack_interaction_view_submission_event) => {
|
||||
match slack_interaction_view_submission_event.view.view {
|
||||
SlackView::Home(view) => {
|
||||
debug!(?view, "Received home view");
|
||||
Ok(())
|
||||
}
|
||||
SlackView::Modal(ref view) => {
|
||||
debug!(?view, "Received modal view");
|
||||
|
||||
let user_id: user::Id<Trusted> =
|
||||
slack_interaction_view_submission_event.user.id.into();
|
||||
let states = states.read().await;
|
||||
let user_state = states.get_user_state::<user::State>().unwrap();
|
||||
|
||||
fields!(user_id = %&user_id);
|
||||
|
||||
let Some(view_state) = slack_interaction_view_submission_event
|
||||
.view
|
||||
.state_params
|
||||
.state
|
||||
else {
|
||||
error!("No state found in view submission");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
handle_modal_view(
|
||||
client,
|
||||
view_state,
|
||||
user_state,
|
||||
user_id,
|
||||
view.external_id.as_deref(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
handle_view_submission(slack_interaction_view_submission_event, client, states).await
|
||||
}
|
||||
SlackInteractionEvent::Shortcut(shortcut) => {
|
||||
debug!(?shortcut, "Received shortcut event");
|
||||
todo!()
|
||||
}
|
||||
event => {
|
||||
debug!("Received interaction event: {:#?}", event);
|
||||
debug!(?event, "Received interaction event",);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(client, view_state, user_state))]
|
||||
async fn handle_view_submission(
|
||||
view_submission: SlackInteractionViewSubmissionEvent,
|
||||
client: Arc<SlackHyperClient>,
|
||||
states: SlackClientEventsUserState,
|
||||
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
match view_submission.view.view {
|
||||
SlackView::Home(view) => {
|
||||
debug!(?view, "Received home view");
|
||||
Ok(())
|
||||
}
|
||||
SlackView::Modal(view) => {
|
||||
debug!(?view, "Received modal view");
|
||||
|
||||
let user_id: user::Id<Trusted> = view_submission.user.id.into();
|
||||
|
||||
let Some(view_state) = view_submission.view.state_params.state else {
|
||||
error!("No state found in modal view submission");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
handle_modal_view(client, view, view_state, states, user_id).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(client, view, states))]
|
||||
async fn handle_modal_view(
|
||||
client: Arc<SlackHyperClient>,
|
||||
view: SlackModalView,
|
||||
view_state: SlackViewState,
|
||||
user_state: &user::State,
|
||||
states: SlackClientEventsUserState,
|
||||
user_id: user::Id<Trusted>,
|
||||
external_id: Option<&str>,
|
||||
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
) {
|
||||
let states = states.read().await;
|
||||
let user_state = states.get_user_state::<user::State>().unwrap();
|
||||
let external_id = view.external_id.as_deref();
|
||||
|
||||
match external_id {
|
||||
None => {
|
||||
error!(
|
||||
"No external id found in modal view. To the person that created the modal: How do you expect the bot to figure out what to do?"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
Some("create_member") => {
|
||||
debug!("Received create member modal view");
|
||||
|
||||
create_member(view_state, &client, user_state, user_id).await?;
|
||||
|
||||
Ok(())
|
||||
if let Err(error) =
|
||||
create_member(view_state, &client, user_state, user_id.clone()).await
|
||||
{
|
||||
handle_user_error(error, user_id.into(), client).await;
|
||||
}
|
||||
}
|
||||
Some(id) if id.starts_with("edit_member_") => {
|
||||
debug!("Received edit member modal view");
|
||||
|
|
@ -111,22 +115,31 @@ async fn handle_modal_view(
|
|||
id,
|
||||
"Failed to parse member id from external id. Bailing in case this was a malicious call",
|
||||
);
|
||||
return Ok(());
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(trusted_member_id) =
|
||||
member_id.validate_by_user(&user_id, &user_state.db).await?
|
||||
// TO-DO: better handling of Err case
|
||||
let Ok(Some(trusted_member_id)) =
|
||||
member_id.validate_by_user(&user_id, &user_state.db).await
|
||||
else {
|
||||
error!(
|
||||
id,
|
||||
"Failed to validate member id from external id. Bailing in case this was a malicious call",
|
||||
);
|
||||
return Ok(());
|
||||
return;
|
||||
};
|
||||
|
||||
edit_member(view_state, &client, user_state, user_id, trusted_member_id).await?;
|
||||
|
||||
Ok(())
|
||||
if let Err(error) = edit_member(
|
||||
view_state,
|
||||
&client,
|
||||
user_state,
|
||||
user_id.clone(),
|
||||
trusted_member_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
handle_user_error(error, user_id.into(), client).await;
|
||||
}
|
||||
}
|
||||
Some(id) if id.starts_with("create_trigger_") => {
|
||||
debug!("Creating trigger");
|
||||
|
|
@ -138,18 +151,28 @@ async fn handle_modal_view(
|
|||
.map(models::member::Id::new)
|
||||
.expect("Failed to parse member id from external id");
|
||||
|
||||
let Some(trusted_member_id) =
|
||||
member_id.validate_by_user(&user_id, &user_state.db).await?
|
||||
// TO-DO: Better handling of Err case
|
||||
let Ok(Some(trusted_member_id)) =
|
||||
member_id.validate_by_user(&user_id, &user_state.db).await
|
||||
else {
|
||||
error!(
|
||||
id,
|
||||
"Failed to validate member id from external id. Bailing in case this was a malicious call",
|
||||
);
|
||||
return Ok(());
|
||||
return;
|
||||
};
|
||||
|
||||
create_trigger(view_state, &client, user_state, user_id, trusted_member_id).await?;
|
||||
Ok(())
|
||||
if let Err(error) = create_trigger(
|
||||
view_state,
|
||||
&client,
|
||||
user_state,
|
||||
user_id.clone(),
|
||||
trusted_member_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
handle_user_error(error, user_id.into(), client).await;
|
||||
};
|
||||
}
|
||||
Some(id) if id.starts_with("edit_trigger_") => {
|
||||
debug!("Editing trigger");
|
||||
|
|
@ -170,7 +193,7 @@ async fn handle_modal_view(
|
|||
%user_id,
|
||||
"Failed to fetch system id for user id. Bailing in case this was a malicious call"
|
||||
);
|
||||
return Ok(());
|
||||
return;
|
||||
};
|
||||
|
||||
let Ok(trusted_trigger_id) = trigger_id
|
||||
|
|
@ -181,15 +204,50 @@ async fn handle_modal_view(
|
|||
"Failed to validate member id from external id {}. Bailing in case this was a malicious call",
|
||||
id
|
||||
);
|
||||
return Ok(());
|
||||
return;
|
||||
};
|
||||
|
||||
edit_trigger(view_state, &client, user_state, user_id, trusted_trigger_id).await?;
|
||||
Ok(())
|
||||
if let Err(error) = edit_trigger(
|
||||
view_state,
|
||||
&client,
|
||||
user_state,
|
||||
user_id.clone(),
|
||||
trusted_trigger_id,
|
||||
)
|
||||
.await
|
||||
{
|
||||
handle_user_error(error, user_id.into(), client.clone()).await;
|
||||
}
|
||||
}
|
||||
Some(id) => {
|
||||
error!("receieved unknown external id: {id}");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_user_error<E>(
|
||||
error: Report<E>,
|
||||
user: SlackUserId,
|
||||
client: Arc<SlackHyperClient>,
|
||||
) where
|
||||
E: std::error::Error + Send + Sync + 'static,
|
||||
{
|
||||
error!(?error);
|
||||
|
||||
let session = client.open_session(&BOT_TOKEN);
|
||||
|
||||
let conversation = session
|
||||
.conversations_open(&SlackApiConversationsOpenRequest::new().with_users(vec![user.clone()]))
|
||||
.await
|
||||
.expect("Expected to be able to open conversation")
|
||||
.channel;
|
||||
|
||||
session
|
||||
.chat_post_ephemeral(&SlackApiChatPostEphemeralRequest::new(
|
||||
conversation.id,
|
||||
user,
|
||||
SlackMessageContent::new().with_text(format!("An error occured! {error}",)),
|
||||
))
|
||||
.await
|
||||
.expect("Expected to be able to post ephemeral message");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue