sfr_server/handler/
slash_command.rs1use 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
12pub trait SlashCommandHandlerTrait: Send + Sync {
14 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#[derive(Clone)]
24pub(crate) struct SlashCommandHandler<T>(T)
25where
26 T: SlashCommandHandlerTrait;
27
28impl<T> SlashCommandHandler<T>
29where
30 T: SlashCommandHandlerTrait,
31{
32 pub fn new(inner: T) -> Self {
34 Self(inner)
35 }
36
37 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}