use google_drive3::api::File;
use http_body_util::BodyExt;
use crate::client::DriveClient;
use crate::error::{GDriveError, Result};
pub const MIME_GOOGLE_DOC: &str = "application/vnd.google-apps.document";
pub const MIME_GOOGLE_SHEET: &str = "application/vnd.google-apps.spreadsheet";
pub const MIME_GOOGLE_SLIDES: &str = "application/vnd.google-apps.presentation";
pub const MIME_GOOGLE_DRAWING: &str = "application/vnd.google-apps.drawing";
pub const MIME_GOOGLE_FORM: &str = "application/vnd.google-apps.form";
pub const MIME_GOOGLE_SCRIPT: &str = "application/vnd.google-apps.script";
pub const MIME_FOLDER: &str = "application/vnd.google-apps.folder";
pub fn is_google_workspace_type(mime_type: &str) -> bool {
matches!(
mime_type,
MIME_GOOGLE_DOC
| MIME_GOOGLE_SHEET
| MIME_GOOGLE_SLIDES
| MIME_GOOGLE_DRAWING
| MIME_GOOGLE_FORM
| MIME_GOOGLE_SCRIPT
)
}
pub fn default_export_mime(workspace_mime: &str) -> Option<&'static str> {
match workspace_mime {
MIME_GOOGLE_DOC => Some("text/markdown"),
MIME_GOOGLE_SHEET => Some("text/csv"),
MIME_GOOGLE_SLIDES => Some("text/plain"),
MIME_GOOGLE_DRAWING => Some("image/png"),
MIME_GOOGLE_FORM => Some("text/plain"),
MIME_GOOGLE_SCRIPT => Some("application/vnd.google-apps.script+json"),
_ => None,
}
}
pub async fn export_as_text(
client: &DriveClient,
file_id: &str,
export_mime: &str,
) -> Result<String> {
let response = client
.hub()
.files()
.export(file_id, export_mime)
.doit()
.await
.map_err(GDriveError::DriveApi)?;
read_body_as_text(response).await
}
pub async fn export_as_bytes(
client: &DriveClient,
file_id: &str,
export_mime: &str,
) -> Result<Vec<u8>> {
let response = client
.hub()
.files()
.export(file_id, export_mime)
.doit()
.await
.map_err(GDriveError::DriveApi)?;
read_body_as_bytes(response).await
}
pub async fn download_as_text(client: &DriveClient, file_id: &str) -> Result<String> {
let (response, _) = client
.hub()
.files()
.get(file_id)
.param("alt", "media")
.doit()
.await
.map_err(GDriveError::DriveApi)?;
read_body_as_text(response).await
}
pub async fn download_as_bytes(client: &DriveClient, file_id: &str) -> Result<Vec<u8>> {
let (response, _) = client
.hub()
.files()
.get(file_id)
.param("alt", "media")
.doit()
.await
.map_err(GDriveError::DriveApi)?;
read_body_as_bytes(response).await
}
async fn read_body_as_text(response: google_drive3::common::Response) -> Result<String> {
let bytes = read_body_as_bytes(response).await?;
String::from_utf8(bytes)
.map_err(|e| GDriveError::Other(format!("Response body is not valid UTF-8: {e}")))
}
async fn read_body_as_bytes(response: google_drive3::common::Response) -> Result<Vec<u8>> {
let body = response.into_body();
let bytes = body
.collect()
.await
.map_err(|e| GDriveError::HttpBody(format!("Failed to read response body: {e}")))?
.to_bytes();
Ok(bytes.to_vec())
}
pub fn file_summary(file: &File) -> String {
let name = file.name.as_deref().unwrap_or("(unnamed)");
let id = file.id.as_deref().unwrap_or("(no id)");
let mime = file.mime_type.as_deref().unwrap_or("unknown");
format!("{name} (id: {id}, type: {mime})")
}
pub fn files_summary(files: &[File]) -> String {
if files.is_empty() {
return "No files found.".to_string();
}
files
.iter()
.map(file_summary)
.collect::<Vec<_>>()
.join("\n")
}