asimov-apify-module 0.1.0

ASIMOV module for data import powered by the Apify web automation platform.
Documentation
// This is free and unencumbered software released into the public domain.

#[cfg(feature = "std")]
fn main() -> Result<clientele::SysexitsError, Box<dyn std::error::Error>> {
    use asimov_apify_module::{api::*, find_actor_for, jq};
    use asimov_module::getenv;
    use clientele::SysexitsError::*;
    use std::io::stdout;

    // Load environment variables from `.env`:
    clientele::dotenv().ok();

    // Expand wildcards and @argfiles:
    let args = clientele::args_os()?;

    // Configure logging:
    #[cfg(feature = "tracing")]
    tracing_subscriber::fmt()
        .with_writer(std::io::stderr)
        .with_max_level(tracing_subscriber::filter::LevelFilter::WARN)
        .init();

    // Parse URLs from command-line arguments:
    let urls: Vec<String> = args
        .iter()
        .skip(1)
        .map(|arg| arg.to_string_lossy().into())
        .collect();
    if urls.is_empty() {
        return Ok(EX_OK);
    }

    // Obtain the Apify API token from the environment:
    let Some(api_key) = getenv::var_secret("APIFY_TOKEN") else {
        return Ok(EX_CONFIG); // not configured
    };
    let api = Apify::new(api_key);

    // Process each of the given URL arguments:
    for url in urls {
        // Find the appropriate actor based on the URL prefix:
        let Some(actor) = find_actor_for(&url) else {
            return Ok(EX_UNAVAILABLE); // not supported
        };

        // Send the request and block while waiting for the response:
        let response = match actor.id {
            "apify~google-search-scraper" => jq::google_search()
                .filter_json_str(api.google_search(&url.parse().map_err(|_| EX_DATAERR)?)?)?,
            "C2Wk3I6xAqC4Xi63f" => jq::x_follows()
                .filter_json_str(api.x_follows(&url.parse().map_err(|_| EX_DATAERR)?)?)?,
            _ => {
                return Ok(EX_UNAVAILABLE); // not supported
            }
        };

        // Serialize the response data:
        if cfg!(feature = "pretty") {
            colored_json::write_colored_json(&response, &mut stdout())?;
            println!();
        } else {
            println!("{}", serde_json::to_string(&response).unwrap());
        }
    }

    Ok(EX_OK)
}

#[cfg(not(feature = "std"))]
fn main() {
    unimplemented!("asimov-apify-importer requires the 'std' feature")
}