clipboard-gdrive 0.1.0

A command-line tool to interact with Google Drive and system clipboard
use arboard::Clipboard;
use image::{ImageBuffer, ImageOutputFormat, RgbaImage};
use std::{
    env::temp_dir,
    fs::File,
    io::{BufWriter, Write},
    process::{exit, Command},
    time::{Instant, SystemTime},
};

const FOLDER_NAME: &str = "clipboard-gdrive";

fn main() {
    let mut clipboard = Clipboard::new().unwrap();

    let text = clipboard.get_text();
    let image = clipboard.get_image();

    if text.is_ok() {
        eprintln!("Not implemented yet");
        exit(1);
    } else if image.is_ok() {
        let s = Instant::now();

        let cur_timestamp = SystemTime::now()
            .duration_since(SystemTime::UNIX_EPOCH)
            .unwrap()
            .as_millis();

        let temp_path = temp_dir()
            .join("clipboard_google_drive")
            .with_file_name(&cur_timestamp.to_string())
            .with_extension("png");
        let temp_file = File::create(&temp_path).unwrap();
        let image_data = image.unwrap();

        let image: RgbaImage = ImageBuffer::from_raw(
            image_data.width.try_into().unwrap(),
            image_data.height.try_into().unwrap(),
            image_data.bytes.into_owned(),
        )
        .unwrap();

        let mut writer = BufWriter::new(temp_file);

        image.write_to(&mut writer, ImageOutputFormat::Png).unwrap();
        writer.flush().unwrap();
        println!("Image file saved;elapsed={:?}", s.elapsed());

        let s = Instant::now();
        let upload = Command::new("gdrive")
            .args([
                "upload",
                "--delete",
                "--share",
                "--parent",
                &get_parent_id(),
                "--name",
                &format!(
                    "{}.{}",
                    &cur_timestamp.to_string(),
                    &temp_path.extension().unwrap().to_str().unwrap()
                ),
                temp_path.to_str().unwrap(),
            ])
            .output()
            .expect("Failed to upload to Google Drive");

        let mut shared_link: String = String::from("");
        for line in String::from_utf8(upload.stdout.to_vec()).unwrap().lines() {
            if !line.starts_with("File is readable by anyone at") {
                continue;
            }

            let chunks: Vec<&str> = line.split(" ").collect();
            shared_link = chunks.last().unwrap().to_string();
        }

        shared_link = shared_link.replace("export=download", "export=view");
        println!(
            "Image file uploaded;shared_link={:?},elapsed={:?}",
            shared_link,
            s.elapsed()
        );
        clipboard.set_text(&shared_link).expect(&format!(
            "Failed to set file URI to clipboard;{}",
            &shared_link
        ));
    } else {
        eprintln!("Clipboard failure");
        exit(1);
    }
}

fn get_parent_id() -> String {
    let output = Command::new("gdrive")
        .args([
            "list",
            "--no-header",
            "--query",
            &format!("name = '{}'", FOLDER_NAME,),
        ])
        .output()
        .expect("Failed to find folder id");

    let entry = String::from_utf8(output.stdout.to_vec()).unwrap();
    let chunks: Vec<&str> = entry.split(" ").collect();
    return chunks
        .first()
        .expect(&format!("Failed to find folder;expected={FOLDER_NAME}"))
        .to_string();
}