use sfr_core as sc;
use sfr_server as ss;
use sfr_slack_api as ssa;
use sfr_types as st;
use derive_new::new;
use sc::{OauthV2AccessResponse, Slack, SlashCommandBody};
use ss::{
HomeHandlerTrait, OauthHandlerTrait, OauthRedirectResponse, ResponseError, Server,
SlashCommandHandlerTrait,
};
use ssa::Client;
use std::env;
#[tokio::main]
async fn main() -> Result<(), st::Error> {
let args: Vec<String> = env::args().collect();
let sock = args.get(1).unwrap();
let url_prefix = env::var("SSCT_URL_PREFIX").unwrap();
let id = env::var("SSCT_SLACK_ID").unwrap();
let secret = env::var("SSCT_SLACK_SECRET").unwrap();
let signing_secret = env::var("SSCT_SLACK_SIGNING_SECRET").unwrap();
let verification_token = env::var("SSCT_SLACK_VERIFICATION_TOKEN").unwrap();
let oauth_token = env::var("SSCT_SLACK_OAUTH_TOKEN").unwrap();
let log = env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string());
let server_config = ss::Config::builder()
.sock(sock.parse().unwrap())
.log(Some(log))
.build();
let slack_creds = sc::AppCredentials {
id,
secret,
signing_secret,
verification_token,
};
let slack_config = sc::Config {
timestamp_range: 300,
};
let slack = Slack::new(slack_creds, slack_config);
let client = reqwest::Client::new();
let dummy = DummyHandler;
let handler = Handler::new(url_prefix);
let oauth_handler = OauthHandler::new(oauth_token);
let server = Server::new(server_config, slack, client, dummy, handler, oauth_handler);
server.serve().await
}
#[derive(new)]
struct Handler {
url_prefix: String,
}
#[derive(new)]
struct OauthHandler {
token: String,
}
struct DummyHandler;
impl SlashCommandHandlerTrait for Handler {
async fn handle_slash_command(
&self,
client: &Client,
_body: SlashCommandBody,
) -> Result<st::SlashCommandResponse, ResponseError> {
let external_id = uuid::Uuid::new_v4().to_string();
let external_url = format!("{}/remote/loop1.wav", self.url_prefix);
tracing::debug!("external_id: {}", external_id);
tracing::debug!("external_url: {}", external_url);
let request_body = ssa::RequestBuilder::files_remote_add()
.external_id(external_id.clone())
.external_url(external_url)
.title("audio".to_string())
.build()
.inspect_err(|e| {
tracing::error!("failed to build api object: {e}");
})
.map_err(|e| ResponseError::InternalServerError(Box::new(e)))?;
tracing::debug!("request_body: {:?}", request_body);
let response_body = client
.request(request_body)
.await
.inspect_err(|e| tracing::error!("failed to request: {e}"))
.map_err(|e| ResponseError::InternalServerError(Box::new(e)))?;
tracing::info!("requested: {response_body:?}");
let message = st::MessagePayloads {
text: "loop1.wav".to_string(),
blocks: vec![st::Block::File(st::FileBlock::new(st::ExternalId(
external_id,
)))],
attachments: vec![],
thread_ts: None,
mrkdwn: None,
};
let layouts = st::Layouts::BlocksArray(message);
let resp = st::SlashCommandResponse::Layouts(layouts);
Ok(resp.into())
}
}
impl OauthHandlerTrait for OauthHandler {
async fn handle_oauth(
&self,
_client: reqwest::Client,
body: OauthV2AccessResponse,
) -> Result<Option<OauthRedirectResponse>, ResponseError> {
tracing::info!("body: {body:?}");
Ok(None)
}
async fn take_oauth_token_from_team_id(&self, _team_id: &str) -> Result<String, ResponseError> {
Ok(self.token.clone())
}
fn redirect_uri(&self) -> &str {
unimplemented!()
}
}
impl HomeHandlerTrait for DummyHandler {
async fn handle_home(&self) -> Result<Vec<u8>, ResponseError> {
const RESPONSE: &str = r#"<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title></title></head><body>ok</body></html>"#;
Ok(RESPONSE.into())
}
}