sfr_server/handler/
slash_command.rs

1//! The trait representing the interface that acts as a slash command.
2
3use sfr_core as sc;
4use sfr_slack_api as ssa;
5use sfr_types as st;
6
7use crate::handler::oauth::{OauthHandler, OauthHandlerTrait};
8use crate::{ResponseError, SlashCommandResponse};
9use sc::SlashCommandBody;
10use ssa::Client as SlackClient;
11
12/// The trait representing the interface that acts as a slash command.
13pub trait SlashCommandHandlerTrait: Send + Sync {
14    /// Handles [`SlashCommandBody`].
15    fn handle_slash_command(
16        &self,
17        client: &SlackClient,
18        body: SlashCommandBody,
19    ) -> impl std::future::Future<Output = Result<st::SlashCommandResponse, ResponseError>> + Send;
20}
21
22/// The new type to wrap [`SlashCommandHandlerTrait`].
23#[derive(Clone)]
24pub(crate) struct SlashCommandHandler<T>(T)
25where
26    T: SlashCommandHandlerTrait;
27
28impl<T> SlashCommandHandler<T>
29where
30    T: SlashCommandHandlerTrait,
31{
32    /// The constructor.
33    pub fn new(inner: T) -> Self {
34        Self(inner)
35    }
36
37    /// The wrapper function for a slash command.
38    pub fn handle<'a, OH>(
39        &'a self,
40        client: reqwest::Client,
41        oauth: &'a OauthHandler<OH>,
42        body: SlashCommandBody,
43    ) -> impl std::future::Future<Output = Result<impl axum::response::IntoResponse, ResponseError>>
44           + Send
45           + 'a
46    where
47        OH: OauthHandlerTrait,
48    {
49        tracing::info!("slash command: start to process");
50
51        async move {
52            let token = oauth.take_oauth_token_from_team_id(&body.team_id).await?;
53            let client = SlackClient::new(client, token);
54
55            let resp: SlashCommandResponse =
56                self.0.handle_slash_command(&client, body).await?.into();
57            Ok(resp)
58        }
59    }
60}
61
62impl<T> std::ops::Deref for SlashCommandHandler<T>
63where
64    T: SlashCommandHandlerTrait,
65{
66    type Target = T;
67
68    fn deref(&self) -> &Self::Target {
69        &self.0
70    }
71}