Skip to main content

made_client/
reports.rs

1use std::path::Path;
2
3use made_proto::v1::{GenerateCeremonyReportRequest, GenerateCeremonyReportResponse};
4use tokio::io::AsyncWriteExt;
5use uuid::Uuid;
6
7use crate::{MadeClient, MadeClientError};
8
9impl MadeClient {
10    pub async fn generate_report(
11        &self,
12        ceremony_ids: Vec<String>,
13        title: impl Into<String>,
14    ) -> Result<GenerateCeremonyReportResponse, MadeClientError> {
15        self.rpc()
16            .generate_ceremony_report(Self::request(
17                &self.context(),
18                "/underpass.made.v1.MadeService/GenerateCeremonyReport",
19                GenerateCeremonyReportRequest {
20                    ceremony_ids,
21                    title: title.into(),
22                },
23            ))
24            .await
25            .map(tonic::Response::into_inner)
26            .map_err(MadeClientError::from_status)
27    }
28
29    pub async fn export_report(
30        &self,
31        ceremony_ids: Vec<String>,
32        title: impl Into<String>,
33        destination: &Path,
34    ) -> Result<GenerateCeremonyReportResponse, MadeClientError> {
35        let report = self.generate_report(ceremony_ids, title).await?;
36        let parent = destination.parent().unwrap_or_else(|| Path::new("."));
37        tokio::fs::create_dir_all(parent)
38            .await
39            .map_err(|error| MadeClientError::io(parent, error))?;
40        let name = destination
41            .file_name()
42            .and_then(|name| name.to_str())
43            .unwrap_or("report.md");
44        let temporary = parent.join(format!(".{name}.{}.part", Uuid::new_v4()));
45        let result = async {
46            let mut file = tokio::fs::File::create(&temporary)
47                .await
48                .map_err(|error| MadeClientError::io(&temporary, error))?;
49            file.write_all(report.report_markdown.as_bytes())
50                .await
51                .map_err(|error| MadeClientError::io(&temporary, error))?;
52            file.sync_all()
53                .await
54                .map_err(|error| MadeClientError::io(&temporary, error))?;
55            drop(file);
56            tokio::fs::rename(&temporary, destination)
57                .await
58                .map_err(|error| MadeClientError::io(destination, error))
59        }
60        .await;
61        if result.is_err() {
62            let _ = tokio::fs::remove_file(&temporary).await;
63        }
64        result.map(|()| report)
65    }
66}