slack-framework-rs 0.1.2

`slack-framework-rs` is the library that [the author](https://gitlab.com/nogiro) uses to create the Slack App.
Documentation
use sfr_core as sc;
use sfr_server as ss;
use sfr_slack_api as ssa;
use sfr_types as st;

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 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 redirect_uri = env::var("SSCT_SLACK_REDIRECT_URI").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 oauth_handler = OauthHandler {
        token: None,
        redirect_uri,
    };

    let server = Server::new(
        server_config,
        slack,
        client,
        Handler,
        Handler,
        oauth_handler,
    );
    server.serve().await
}

struct Handler;

struct OauthHandler {
    token: Option<String>,
    redirect_uri: String,
}

impl SlashCommandHandlerTrait for Handler {
    async fn handle_slash_command(
        &self,
        _client: &Client,
        body: SlashCommandBody,
    ) -> Result<st::SlashCommandResponse, ResponseError> {
        tracing::info!("body: {:?}", body);

        Ok(st::SlashCommandResponse::empty().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> {
        self.token.clone().ok_or(ResponseError::Unknown)
    }

    fn redirect_uri(&self) -> &str {
        self.redirect_uri.as_str()
    }
}

impl HomeHandlerTrait for Handler {
    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())
    }
}