mirror of
https://github.com/System-End/plura.git
synced 2026-04-19 18:35:12 +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 std::sync::Arc;
|
||||||
|
|
||||||
use axum::Extension;
|
use axum::Extension;
|
||||||
|
use error_stack::Report;
|
||||||
use member::{create_member, edit_member};
|
use member::{create_member, edit_member};
|
||||||
use slack_morphism::prelude::*;
|
use slack_morphism::prelude::*;
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
use trigger::{create_trigger, edit_trigger};
|
use trigger::{create_trigger, edit_trigger};
|
||||||
|
|
||||||
use crate::fields;
|
use crate::BOT_TOKEN;
|
||||||
use crate::models::system::System;
|
use crate::models::system::System;
|
||||||
use crate::models::{self, Trusted, user};
|
use crate::models::{self, Trusted, user};
|
||||||
|
|
||||||
|
|
@ -34,69 +35,72 @@ async fn interaction_event(
|
||||||
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
match event {
|
match event {
|
||||||
SlackInteractionEvent::ViewSubmission(slack_interaction_view_submission_event) => {
|
SlackInteractionEvent::ViewSubmission(slack_interaction_view_submission_event) => {
|
||||||
match slack_interaction_view_submission_event.view.view {
|
handle_view_submission(slack_interaction_view_submission_event, client, states).await
|
||||||
SlackView::Home(view) => {
|
}
|
||||||
debug!(?view, "Received home view");
|
SlackInteractionEvent::Shortcut(shortcut) => {
|
||||||
Ok(())
|
debug!(?shortcut, "Received shortcut event");
|
||||||
}
|
todo!()
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
event => {
|
event => {
|
||||||
debug!("Received interaction event: {:#?}", event);
|
debug!(?event, "Received interaction event",);
|
||||||
Ok(())
|
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(
|
async fn handle_modal_view(
|
||||||
client: Arc<SlackHyperClient>,
|
client: Arc<SlackHyperClient>,
|
||||||
|
view: SlackModalView,
|
||||||
view_state: SlackViewState,
|
view_state: SlackViewState,
|
||||||
user_state: &user::State,
|
states: SlackClientEventsUserState,
|
||||||
user_id: user::Id<Trusted>,
|
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 {
|
match external_id {
|
||||||
None => {
|
None => {
|
||||||
error!(
|
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?"
|
"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") => {
|
Some("create_member") => {
|
||||||
debug!("Received create member modal view");
|
debug!("Received create member modal view");
|
||||||
|
|
||||||
create_member(view_state, &client, user_state, user_id).await?;
|
if let Err(error) =
|
||||||
|
create_member(view_state, &client, user_state, user_id.clone()).await
|
||||||
Ok(())
|
{
|
||||||
|
handle_user_error(error, user_id.into(), client).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(id) if id.starts_with("edit_member_") => {
|
Some(id) if id.starts_with("edit_member_") => {
|
||||||
debug!("Received edit member modal view");
|
debug!("Received edit member modal view");
|
||||||
|
|
@ -111,22 +115,31 @@ async fn handle_modal_view(
|
||||||
id,
|
id,
|
||||||
"Failed to parse member id from external id. Bailing in case this was a malicious call",
|
"Failed to parse member id from external id. Bailing in case this was a malicious call",
|
||||||
);
|
);
|
||||||
return Ok(());
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(trusted_member_id) =
|
// TO-DO: better handling of Err case
|
||||||
member_id.validate_by_user(&user_id, &user_state.db).await?
|
let Ok(Some(trusted_member_id)) =
|
||||||
|
member_id.validate_by_user(&user_id, &user_state.db).await
|
||||||
else {
|
else {
|
||||||
error!(
|
error!(
|
||||||
id,
|
id,
|
||||||
"Failed to validate member id from external id. Bailing in case this was a malicious call",
|
"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?;
|
if let Err(error) = edit_member(
|
||||||
|
view_state,
|
||||||
Ok(())
|
&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_") => {
|
Some(id) if id.starts_with("create_trigger_") => {
|
||||||
debug!("Creating trigger");
|
debug!("Creating trigger");
|
||||||
|
|
@ -138,18 +151,28 @@ async fn handle_modal_view(
|
||||||
.map(models::member::Id::new)
|
.map(models::member::Id::new)
|
||||||
.expect("Failed to parse member id from external id");
|
.expect("Failed to parse member id from external id");
|
||||||
|
|
||||||
let Some(trusted_member_id) =
|
// TO-DO: Better handling of Err case
|
||||||
member_id.validate_by_user(&user_id, &user_state.db).await?
|
let Ok(Some(trusted_member_id)) =
|
||||||
|
member_id.validate_by_user(&user_id, &user_state.db).await
|
||||||
else {
|
else {
|
||||||
error!(
|
error!(
|
||||||
id,
|
id,
|
||||||
"Failed to validate member id from external id. Bailing in case this was a malicious call",
|
"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?;
|
if let Err(error) = create_trigger(
|
||||||
Ok(())
|
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_") => {
|
Some(id) if id.starts_with("edit_trigger_") => {
|
||||||
debug!("Editing trigger");
|
debug!("Editing trigger");
|
||||||
|
|
@ -170,7 +193,7 @@ async fn handle_modal_view(
|
||||||
%user_id,
|
%user_id,
|
||||||
"Failed to fetch system id for user id. Bailing in case this was a malicious call"
|
"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
|
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",
|
"Failed to validate member id from external id {}. Bailing in case this was a malicious call",
|
||||||
id
|
id
|
||||||
);
|
);
|
||||||
return Ok(());
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
edit_trigger(view_state, &client, user_state, user_id, trusted_trigger_id).await?;
|
if let Err(error) = edit_trigger(
|
||||||
Ok(())
|
view_state,
|
||||||
|
&client,
|
||||||
|
user_state,
|
||||||
|
user_id.clone(),
|
||||||
|
trusted_trigger_id,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
handle_user_error(error, user_id.into(), client.clone()).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(id) => {
|
Some(id) => {
|
||||||
error!("receieved unknown external id: {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